services/execution-service owns persisted execution and preview metadata.
It is responsible for:
- recording command execution lifecycle
- exposing execution history and details to the frontend
- initiating execution and preview flows through pub/sub
- buffering/retrieving execution output
- reacting to runtime completion/error events
- cleaning up stale executions
It does not execute commands itself. Container-service does the actual runtime work.
src
├── config
│ ├── database.ts
│ ├── index.ts
│ └── subscribers.ts
├── jobs
│ └── stale.watcher.ts
├── modules
│ └── execution
│ ├── execution.controller.ts
│ ├── execution.repository.ts
│ ├── execution.routes.ts
│ ├── execution.schema.ts
│ └── execution.service.ts
├── utils
│ ├── AppError.ts
│ ├── lock.ts
│ └── projectAccess.ts
├── index.ts
└── openapi.ts
Routes are mounted at /.
POST /previewDELETE /preview/:projectIdGET /project/:projectIdPOST /GET /:executionIdGET /:executionId/bufferDELETE /:executionIdGET /healthGET /openapi.json
POST /
- validates execution request
- creates/persists execution record
- publishes
execution:start - returns
executionIdimmediately
GET /:executionIdreturns stored execution metadataGET /project/:projectIdreturns history for a projectGET /:executionId/bufferreturns buffered output chunks for reconnect/replay
DELETE /:executionId
- marks the execution as being killed
- publishes
execution:kill
POST /previewstarts a dev-server flow by publishingpreview:startDELETE /preview/:projectIdpublishespreview:stop
src/config/subscribers.ts consumes:
- finalizes execution record
- stores exit code, duration, status, error metadata
- logs completion state transitions
- records preview availability metadata such as host/URL state
- enables gateway-side preview routing
- marks preview state as failed and publishes/records the failure
- removes execution history for deleted projects
This service works with shared helpers from @synthex/database and local utilities to manage:
- replay buffers for execution output
- execution/project locks
- metadata needed by gateway socket joins
These pieces allow:
- reconnect-safe output replay
- prevention of overlapping executions where disallowed
- cleanup after completion or failure
src/jobs/stale.watcher.ts runs every 5 minutes.
It finds non-dev-server executions that have been queued or running for longer than 35 minutes and:
- marks them failed
- publishes
execution:kill - releases locks
- clears Redis buffers
This protects the system from orphaned execution records if the runtime side crashes or hangs.
Primary table:
ExecutionLog
Important fields:
executionIdprojectIduserIdstatuscommandoutputerrorexitCodedurationMscompletedAtisDevServer
- frontend calls execution-service
- service creates execution record and publishes
execution:start - container-service runs the command and streams output
- gateway relays live chunks to browser sockets
- container-service publishes
execution:done - execution-service finalizes persistence state
- frontend calls
POST /preview - service validates and publishes
preview:start - container-service launches preview server
- container-service publishes
preview:readyorpreview:error - execution-service records preview state
- gateway registers/removes preview proxies and informs the browser
- PostgreSQL for
ExecutionLog - Redis for buffers, locks, and metadata
- container-service for actual command/preview runtime
- project-service ownership context
- API gateway for browser-facing socket replay/fan-out