feat(shared-queues): group-keyed queue store + enqueue service + SDK (D3.1)
The producer side of shared durable queues:
- migration 0065 group_queue_messages (mirrors 0034, keyed by (group_id,
collection); CASCADE on group delete).
- GroupQueueRepo/PostgresGroupQueueRepo: enqueue + the competing-consumer
claim (FOR UPDATE SKIP LOCKED) + ack/nack/drop_exhausted/reclaim/depth.
- GroupQueueService trait (shared) + GroupQueueServiceImpl: resolve owning
group (kind='queue') from cx.app_id's chain, require editor+
(GroupQueueEnqueue, fails closed on anon), size-cap, enqueue.
- SDK: `queue::shared_collection("name")` -> GroupQueueHandle with
`.enqueue(msg[, opts])` / `.depth()` / `.depth_pending()`; wired through
Services + the picloud binary.
- authz: Capability::GroupQueueEnqueue(GroupId), editor+ / script:write.
Deterministic test proves competing consumers claim each message exactly
once. Consumption wiring (materialized consumers + dispatcher branch) lands
in D3.2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,23 +20,23 @@ use picloud_manager_core::{
|
||||
AppsState, AuthState, AuthzRepo, DeadLetterRepo, DeadLettersState, DevEmailState, Dispatcher,
|
||||
DocsServiceImpl, EmailInboundState, EmailServiceImpl, FilesAdminState, FilesConfig,
|
||||
FilesServiceImpl, FsFilesRepo, FsGroupFilesRepo, GroupDocsServiceImpl, GroupFilesServiceImpl,
|
||||
GroupKvServiceImpl, GroupMembersRepository, GroupPubsubServiceImpl, GroupRepository,
|
||||
GroupsState, HttpConfig, HttpServiceImpl, InboundNonceDedup, KvAdminState, KvServiceImpl,
|
||||
OutboxEventEmitter, OutboxRepo, PostgresAbandonedRepo, PostgresAdminSessionRepository,
|
||||
PostgresAdminUserRepository, PostgresApiKeyRepository, PostgresAppDomainRepository,
|
||||
PostgresAppMembersRepository, PostgresAppRepository, PostgresAppSecretsRepo,
|
||||
PostgresAppUserInvitationRepo, PostgresAppUserPasswordResetRepo, PostgresAppUserRepository,
|
||||
PostgresAppUserRoleRepo, PostgresAppUserSessionRepository, PostgresAppUserVerificationRepo,
|
||||
PostgresDeadLetterRepo, PostgresDeadLetterService, PostgresDocsRepo,
|
||||
PostgresExecutionLogRepository, PostgresExecutionLogSink, PostgresGroupCollectionResolver,
|
||||
PostgresGroupDocsRepo, PostgresGroupKvRepo, PostgresGroupMembersRepository,
|
||||
PostgresGroupRepository, PostgresKvRepo, PostgresOutboxRepo, PostgresPubsubRepo,
|
||||
PostgresRouteRepository, PostgresScriptRepository, PostgresSecretsRepo, PostgresTopicRepo,
|
||||
PostgresTriggerRepo, PostgresVarsRepo, PrincipalResolver, PubsubServiceImpl,
|
||||
RealtimeAuthorityImpl, RepoResolver, RouteAdminState, SandboxCeiling, ScriptRepository,
|
||||
SecretsConfig, SecretsServiceImpl, SecretsState, SubscriberTokenConfig, TopicRepo, TopicsState,
|
||||
TriggerConfig, TriggerRepo, TriggersState, UsersServiceConfig, UsersServiceImpl, VarsApiState,
|
||||
VarsServiceImpl,
|
||||
GroupKvServiceImpl, GroupMembersRepository, GroupPubsubServiceImpl, GroupQueueServiceImpl,
|
||||
GroupRepository, GroupsState, HttpConfig, HttpServiceImpl, InboundNonceDedup, KvAdminState,
|
||||
KvServiceImpl, OutboxEventEmitter, OutboxRepo, PostgresAbandonedRepo,
|
||||
PostgresAdminSessionRepository, PostgresAdminUserRepository, PostgresApiKeyRepository,
|
||||
PostgresAppDomainRepository, PostgresAppMembersRepository, PostgresAppRepository,
|
||||
PostgresAppSecretsRepo, PostgresAppUserInvitationRepo, PostgresAppUserPasswordResetRepo,
|
||||
PostgresAppUserRepository, PostgresAppUserRoleRepo, PostgresAppUserSessionRepository,
|
||||
PostgresAppUserVerificationRepo, PostgresDeadLetterRepo, PostgresDeadLetterService,
|
||||
PostgresDocsRepo, PostgresExecutionLogRepository, PostgresExecutionLogSink,
|
||||
PostgresGroupCollectionResolver, PostgresGroupDocsRepo, PostgresGroupKvRepo,
|
||||
PostgresGroupMembersRepository, PostgresGroupQueueRepo, PostgresGroupRepository,
|
||||
PostgresKvRepo, PostgresOutboxRepo, PostgresPubsubRepo, PostgresRouteRepository,
|
||||
PostgresScriptRepository, PostgresSecretsRepo, PostgresTopicRepo, PostgresTriggerRepo,
|
||||
PostgresVarsRepo, PrincipalResolver, PubsubServiceImpl, RealtimeAuthorityImpl, RepoResolver,
|
||||
RouteAdminState, SandboxCeiling, ScriptRepository, SecretsConfig, SecretsServiceImpl,
|
||||
SecretsState, SubscriberTokenConfig, TopicRepo, TopicsState, TriggerConfig, TriggerRepo,
|
||||
TriggersState, UsersServiceConfig, UsersServiceImpl, VarsApiState, VarsServiceImpl,
|
||||
};
|
||||
use picloud_orchestrator_core::realtime::DEFAULT_GC_INTERVAL_SECS;
|
||||
use picloud_orchestrator_core::routing::{AppDomainTable, RouteTable};
|
||||
@@ -268,6 +268,14 @@ pub async fn build_app(
|
||||
Arc::new(PostgresGroupCollectionResolver::new(pool.clone())),
|
||||
authz.clone(),
|
||||
));
|
||||
// §11.6 D3: the group shared-queue store + enqueue service.
|
||||
let group_queue_repo = Arc::new(PostgresGroupQueueRepo::new(pool.clone()));
|
||||
let group_queue: Arc<dyn picloud_shared::GroupQueueService> =
|
||||
Arc::new(GroupQueueServiceImpl::new(
|
||||
group_queue_repo.clone(),
|
||||
Arc::new(PostgresGroupCollectionResolver::new(pool.clone())),
|
||||
authz.clone(),
|
||||
));
|
||||
let pubsub: Arc<dyn PubsubService> = Arc::new(
|
||||
PubsubServiceImpl::new(pubsub_repo, authz.clone())
|
||||
.with_max_message_bytes(
|
||||
@@ -393,7 +401,8 @@ pub async fn build_app(
|
||||
.with_group_kv(group_kv)
|
||||
.with_group_docs(group_docs)
|
||||
.with_group_files(group_files)
|
||||
.with_group_pubsub(group_pubsub);
|
||||
.with_group_pubsub(group_pubsub)
|
||||
.with_group_queue(group_queue);
|
||||
// v1.1.9: keep the invoke depth bound aligned with the dispatcher's
|
||||
// trigger-depth bound (same counter under the hood).
|
||||
let engine_limits = Limits {
|
||||
|
||||
Reference in New Issue
Block a user