EventCache Contract¶
Why this page exists
This page is the implementation contract for the central state engine. If you need to reason about event lifecycle, optimistic updates, rollback, publish behavior, or cache ownership, start here.
Role in the architecture¶
EventCache is the single runtime authority for event state. It does not directly parse files or call remote APIs; it delegates source I/O to ProviderRegistry, stores normalized events in EventStore, and broadcasts deterministic updates to UI and feature subscribers.
Responsibilities¶
| Responsibility | Component / Practical behavior |
|---|---|
| Staged population | CacheSyncHandler: Calls ProviderRegistry.fetchAllByPriority() and progressively syncs provider results. |
| State ownership | EventCache & EventStore: Persists canonical event state and exposes query APIs for views/features. |
| Mutation orchestration | CacheMutationHandler: Executes optimistic add/update/delete, then commits or rolls back based on provider result (e.g., Tasks Optimistic Flow). |
| Publish/subscribe hub | CacheSubscriptionManager: Emits update payloads (events, calendar, resync) and time-tick state for reminder/time UI flows. |
| Identifier bridge | EventCache: Uses ProviderRegistry to map persistent provider identifiers to session IDs used by the UI. |
Mutation lifecycle (authoritative path)¶
- UI action calls a cache mutation API (
addEvent,updateEventWithId,deleteEventWithId). - Cache performs optimistic in-memory state update in
EventStore. - Cache flushes an update payload to subscribers for immediate UX response.
- Cache delegates durable write to the owning provider via
ProviderRegistry. - Success path replaces optimistic state with provider-authoritative result; failure path rolls back and republishes correction.
Delegated provider action exception path¶
Some providers intentionally hand off creation/edit UX to native integration UI instead of returning a created entity immediately.
- Signal: provider throws
DelegatedProviderActionError. - Cache behavior: roll back optimistic placeholder state.
- UX behavior: do not show generic create-failed notice.
This contract allows provider-owned UI flows (for example TaskNotes NLP handoff) without polluting dispatcher logic with provider-specific branches.
Recurring instance state path (provider-agnostic)¶
Recurring-instance status operations (complete/skip for a single occurrence) use a normalized contract rather than provider-type branching.
Flow:
- UI interaction identifies a recurring instance date.
- Interaction layer asks the owning provider for normalized instance state (
RecurringInstanceStateProvider.getRecurringInstanceState). - UI submits desired normalized state (
setRecurringInstanceState) back to the provider. - Provider performs backend-native persistence and emits/propagates cache refresh updates through existing provider update channels.
Invariants:
- Core/UI never inspect backend-specific recurring fields.
- Provider implementations own translation from normalized state to backend semantics.
- Providers that do not implement this optional interface keep existing fallback behavior.
Invariant
No subsystem should mutate persistent event state outside EventCache. Direct provider-to-UI mutation paths are architectural violations.
Subscription contract¶
update: event-level or calendar-level changes for rendering/sync.time-tick: high-frequency temporal state for reminders and now-indicator style behavior.
Consumers should subscribe/unsubscribe cleanly and must handle batched updates instead of assuming one-event-at-a-time delivery.
Integration anchors¶
src/core/EventCache.tssrc/core/EventStore.tssrc/core/cache/CacheMutationHandler.tssrc/core/cache/CacheSubscriptionManager.tssrc/core/cache/CacheSyncHandler.tssrc/providers/ProviderRegistry.tssrc/core/TimeEngine.tssrc/ui/view.ts