Skip to content

feat: workflow engine mailbox - #20091

Open
vxkc wants to merge 65 commits into
mainfrom
feat/workflow-engine-mailbox
Open

feat: workflow engine mailbox#20091
vxkc wants to merge 65 commits into
mainfrom
feat/workflow-engine-mailbox

Conversation

@vxkc

@vxkc vxkc commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description

Verification

  • Related issues are connected (if applicable)
  • Your code builds clean without any errors or warnings
  • Manual testing done (required)
  • Relevant automated test added (if you find this hard, leave it and we'll help out)

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 281 files, which is 181 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 141e3381-7c88-4815-9c9a-2fe44a14943f

📥 Commits

Reviewing files that changed from the base of the PR and between 5ada6d4 and 40f52c7.

📒 Files selected for processing (281)
  • .gitignore
  • .prettierignore
  • src/App/backend/AGENTS.md
  • src/App/backend/CHANGELOG.md
  • src/App/backend/src/Altinn.App.Api/Controllers/WorkflowEngineCallbackController.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/Constants/FiksIOConstants.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/Extensions/DataElementExtensions.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/Extensions/ServiceCollectionExtensions.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivDefaultResponseHandler.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivHost.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/FiksArkivServiceTask.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/IFiksArkivConfigResolver.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/IFiksArkivHost.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/IFiksArkivResponseHandler.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/FiksArkivSettings.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksArkiv/Models/StoredFiksArkivMessage.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksIO/Models/FiksIOReceivedMessage.cs
  • src/App/backend/src/Altinn.App.Clients.Fiks/FiksIO/Models/FiksIOReplayedMessage.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/IServiceTaskReplyForwarder.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/MailboxClosedReason.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/MailboxOptions.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskContext.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskLookupExtensions.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskMailbox.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskPipeline.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskPipelineBuilder.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskReply.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskReplyForwardException.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskReplyForwardOutcome.cs
  • src/App/backend/src/Altinn.App.Core/Features/Process/ServiceTaskResult.cs
  • src/App/backend/src/Altinn.App.Core/Features/Telemetry/Telemetry.Fiks.cs
  • src/App/backend/src/Altinn.App.Core/Internal/Process/Interfaces/IProcessEngine.cs
  • src/App/backend/src/Altinn.App.Core/Internal/Process/ProcessEngine.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/AGENTS.md
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Commands/EnqueueReceiveWorkflow.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Commands/ExecuteServiceTask.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Commands/_Base/CommandPayload.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Commands/_Base/ProcessEngineCommandContext.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Commands/_Base/ProcessEngineCommandResult.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/DependencyInjection/ServiceCollectionExtensions.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/DependencyInjection/WorkflowEngineCommandValidator.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Http/IWorkflowEngineClient.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Http/MailboxDeliveryResult.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Http/MailboxMintResult.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Http/WorkflowEngineClient.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/IWorkflowEngineService.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/MailboxContinuation.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/MailboxDeliveryEnvelope.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/MailboxRelay.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/AppCommand/AppCallbackPayload.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/MailboxCreateRequest.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/MailboxDeliveryRequest.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/MailboxDeliveryResponse.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/MailboxDisposedReason.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/MailboxReference.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/MailboxResponse.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/MailboxStatus.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/PersistentItemStatus.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/Engine/WorkflowRequest.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/SignedWorkflowState.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/WorkflowCallbackState.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/Models/WorkflowCallbackStateCarry.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/ProcessNextRequestFactory.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/ServiceTaskReplyForwarder.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/SigningPurpose.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/WorkflowCallbackStateService.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/WorkflowCommandSet.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/WorkflowCommandSetContexts.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/WorkflowEngineService.cs
  • src/App/backend/src/Altinn.App.Core/Internal/WorkflowEngine/WorkflowStateSigner.cs
  • src/App/backend/test/Altinn.App.Api.Tests/Controllers/InstancesController_PostNewInstanceTests.cs
  • src/App/backend/test/Altinn.App.Api.Tests/Controllers/WorkflowEngineCallbackControllerAuthTests.cs
  • src/App/backend/test/Altinn.App.Api.Tests/Controllers/WorkflowEngineCallbackControllerCarryTests.cs
  • src/App/backend/test/Altinn.App.Api.Tests/Controllers/WorkflowEngineCallbackControllerMailboxTests.cs
  • src/App/backend/test/Altinn.App.Api.Tests/FakeWorkflowEngineClient.cs
  • src/App/backend/test/Altinn.App.Api.Tests/OpenApi/OpenApiSpecChangeDetection.SaveJsonSwagger.verified.json
  • src/App/backend/test/Altinn.App.Api.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt
  • src/App/backend/test/Altinn.App.Api.Tests/PublicApiTests.cs
  • src/App/backend/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivDefaultResponseHandlerTest.cs
  • src/App/backend/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivHostTest.cs
  • src/App/backend/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivReplyAddressRoundTripTest.cs
  • src/App/backend/test/Altinn.App.Clients.Fiks.Tests/FiksArkiv/FiksArkivServiceTaskTest.cs
  • src/App/backend/test/Altinn.App.Clients.Fiks.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt
  • src/App/backend/test/Altinn.App.Clients.Fiks.Tests/PublicApiTests.cs
  • src/App/backend/test/Altinn.App.Clients.Fiks.Tests/TestFixture.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Features/Process/ServiceTaskContextTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Features/Process/ServiceTaskPipelineMailboxTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/Process/ProcessEngineTest.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/AltinnEvents/CompletedAltinnEventTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/AltinnEvents/InstanceCreatedAltinnEventTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/AltinnEvents/MovedToAltinnEventTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ExecuteServiceTaskMailboxTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ExecuteServiceTaskReplyTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ExecuteServiceTaskStageTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ExecuteServiceTaskTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/MutateProcessStateTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/ProcessEnd/DeleteDataElementsIfConfiguredTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/ProcessEnd/DeleteInstanceIfConfiguredTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/ProcessEnd/OnProcessEndingHookTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskAbandon/AbandonTaskTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskAbandon/OnTaskAbandonHookTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskEnd/CommonTaskFinalizationTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskEnd/EndTaskTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskEnd/LockTaskDataTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskEnd/OnTaskEndingHookTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskStart/CleanupGeneratedFromTaskTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskStart/CommonTaskInitializationTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskStart/OnTaskStartingHookTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskStart/StartTaskTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/Commands/ProcessNext/TaskStart/UnlockTaskDataTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/ContractTests/AppWireContractTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/DependencyInjection/WorkflowEngineCommandValidatorTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/EnqueueReceiveWorkflowTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/EnqueueSideEffectsWorkflowTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/MailboxDeliveryEnvelopeTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/MailboxRelayFrontierTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/MailboxRelayTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/ProcessNextRequestFactoryTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/ProcessStepOptionsResolverTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/ServiceTaskRegistrationValidatorTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/ServiceTaskReplyForwarderTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/TestMailboxDeliveryEnvelope.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/WorkflowCallbackStateCarryTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/WorkflowEngineClientTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/WorkflowEngineServiceTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/Internal/WorkflowEngine/WorkflowStateSignerTests.cs
  • src/App/backend/test/Altinn.App.Core.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt
  • src/App/backend/test/Altinn.App.Core.Tests/PublicApiTests.cs
  • src/Runtime/workflow-engine-app/AGENTS.md
  • src/Runtime/workflow-engine-app/src/WorkflowEngine.App/Commands/AppCommand/AppCallbackPayload.cs
  • src/Runtime/workflow-engine-app/src/WorkflowEngine.App/Commands/AppCommand/AppCommand.cs
  • src/Runtime/workflow-engine-app/tests/WorkflowEngine.App.Tests/.snapshots/AppCommandIntegrationTests.AppCommand_FullHttpChatter_DocumentsExchange.http
  • src/Runtime/workflow-engine-app/tests/WorkflowEngine.App.Tests/.snapshots/AppCommandIntegrationTests.Response_AppCommandCallback_PayloadShape.verified.txt
  • src/Runtime/workflow-engine-app/tests/WorkflowEngine.App.Tests/Commands/AppCommand/AppCommandMailboxTests.cs
  • src/Runtime/workflow-engine-app/tests/WorkflowEngine.App.Tests/Contract/EngineWireContractTests.cs
  • src/Runtime/workflow-engine-app/tests/WorkflowEngine.App.Tests/Contract/wire-contract.verified.json
  • src/Runtime/workflow-engine-app/tests/WorkflowEngine.App.Tests/Fixtures/AppCommandTestFixture.cs
  • src/Runtime/workflow-engine-app/typos.toml
  • src/Runtime/workflow-engine/.claude/skills/docker/SKILL.md
  • src/Runtime/workflow-engine/.claude/skills/k6/SKILL.md
  • src/Runtime/workflow-engine/.claude/skills/test/SKILL.md
  • src/Runtime/workflow-engine/.gitignore
  • src/Runtime/workflow-engine/.k6/README.md
  • src/Runtime/workflow-engine/.k6/docker-compose.measure.yaml
  • src/Runtime/workflow-engine/.k6/lib/compare-summaries.mjs
  • src/Runtime/workflow-engine/.k6/lib/helpers.js
  • src/Runtime/workflow-engine/.k6/mailbox-storm-compare.sh
  • src/Runtime/workflow-engine/.k6/mailbox-storm.js
  • src/Runtime/workflow-engine/.k6/payloads/mailbox-receiver.json
  • src/Runtime/workflow-engine/AGENTS.md
  • src/Runtime/workflow-engine/docs/technical-guide.md
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/BatchBuffer.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/Constants/Defaults.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/DashboardMapper.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/Endpoints/DashboardEndpoints.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/Endpoints/EngineEndpoints.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/Engine.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/Extensions/ServiceCollectionExtensions.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/MailboxBuffers.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/Metadata/EngineApiDocsTransformer.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/MetricsCollector.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/WorkflowExecutor.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/WorkflowWriteBuffer.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/AGENTS.md
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/DASHBOARD_SPEC.md
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/index.html
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/core/helpers.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/core/state.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/features/filters.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/features/modal.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/features/query.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/shared/cards.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/shared/chain-groups.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/shared/chain.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/shared/pipeline.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/modules/shared/timers.js
  • src/Runtime/workflow-engine/src/WorkflowEngine.Core/wwwroot/style.css
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/BatchEnqueueResult.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/BatchEnqueueResultStatus.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/BufferedMailboxRequests.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Constants/MailboxStatusMap.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Constants/PersistentItemStatusMap.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Context/EngineDbContext.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Entities/MailboxDeliveryEntity.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Entities/MailboxEntity.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Entities/MailboxReceiverEntity.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Entities/WorkflowEntity.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Extensions/ServiceCollectionExtensions.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Extensions/WorkflowRequestExtensions.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/IBufferedRequest.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Migrations/20260820195459_AddMailbox.Designer.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Migrations/20260820195459_AddMailbox.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Migrations/EngineDbContextModelSnapshot.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Repository/EngineRepository.Logs.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Repository/EngineRepository.Mailboxes.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Repository/EngineRepository.QueryExtensions.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Repository/EngineRepository.Writes.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Repository/IEngineRepository.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Services/DbMaintenanceService.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/Services/MailboxDeadlineService.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Data/WorkflowEnqueueOutcome.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/CommandExecutionContext.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/EngineSettings.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxCreateRequest.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxDeliveryRequest.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxDeliveryResponse.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxDisposedReason.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxReceipt.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxReference.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxResponse.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/MailboxStatus.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/PersistentItemStatus.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/Workflow.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Models/WorkflowRequest.cs
  • src/Runtime/workflow-engine/src/WorkflowEngine.Telemetry/Metrics.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/CallbackTokenLifetimeInvariantTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/DashboardMailboxMapperTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/Extensions/EngineSettingsConfigurationTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/Fixtures/WorkflowEngineTestFixture.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/MailboxCloseBufferTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/MailboxDeliveryBufferTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/MailboxDeliveryOutcomeTagTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/MailboxMintBufferTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/MeterCollector.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/MetricsCollectorTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Core.Tests/WorkflowExecutorMailboxTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Data.Tests/Constants/MailboxStatusMapTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Data.Tests/Constants/PersistentItemStatusMapTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/EngineTests.WebhookCommand_FullHttpChatter_DocumentsExchange.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/DagRoundtrip_AllRelations_FullExchange.exchange.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_MultiWorkflow_DependsOn_MixedRefs.inbound.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_MultiWorkflow_DependsOn_RefsOnly.inbound.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Validation_CycleDetected.exchange.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Validation_DuplicateRef.exchange.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Validation_MissingRef.exchange.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Validation_SelfReference.exchange.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Workflow_DependsOnHeadsFalse.inbound.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Workflow_FullyPopulated.inbound.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Workflow_IsHeadForceExclude.inbound.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Workflow_IsHeadForceInclude.inbound.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/.snapshots/inbound/Inbound_Workflow_WithLinks.inbound.http
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/DashboardMailboxEndpointTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/MailboxDeliveryEndpointTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/MailboxEndpointTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/MailboxReceiptEndpointTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/MailboxReceiverEndpointTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/MailboxRendezvousEndpointTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Integration.Tests/MailboxSweepEndpointTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.CloseLockedMailboxes_ProbesThePrimaryKeyForEveryMailboxInTheBatch.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.CountOverdueOpenMailboxes_UsesIndexScans.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.GetActiveWorkflows_UsesIndexScans.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.GetScheduledWorkflows_UsesIndexScans.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.LockMailboxesForMutation_ProbesThePrimaryKeyForEveryMailboxInAFullBatch.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.MintMailboxes_ProbesBothMailboxIndexesForEveryCandidateInTheBatch_width-1.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.MintMailboxes_ProbesBothMailboxIndexesForEveryCandidateInTheBatch_width-100.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.ReleaseMailboxReceivers_ProbesTheReceiverKeyForEveryPositionInTheBatch.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.SelectExistingMailboxDeliveries_ProbesTheMessageKeyForEveryPairInTheBatch_width-1.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.SelectExistingMailboxDeliveries_ProbesTheMessageKeyForEveryPairInTheBatch_width-100.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.SelectExpiredMailboxCandidates_UsesIndexScans.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.SelectExpiredWorkflowCandidates_UsesIndexScans.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.SelectMailboxesForCollections_UsesIndexScans.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/.snapshots/QueryPlanTests.SelectOverdueMailboxCandidates_UsesIndexScans.verified.txt
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/Fixtures/PostgresFixture.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/Fixtures/QueryPlanHelper.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxBatchTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxDashboardTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxDeliveryTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxReceiptTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxReceiverTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxRendezvousTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxSweepTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/MailboxTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/QueryPlanTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/RetentionTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.Repository.Tests/WorkflowCrudTests.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.TestApp/Program.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.TestApp/ReceivingCommand.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.TestKit/EngineApiClient.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.TestKit/EngineAppFixture.cs
  • src/Runtime/workflow-engine/tests/WorkflowEngine.TestKit/HttpChatterHelpers.cs
  • src/Runtime/workflow-engine/typos.toml

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the skip-releasenotes Issues that do not make sense to list in our release notes label Aug 20, 2026
@vxkc
vxkc marked this pull request as draft August 20, 2026 13:48
@vxkc
vxkc marked this pull request as ready for review August 20, 2026 18:18
vxkc added 26 commits August 20, 2026 20:22
A coarse BackgroundService closes open mailboxes past their deadline by running
exactly the routine DELETE runs, with disposed_reason = 'deadline'. The
FOR UPDATE SKIP LOCKED claim is the mailbox row lock the closure requires, one
transaction per mailbox, and a close that throws is contained to its own mailbox
rather than wedging the batch behind it. A tick drains — SweepBatchSize bounds
the statement, not the tick — so the deadline-to-close gap really is at most one
cadence rather than ceil(overdue / batch) cadences. There is no second half:
nothing is enqueued, because the receiver that concludes the exchange already
exists and is released rather than created.

Retention purges closed mailboxes past the cutoff with their deliveries and
waiters, children first — an order the RESTRICT foreign keys enforce.

The sweep runs on its own coarser cadence, EngineSettings.MailboxSweepInterval,
so the term MaxMailboxTimeout's derivation charges for it is repointed there in
both places step 1 named. The setting carries no property initializer, so
Defaults is the only source of its value and the tripwire that reads Defaults
guards the number the engine actually runs on.

Step 5's dashboard half is split out as step 5b.
@vxkc
vxkc force-pushed the feat/workflow-engine-mailbox branch from 72f48c1 to 6239611 Compare August 20, 2026 18:51
vxkc added 4 commits August 20, 2026 21:56
The stack (wnoznnum..trtzopwn) landed roughly 8 200 lines of comment across 197
files, much of it multi-paragraph prose restating the code beside it. This trims
them to short statements and deletes the ones that said nothing the name did not:
essays collapsed to one or two lines, XML-doc <remarks> folded into their summary
or dropped, Arrange/Act/Assert markers and "Gets or sets the X" property docs
removed, and per-test preambles cut where the test name already says it.

Comment lines added by the stack drop from ~8 200 to ~4 900.
Delete the mailbox proposal — a design record whose implementation plan is
complete and whose shipped behavior is specified in the technical guide —
and cut the engine AGENTS.md mailbox bullets to a pointer plus the
agent-operational invariants (lock discipline, Held's semantics, the
birth/idempotency rules, the frozen rendezvous read, the closure routine,
the token-lifetime coupling, retention order).

What the bullets alone carried moves into the technical guide first, so
nothing is lost: the mailbox metrics table with tag values and alert
semantics (rendezvous violations, the open.overdue gauge), the mailbox
settings reference, and the dashboard mailbox view. technical-guide.md is
now prettier-formatted — the md format hook is a git-side lefthook, so
jj-made commits had let it drift.
A readability pass over what the mailbox stack added: the same structure,
the same headings (every anchor is linked from AGENTS.md and within the
guide), every fact, invariant, and warning retained — each now stated once,
with its justification compressed to the clause that earns its place.
Connective rhetoric and restatements are gone; tables, examples, and the
subtle passages (the frozen-meaning rule, the single-snapshot read, the
critical-versus-retryable choice) keep their full reasoning.

Audited for information loss: every code span, metric name, setting, and
status code from the old text survives, checked mechanically.
@vxkc
vxkc force-pushed the feat/workflow-engine-mailbox branch from 6239611 to a3a1da8 Compare August 20, 2026 20:01
@vxkc vxkc changed the title Feat/workflow engine mailbox feat: workflow engine mailbox Aug 20, 2026
private bool PrintMembers(StringBuilder builder)
{
builder.Append("InstanceDataMutator = ").Append(InstanceDataMutator);
builder.Append(", CancellationToken = ").Append(CancellationToken.ToString());
_logger.LogWarning(
"Workflow engine reported no mailbox to close. URL: {Url}. The mailbox was purged, or it was never "
+ "minted in this namespace.",
url
_logger.LogError(
"Workflow engine mailbox close failed with status {StatusCode}. URL: {Url}. Response body: {Body}",
response.StatusCode,
url,

| Outcome | Response |
| --------------------------------------- | ---------------------------------------------- |
| Appended at a new position | `202 Accepted` with the assigned `idx` |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're returning 201 from POST /workflows, where 202 was reserved for truly async tasks like POST /cancel. Food for thought.

does not exist. The dashboard's _Retry now_ / _Check now_ buttons drive the same operation through
`POST /dashboard/nudge`.

## Mailboxes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General observations after grilling a local agent on some edge cases:

Two dependsOn × mailbox corners that are currently neither blocked nor documented:                                                                                                                              
                                                                                                                                                                                                                  
  1. A receiver with dependsOn: if the dependency fails, the receiver dies without ever running its handler — no successor gets enqueued, the exchange silently stalls until the deadline sweep, and the message  
     at its position is never processed (and isn't reported as unconsumed at close, since its position was already claimed).                                                                                      
  2. Depending on a receiver: every receiver in a multi-message exchange completes successfully — including the ones that just said "wait for the next message." So a dependent fires after the first reply, not  
     when the exchange actually concludes. Works by accident for single-message exchanges, breaks quietly for multi-message ones (e.g. Fiks Arkiv).                                                               
                                                                                                                                                                                                                  
  Suggest either validating both combinations away or spelling out the semantics in the technical guide.

vxkc added 20 commits August 22, 2026 20:53
Warnings are errors when CI=true, so the stray second <summary> on
LockedMailboxState failed WorkflowEngine.Data with CS1570. Local builds
only warned, which is why it survived.
Adds BatchCloseMailboxes, the flush the close buffer will call: one
connection and one transaction for a batch of close requests, locking
every distinct (mailbox, namespace) pair it decides on in one sorted
statement as the transaction's first act. The sorted lock is hoisted as
LockMailboxesForMutationSql so the delivery flush can share it, and its
plan is pinned at a full batch's width -- one primary-key probe per
mailbox named, with LockRows above the sort so the lock order binds.

Requests are answered positionally with the verdict a separate call
would have received: a pair the lock did not match is NotFound, and a
mailbox named twice in one batch is closed once, its repeat replaying
the disposal the first occurrence wrote. Per-request CloseMailbox is now
that same transaction with a batch of one, keeping its own slot, retry
and telemetry envelope; the deadline sweep is untouched and still runs
the closure core under its own SKIP LOCKED claim.

Introduces IBufferedRequest<TResult> and BufferedMailboxCloseRequest for
the buffer layer to build on.
Adds BatchMintMailboxes, the flush the mint buffer will call: one
connection, no lock and no transaction, because the unique index on
(namespace, idempotency_key) is what serializes minters. The bespoke
single-row MintMailboxSql CTE is deleted and replaced by
MintMailboxesSql: an ordinality-numbered input CTE, a fresh CTE dropping
the keys the snapshot already sees, a materialized open_counts, and one
INSERT ... SELECT in unique-index order with ON CONFLICT DO NOTHING. A
second statement classifies the keys the insert did not return, the
ClassifyExistingIdempotencyKeys pattern.

Requests are answered positionally with the verdict a separate call
would have received. Only fresh candidates rank against the collection
cap (row_number() - 1 as peers_ahead), so a flush counts its own mints
against the cap instead of admitting all of them off one reading, while
replays are answered even at the cap and consume none of it. A key named
twice in one batch mints once and its repeat replays the row, costing the
collection one slot rather than two. Minted versus Existing stays decided
by returned id == candidate id, which is also how an attempt whose commit
the client never saw recognises its own mailbox on retry.

The mint plan test is rewritten against the new statement and now probes
a hundred-wide batch as well as a singleton: written as a GROUP BY over a
join, open_counts planned as one index probe at width one and a hash join
against every open mailbox at width a hundred. Per-request MintMailbox is
the same two statements with a batch of one, keeping its slot, retry and
telemetry envelope.

Also renames the close plan test after the const it exercises, left over
from the previous revision's rename.
Extracts WorkflowWriteBuffer's channel/drain/flush mechanics into a generic
BatchBuffer<TItem, TResult> over IBufferedRequest<TResult>, and adds the first
subclass: MailboxDeliveryBuffer, which flushes through BatchDeliverToMailboxes
and fans the positional results back out. Deliveries are never refused
admission — the bounded channel waits — and the fan-out records nothing.

Delivery batches are bounded by a cumulative payload budget as well as by batch
size, so a hundred requests at the payload ceiling cannot build one enormous
command. The same bound applies to the shutdown drain.

Adds BatchBufferSettings/MailboxBufferSettings with defaults and the <= 0
back-fill for all three mailbox buffers, even though the mint and close buffers
themselves come next: the settings are one coherent block.

Nothing is registered in DI or reachable from an endpoint yet.
Engine's MintMailbox, CloseMailbox and DeliverToMailbox now enqueue into the
three mailbox buffers instead of calling the repository per request, and the
buffers are registered as singleton hosted services. Everything else about the
three methods stays put: the pre-database validation that produces the Invalid
verdicts (which no repository path can return), the candidate id and the
caller's own instant, and the verdict-shaped metrics — MailboxesCreated on a
mint, MailboxDeliveriesReceived for every delivery outcome including the
refusals decided before the database. Commit-gated metrics stay in the
repository.

The buffers register above the HeartbeatService ordering comment, beside the
write and update buffers: hosted services stop in reverse registration order,
so they are stopped after the processor and answer their queued callers from
the 30-second drain rather than being cut off. What they have to outlive is
request handling, since they are fed from the HTTP path.

BatchBuffer takes an operation tag and emits engine.mailbox_buffer.flushed
immediately after FlushCore returns — the one point where a batch is known to
have been answered without faulting. MetricsCollector feeds the new
engine.mailbox_buffer.depth gauge from the three queue depths each tick.

The 219 integration tests and the repository suites pass unmodified: HTTP
semantics are unchanged, including that a full delivery queue waits rather than
refusing.
Strict bar: a comment stays only if it carries knowledge the surrounding
code cannot give — behaviour of something outside this codebase, a
consequence in another component, or the reason something absent is absent.
On interface members, judged against the signature alone.

Comments, docstrings and blank lines only; no behaviour change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-releasenotes Issues that do not make sense to list in our release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants