Poll for Completion
User Intent
"I want to know when a feed has finished its initial sync"
Operation
SDK Method:
graphlit.isFeedDone()GraphQL:
isFeedDonequeryEntity Type: Feed
Common Use Cases: Wait for initial feed sync, verify feed completion before querying content
TypeScript (Canonical)
import { Graphlit } from 'graphlit-client';
const graphlit = new Graphlit();
// After creating a feed
const feedResponse = await graphlit.createFeed(feedInput);
const feedId = feedResponse.createFeed.id;
console.log(`Feed created: ${feedId}`);
// Poll for completion
const maxAttempts = 60; // 10 minutes max (60 * 10 seconds)
for (let attempts = 1; attempts <= maxAttempts; attempts++) {
const status = await graphlit.isFeedDone(feedId);
if (status.isFeedDone.result) {
console.log('Feed sync complete!');
const contents = await graphlit.queryContents({
feeds: [{ id: feedId }],
});
console.log(`Synced ${contents.contents.results.length} items`);
return;
}
console.log(`Still syncing... (${attempts}/${maxAttempts})`);
await new Promise((resolve) => setTimeout(resolve, 10_000));
}
console.log('Feed sync timeout - still processing');Python:
feed_response = await graphlit.create_feed(feed_input)
feed_id = feed_response.createFeed.id
is_done = False
attempts = 0
max_attempts = 60
while not is_done and attempts < max_attempts:
status = await graphlit.isFeedDone(feed_id)
is_done = status.isFeedDone.result if status.isFeedDone else False
if not is_done:
attempts += 1
print(f"Still syncing... ({attempts}/{max_attempts})")
await asyncio.sleep(10)
if is_done:
print("Feed sync complete!")C#:
using Graphlit;
using System.Threading.Tasks;
var graphlit = new Graphlit();
var feedResponse = await graphlit.CreateFeed(feedInput);
var feedId = feedResponse.CreateFeed.Id;
// Poll for completion (PascalCase)
bool isDone = false;
int attempts = 0;
int maxAttempts = 60;
while (!isDone && attempts < maxAttempts)
{
var status = await graphlit.IsFeedDone(feedId);
isDone = status.IsFeedDone?.Result ?? false;
if (!isDone)
{
attempts++;
Console.WriteLine($"Still syncing... ({attempts}/{maxAttempts})");
await Task.Delay(10000); // Wait 10 seconds
}
}
if (isDone)
{
Console.WriteLine("Feed sync complete!");
}Parameters
Required
id(string): Feed ID to check
Response
{
isFeedDone: {
result: boolean; // true = sync complete, false = still syncing
}
}Developer Hints
Only for Initial Sync
isFeedDone() indicates initial sync completion, not ongoing monitoring:
// After feed creation
const feed = await graphlit.createFeed(feedInput);
// isFeedDone checks initial sync
await waitUntilFeedDone(feed.createFeed.id);
// After initial sync, feed continues to monitor for new content
// You don't need to call isFeedDone againImportant: Once initial sync completes, the feed continuously monitors for new content automatically.
Recommended Polling Interval
// Too frequent (wasteful)
await new Promise(resolve => setTimeout(resolve, 1000)); // Every 1 second
// Good balance
await new Promise(resolve => setTimeout(resolve, 10000)); // Every 10 seconds
// For very large feeds
await new Promise(resolve => setTimeout(resolve, 30000)); // Every 30 secondsWhy 10 seconds?: Balance between responsiveness and API efficiency. Initial feed syncs typically take 1-10 minutes depending on content volume.
🕐 Timeout Considerations
// Typical sync times by feed type
const timeouts = {
rss: 2 minutes, // Small: 10-100 items
slack: 5 minutes, // Medium: 100s-1000s of messages
googleDrive: 10 minutes, // Large: Many files
web: 15 minutes // Very large: Deep crawls
};
// Adjust maxAttempts based on feed type
const maxAttempts = feedType === 'rss' ? 12 : 60; // 2 min vs 10 minHelper Function Pattern
async function waitForFeedCompletion(
feedId: string,
timeoutMinutes: number = 10,
pollIntervalSeconds: number = 10
): Promise<boolean> {
const maxAttempts = (timeoutMinutes * 60) / pollIntervalSeconds;
let attempts = 0;
while (attempts < maxAttempts) {
const status = await graphlit.isFeedDone(feedId);
if (status.isFeedDone.result) {
return true; // Success
}
attempts++;
await new Promise(resolve => setTimeout(resolve, pollIntervalSeconds * 1000));
}
return false; // Timeout
}
// Usage
const completed = await waitForFeedCompletion(feedId, 10, 10);
if (completed) {
console.log('Ready to query content');
} else {
console.log('Timeout - feed still processing');
}Variations
1. Basic Polling with Progress
Simple polling with progress updates:
async function pollFeedWithProgress(feedId: string) {
console.log('Waiting for feed sync to complete...');
let isDone = false;
let attempts = 0;
while (!isDone && attempts < 60) {
const status = await graphlit.isFeedDone(feedId);
isDone = status.isFeedDone.result || false;
if (!isDone) {
attempts++;
const elapsed = attempts * 10; // seconds
console.log(`⏳ ${elapsed}s elapsed...`);
await new Promise(resolve => setTimeout(resolve, 10000));
}
}
console.log(isDone ? ' Complete!' : '⏰ Timeout');
return isDone;
}2. Polling with Content Count Tracking
Track synced content during polling:
async function pollWithContentTracking(feedId: string) {
let isDone = false;
let previousCount = 0;
while (!isDone) {
const status = await graphlit.isFeedDone(feedId);
isDone = status.isFeedDone.result || false;
// Check how many items synced so far
const contents = await graphlit.queryContents({
feeds: [{ id: feedId }],
limit: 1 // Just get count, not all items
});
const currentCount = contents.contents.results.length;
if (currentCount > previousCount) {
console.log(`📥 Synced ${currentCount} items so far...`);
previousCount = currentCount;
}
if (!isDone) {
await new Promise(resolve => setTimeout(resolve, 10000));
}
}
console.log(` Sync complete! Total: ${previousCount} items`);
}3. Parallel Feed Polling
Poll multiple feeds simultaneously:
async function pollMultipleFeeds(feedIds: string[]) {
const pollPromises = feedIds.map(async (feedId) => {
let isDone = false;
while (!isDone) {
const status = await graphlit.isFeedDone(feedId);
isDone = status.isFeedDone.result || false;
if (!isDone) {
await new Promise(resolve => setTimeout(resolve, 10000));
}
}
return feedId;
});
// Wait for all feeds to complete
const completedFeeds = await Promise.all(pollPromises);
console.log(`All ${completedFeeds.length} feeds synced!`);
return completedFeeds;
}
// Usage
const feedIds = [feed1Id, feed2Id, feed3Id];
await pollMultipleFeeds(feedIds);4. Exponential Backoff Polling
Reduce API calls with backoff:
async function pollWithBackoff(feedId: string) {
let isDone = false;
let interval = 5000; // Start at 5 seconds
const maxInterval = 60000; // Max 60 seconds
while (!isDone) {
const status = await graphlit.isFeedDone(feedId);
isDone = status.isFeedDone.result || false;
if (!isDone) {
console.log(`Waiting ${interval / 1000}s before next check...`);
await new Promise(resolve => setTimeout(resolve, interval));
// Exponential backoff
interval = Math.min(interval * 1.5, maxInterval);
}
}
console.log('Feed sync complete!');
}5. Polling with Timeout Promise
Use Promise.race for cleaner timeout:
async function pollWithTimeout(
feedId: string,
timeoutMs: number = 600000 // 10 minutes
): Promise<boolean> {
const pollPromise = (async () => {
let isDone = false;
while (!isDone) {
const status = await graphlit.isFeedDone(feedId);
isDone = status.isFeedDone.result || false;
if (!isDone) {
await new Promise(resolve => setTimeout(resolve, 10000));
}
}
return true;
})();
const timeoutPromise = new Promise<boolean>((resolve) => {
setTimeout(() => resolve(false), timeoutMs);
});
const completed = await Promise.race([pollPromise, timeoutPromise]);
if (!completed) {
console.log('⏰ Feed sync timeout');
}
return completed;
}6. Query Content After Completion
Complete workflow from feed creation to content query:
// Create feed
const feedResponse = await graphlit.createFeed({
name: 'News RSS',
type: FeedTypes.Rss,
rss: {
uri: 'https://news.example.com/rss'
}
});
const feedId = feedResponse.createFeed.id;
// Wait for sync
const completed = await waitForFeedCompletion(feedId);
if (completed) {
// Query synced content
const contents = await graphlit.queryContents({
feeds: [{ id: feedId }],
orderBy: OrderByTypes.CreationDate,
orderDirection: OrderDirectionTypes.Desc,
limit: 10
});
console.log('Latest synced items:');
contents.contents.results.forEach((item, index) => {
console.log(`${index + 1}. ${item.name}`);
});
}Common Issues
Issue: isFeedDone() always returns false
Solution: Feed may be stuck. Check feed state with getFeed(). Look for error state.
Issue: Polling times out but feed has content Solution: Feed may be partially synced but not "done". Increase timeout or query content anyway.
Issue: Feed not found error
Solution: Verify feed ID is correct. Check that feed wasn't deleted.
Issue: Feed completes immediately (no content synced) Solution: Check feed configuration. May have OAuth token issues or incorrect settings.
Issue: Memory leak from long polling Solution: Ensure you have proper timeout/max attempts. Don't poll indefinitely.
Production Example
Poll helper function:
async function waitForFeed(feedId: string, maxMinutes: number = 10): Promise<boolean> {
const maxAttempts = maxMinutes * 6; // 6 checks per minute (10s intervals)
let attempts = 0;
while (attempts < maxAttempts) {
const status = await graphlit.isFeedDone(feedId);
if (status.isFeedDone.result) {
return true;
}
attempts++;
await new Promise(resolve => setTimeout(resolve, 10000));
}
return false;
}
// Usage
const feedId = response.createFeed.id;
const success = await waitForFeed(feedId, 10);
if (success) {
const contents = await graphlit.queryContents({ feeds: [{ id: feedId }] });
console.log(`Synced ${contents.contents.results.length} items`);
}Last updated
Was this helpful?