feat(shared-triggers): emit shared events from group services (M2.3)
ServiceEventEmitter gains emit_shared(cx, owning_group, event) (default no-op); OutboxEventEmitter implements it — matches shared triggers on the owning group and writes outbox rows stamped with the WRITER app_id (dispatch runs under the writer). GroupKv/Docs/FilesServiceImpl gain an events field (Noop default + with_events builder) and emit on set/create/update/delete; the host wires the outbox emitter via with_events. Closes the "group trigger has no app to watch" gap. Authoring + validation land in M2.4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -161,21 +161,26 @@ pub async fn build_app(
|
||||
));
|
||||
// §11.6 shared group collections (KV): a separate store keyed by the owning
|
||||
// group, resolved from cx.app_id's chain. Reuses the KV value-size cap.
|
||||
let group_kv: Arc<dyn picloud_shared::GroupKvService> =
|
||||
Arc::new(GroupKvServiceImpl::with_max_value_bytes(
|
||||
let group_kv: Arc<dyn picloud_shared::GroupKvService> = Arc::new(
|
||||
GroupKvServiceImpl::with_max_value_bytes(
|
||||
Arc::new(PostgresGroupKvRepo::new(pool.clone())),
|
||||
Arc::new(PostgresGroupCollectionResolver::new(pool.clone())),
|
||||
authz.clone(),
|
||||
picloud_manager_core::kv_service::kv_max_value_bytes_from_env(),
|
||||
));
|
||||
)
|
||||
// §11.6 shared-collection triggers: fire `shared = true` triggers.
|
||||
.with_events(events.clone()),
|
||||
);
|
||||
// §11.6 shared group collections (docs): group-keyed group_docs store.
|
||||
let group_docs: Arc<dyn picloud_shared::GroupDocsService> =
|
||||
Arc::new(GroupDocsServiceImpl::with_max_value_bytes(
|
||||
let group_docs: Arc<dyn picloud_shared::GroupDocsService> = Arc::new(
|
||||
GroupDocsServiceImpl::with_max_value_bytes(
|
||||
Arc::new(PostgresGroupDocsRepo::new(pool.clone())),
|
||||
Arc::new(PostgresGroupCollectionResolver::new(pool.clone())),
|
||||
authz.clone(),
|
||||
picloud_manager_core::docs_service::docs_max_value_bytes_from_env(),
|
||||
));
|
||||
)
|
||||
.with_events(events.clone()),
|
||||
);
|
||||
let docs: Arc<dyn DocsService> = Arc::new(DocsServiceImpl::with_max_value_bytes(
|
||||
docs_repo,
|
||||
authz.clone(),
|
||||
@@ -216,14 +221,17 @@ pub async fn build_app(
|
||||
));
|
||||
// §11.6 shared group collections (files): group-keyed blobs under
|
||||
// `<root>/files/groups/<group_id>/...`, resolved from cx.app_id's chain.
|
||||
// Shares the per-file size cap; no events (no app to attribute a trigger to).
|
||||
let group_files: Arc<dyn picloud_shared::GroupFilesService> =
|
||||
Arc::new(GroupFilesServiceImpl::new(
|
||||
// Shares the per-file size cap; fires `shared = true` triggers under the
|
||||
// writer app (§11.6 shared-collection triggers).
|
||||
let group_files: Arc<dyn picloud_shared::GroupFilesService> = Arc::new(
|
||||
GroupFilesServiceImpl::new(
|
||||
Arc::new(FsGroupFilesRepo::new(pool.clone(), files_root.clone())),
|
||||
Arc::new(PostgresGroupCollectionResolver::new(pool.clone())),
|
||||
authz.clone(),
|
||||
files_max_size,
|
||||
));
|
||||
)
|
||||
.with_events(events.clone()),
|
||||
);
|
||||
// v1.1.6 realtime: the in-process broadcaster is shared between the
|
||||
// publish path (PubsubServiceImpl fans out to SSE subscribers after
|
||||
// the durable outbox fan-out) and the SSE endpoint (subscribe side).
|
||||
|
||||
Reference in New Issue
Block a user