Concurrency model for Notifications and Blobs is unclear

The notification arrives before the local node/client has finished syncing, indexing, or resolving the blob that the notification points to. So the UI treats the notification as actionable, but the target resource is not yet available.

Best fix: make notifications depend on blob availability

A notification should not become clickable as “ready” until the referenced blob is locally available or resolvable.

Possible rule:

A notification is only promoted to the visible/actionable notification feed after its referenced blob has been fetched, verified, and indexed.

Flow:

Receive notification event
↓
Extract referenced blob/document/entity
↓
Check local blob availability
↓
If missing: fetch / subscribe / resolve
↓
Only show as ready when blob exists locally

Until then, it can appear as pending, syncing, or not appear at all.

Option 1: Notification inbox with pending state

Keep the notification, but mark it as unresolved.

UI behavior:

New mention from Alice
Syncing content…

Click behavior:

Content is still syncing. Try again in a moment.

This avoids scary error messages and makes the system feel honest.

Good when you want users to know that something happened immediately, even if the content is not ready yet.

Option 2: Lazy fetch on click

When the user clicks the notification, the client checks whether the blob exists.

If not:

Fetching content…

Then the app tries to retrieve the blob from peers, daemon, gateway, or cache.

Only show an error after a real timeout or confirmed failure.

Pseudo-flow:

onNotificationClick(notification):
  target = notification.blobId

  if blobStore.has(target):
    open(target)
  else:
    showLoading("Fetching content…")
    result = await blobStore.fetch(target)

    if result.ok:
      open(target)
    else:
      showRecoverableError("Content is not available yet")

This is probably the fastest product fix because it does not require delaying notifications.

Option 3: Bundle enough data in the notification

If notifications reference a blob that may not exist locally yet, include enough minimal preview data in the notification itself:

notification {
  id
  author
  timestamp
  targetBlobId
  targetDocumentId
  previewText
  dependencyIds
}

Then even if the blob is missing, the UI can show something meaningful:

Alice mentioned you in “Project Notes”
Preview: “Can you review this part…”
Content is still syncing.

This reduces the feeling of brokenness.

Option 4: Dependency-aware sync queue

Treat every notification as a small graph of dependencies.

Before marking it ready, resolve:

notification
 ├─ target document
 ├─ target blob
 ├─ author identity
 └─ conversation/comment context

The daemon or client maintains a queue:

unresolved notifications
↓
missing blobs
↓
fetch priority boost
↓
ready notifications

This is the most architecturally clean fix for Seed, because notifications are not just messages; they are pointers into distributed state.

Option 5: Retry with backoff instead of erroring

The current problem may be that the app checks once, fails, and shows an error.

Better:

Click notification
↓
Blob missing
↓
Retry immediately
↓
Retry after 500ms
↓
Retry after 1s
↓
Retry after 2s
↓
Then show “content unavailable”

The user should almost never see a hard error for a normal sync race.

Option 6: Notification readiness contract

Define a contract between daemon and client:

A notification can be emitted in two states:

1. discovered
   The system knows a notification exists, but dependencies may be missing.

2. ready
   The notification target can be opened safely.

The frontend should only navigate on ready.

Example:

type NotificationState =
  | { status: "discovered"; targetBlobId: string }
  | { status: "resolving"; targetBlobId: string }
  | { status: "ready"; targetBlobId: string; route: string }
  | { status: "unavailable"; targetBlobId: string; reason: string }

This makes concurrency explicit instead of accidental.

My recommendation

Use a combination of lazy fetch on click and pending notification states first.

That gives you a practical fix:

  1. Do not show hard errors when the blob is missing.

  2. On click, try to fetch/resolve the missing blob.

  3. Show “syncing content” while resolving.

  4. Only show “unavailable” after retries or confirmed failure.

  5. Later, improve the daemon so notifications are only marked ready once dependencies are available.

Do you like what you are reading? Subscribe to receive updates.

Unsubscribe anytime