feat(v1.1.2-docs): wire DocsServiceImpl into picloud binary

build_app constructs PostgresDocsRepo + DocsServiceImpl alongside
the existing KV wiring, sharing the same OutboxEventEmitter so KV
and docs mutations both fan out through the same dispatcher. The
docs handle joins the Services bundle so executor-core sees it on
every per-call sdk::register_all.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-02 19:55:51 +02:00
parent a66d4af34f
commit 2a047f1f85

View File

@@ -16,14 +16,14 @@ use picloud_manager_core::{
AdminPrincipalResolver, AdminSessionRepository, AdminState, AdminUserRepository, AdminsState, AdminPrincipalResolver, AdminSessionRepository, AdminState, AdminUserRepository, AdminsState,
ApiKeyRepository, ApiKeysState, AppDomainRepository, AppMembersRepository, AppMembersState, ApiKeyRepository, ApiKeysState, AppDomainRepository, AppMembersRepository, AppMembersState,
AppRepository, AppsState, AuthState, AuthzRepo, DeadLetterRepo, DeadLettersState, Dispatcher, AppRepository, AppsState, AuthState, AuthzRepo, DeadLetterRepo, DeadLettersState, Dispatcher,
KvServiceImpl, OutboxEventEmitter, OutboxRepo, PostgresAbandonedRepo, DocsServiceImpl, KvServiceImpl, OutboxEventEmitter, OutboxRepo, PostgresAbandonedRepo,
PostgresAdminSessionRepository, PostgresAdminUserRepository, PostgresApiKeyRepository, PostgresAdminSessionRepository, PostgresAdminUserRepository, PostgresApiKeyRepository,
PostgresAppDomainRepository, PostgresAppMembersRepository, PostgresAppRepository, PostgresAppDomainRepository, PostgresAppMembersRepository, PostgresAppRepository,
PostgresDeadLetterRepo, PostgresDeadLetterService, PostgresExecutionLogRepository, PostgresDeadLetterRepo, PostgresDeadLetterService, PostgresDocsRepo,
PostgresExecutionLogSink, PostgresKvRepo, PostgresOutboxRepo, PostgresRouteRepository, PostgresExecutionLogRepository, PostgresExecutionLogSink, PostgresKvRepo, PostgresOutboxRepo,
PostgresScriptRepository, PostgresTriggerRepo, PrincipalResolver, RepoResolver, PostgresRouteRepository, PostgresScriptRepository, PostgresTriggerRepo, PrincipalResolver,
RouteAdminState, RouteRepository, SandboxCeiling, ScriptRepository, TriggerConfig, TriggerRepo, RepoResolver, RouteAdminState, RouteRepository, SandboxCeiling, ScriptRepository,
TriggersState, TriggerConfig, TriggerRepo, TriggersState,
}; };
use picloud_orchestrator_core::routing::{AppDomainTable, RouteTable}; use picloud_orchestrator_core::routing::{AppDomainTable, RouteTable};
use picloud_orchestrator_core::{ use picloud_orchestrator_core::{
@@ -31,8 +31,9 @@ use picloud_orchestrator_core::{
LocalExecutorClient, LocalExecutorClient,
}; };
use picloud_shared::{ use picloud_shared::{
DeadLetterService, ExecutionLogSink, InboxResolver, KvService, OutboxWriter, ScriptValidator, DeadLetterService, DocsService, ExecutionLogSink, InboxResolver, KvService, OutboxWriter,
ServiceEventEmitter, Services, API_VERSION, PRODUCT_VERSION, SDK_VERSION, WIRE_VERSION, ScriptValidator, ServiceEventEmitter, Services, API_VERSION, PRODUCT_VERSION, SDK_VERSION,
WIRE_VERSION,
}; };
use sqlx::postgres::PgPoolOptions; use sqlx::postgres::PgPoolOptions;
use sqlx::PgPool; use sqlx::PgPool;
@@ -119,22 +120,29 @@ pub async fn build_app(pool: PgPool, auth: AuthDeps) -> anyhow::Result<Router> {
let abandoned_repo: Arc<dyn AbandonedRepo> = Arc::new(PostgresAbandonedRepo::new(pool.clone())); let abandoned_repo: Arc<dyn AbandonedRepo> = Arc::new(PostgresAbandonedRepo::new(pool.clone()));
let trigger_config = TriggerConfig::from_env(); let trigger_config = TriggerConfig::from_env();
// SDK services bundle. v1.1.1 ships the KV store + the // SDK services bundle. v1.1.1 added KV + dead-letter; v1.1.2 adds
// outbox-backed event emitter + the dead-letter service (replay / // the docs store. All four bound services share the
// resolve). // outbox-backed event emitter so KV and docs mutations both fan
let kv_repo = Arc::new(PostgresKvRepo::new(pool)); // out through the same dispatcher.
let kv_repo = Arc::new(PostgresKvRepo::new(pool.clone()));
let docs_repo = Arc::new(PostgresDocsRepo::new(pool));
let events: Arc<dyn ServiceEventEmitter> = Arc::new(OutboxEventEmitter::new( let events: Arc<dyn ServiceEventEmitter> = Arc::new(OutboxEventEmitter::new(
trigger_repo.clone(), trigger_repo.clone(),
outbox_repo.clone(), outbox_repo.clone(),
)); ));
let kv: Arc<dyn KvService> = let kv: Arc<dyn KvService> =
Arc::new(KvServiceImpl::new(kv_repo, authz.clone(), events.clone())); Arc::new(KvServiceImpl::new(kv_repo, authz.clone(), events.clone()));
let docs: Arc<dyn DocsService> = Arc::new(DocsServiceImpl::new(
docs_repo,
authz.clone(),
events.clone(),
));
let dl_service: Arc<dyn DeadLetterService> = Arc::new(PostgresDeadLetterService::new( let dl_service: Arc<dyn DeadLetterService> = Arc::new(PostgresDeadLetterService::new(
dl_repo.clone(), dl_repo.clone(),
outbox_repo.clone(), outbox_repo.clone(),
authz.clone(), authz.clone(),
)); ));
let services = Services::new(kv, dl_service.clone(), events); let services = Services::new(kv, docs, dl_service.clone(), events);
let engine = Arc::new(Engine::new(Limits::default(), services)); let engine = Arc::new(Engine::new(Limits::default(), services));
// Compile the routes table once at startup; admin writes refresh it. // Compile the routes table once at startup; admin writes refresh it.