Conversation
Introduced a new deployments page that includes a table for viewing all application and compose deployments, as well as a queue table for monitoring deployment jobs. Updated the sidebar to include a link to the new deployments section. Enhanced the API to support centralized deployment queries and job queue retrieval, improving overall deployment management and visibility.
Added a new endpoint to fetch deployment jobs for a server, integrating with the Inngest API to retrieve job details. Updated the queue management system to support centralized job retrieval for cloud environments, improving the deployment monitoring experience. Enhanced the UI to include action buttons for job cancellation and improved error handling for job fetching.
Added self-hosted and production configuration examples for Inngest to the .env.example file. This enhancement provides clearer guidance for developers on setting up the Inngest integration.
|
Documentation Updates 1 document(s) were updated by changes in this PR: READMEView Changes@@ -6,6 +6,31 @@
```
open http://localhost:3000
```
+
+## Environment Variables
+
+The API server requires the following environment variables for configuration:
+
+### Inngest Configuration
+
+Required for the GET /jobs endpoint to list deployment jobs:
+
+- **INNGEST_BASE_URL** - The base URL for the Inngest instance
+ - Self-hosted: `http://localhost:8288`
+ - Production: `https://dev-inngest.dokploy.com`
+
+- **INNGEST_SIGNING_KEY** - The signing key for authenticating with Inngest
+
+Optional configuration for filtering and pagination:
+
+- **INNGEST_EVENTS_RECEIVED_AFTER** (optional) - An RFC3339 timestamp to filter events received after a specific date (e.g., `2024-01-01T00:00:00Z`). If unset, no date filter is applied.
+
+- **INNGEST_JOBS_MAX_EVENTS** (optional) - Maximum number of events to fetch when listing jobs. Default is 100, maximum is 10000. Used for pagination with cursor.
+
+### Lemon Squeezy Integration
+
+- **LEMON_SQUEEZY_API_KEY** - API key for Lemon Squeezy integration
+- **LEMON_SQUEEZY_STORE_ID** - Store ID for Lemon Squeezy integration
## API Endpoints
|
apps/api/src/service.ts
Outdated
| }), | ||
| ); | ||
|
|
||
| return buildDeploymentRowsFromRuns(events, runsByEventId, serverId); |
There was a problem hiding this comment.
Events beyond the 50-limit always show as "pending"
fetchDeploymentJobs slices requestedForServer to 50 events for run fetching (toFetch), but then passes the full events list to buildDeploymentRowsFromRuns. Inside that function, all events matching the server ID are iterated — including events at positions 51+. For those events, runsByEventId.get(ev.id) returns undefined, so runs = [], and the code creates a row with state: "pending" — even though those deployments may have completed or failed.
Fix: pass toFetch instead of events (all events in toFetch already match serverId, so the filter inside buildDeploymentRowsFromRuns is harmless):
| return buildDeploymentRowsFromRuns(events, runsByEventId, serverId); | |
| return buildDeploymentRowsFromRuns(toFetch, runsByEventId, serverId); |
| } | ||
| rows.sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)); | ||
| } else { | ||
| const jobs = await myQueue.getJobs(); |
There was a problem hiding this comment.
Sequential server fetching causes unnecessary latency
Each fetchDeployApiJobs call is awaited in sequence. With multiple servers, the total time is the sum of all individual request latencies. Using Promise.all would fetch all servers concurrently:
| } | |
| rows.sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)); | |
| } else { | |
| const jobs = await myQueue.getJobs(); | |
| const serverRowsArrays = await Promise.all( | |
| servers.map(({ serverId }) => fetchDeployApiJobs(serverId)), | |
| ); | |
| rows = serverRowsArrays.flat(); |
| Cancel | ||
| </Button> | ||
| )} | ||
| </div> |
There was a problem hiding this comment.
colSpan is one more than the actual column count
The table has 9 columns (Job ID, Label, Type, State, Added, Processed, Finished, Error, Actions) but colSpan={10} is specified for the empty state cell. While browsers handle this gracefully, it should match the actual column count.
| </div> | |
| <TableCell colSpan={9} className="text-center py-12"> |
apps/api/src/service.ts
Outdated
| const DEFAULT_MAX_EVENTS = 500; | ||
|
|
||
| const MAX_EVENTS = DEFAULT_MAX_EVENTS; |
There was a problem hiding this comment.
Constants defined after their first use
DEFAULT_MAX_EVENTS and MAX_EVENTS are declared at the bottom of the file (lines 238–240) but MAX_EVENTS is referenced in fetchInngestEvents at line 58. This works at runtime because the reference is inside a function body (evaluated lazily), but it is confusing to readers. Moving the constant declarations to the top of the file is the conventional approach:
| const DEFAULT_MAX_EVENTS = 500; | |
| const MAX_EVENTS = DEFAULT_MAX_EVENTS; | |
| const DEFAULT_MAX_EVENTS = 500; | |
| const MAX_EVENTS = DEFAULT_MAX_EVENTS; | |
(Place these lines near the top of the file, after the type definitions, and remove the current declarations at the bottom.)
Updated the event fetching logic to utilize Promise.all for concurrent API calls, enhancing performance. Adjusted the UI table layout by modifying the column span for better alignment and presentation of the empty queue state. Introduced constants for maximum events to improve code clarity.
What is this PR about?
Please describe in a short paragraph what this PR is about.
Checklist
Before submitting this PR, please make sure that:
canarybranch.Issues related (if applicable)
Screenshots (if applicable)
Greptile Summary
This PR adds an organization-level deployments dashboard with two tabs: a centralized Deployments view (all application and compose deployments across the org, with filtering, sorting, and pagination) and a Queue view (live job/run status from BullMQ in self-hosted mode or Inngest in cloud mode). A new
/jobsAPI endpoint is added to theapps/apiserver for fetching Inngest run state in a BullMQ-compatible shape.Key changes:
findAllDeploymentsCentralizedservice function with correct org-scoped and member-access-restricted queriesallCentralizedandqueueListtRPC procedures with appropriate authorizationapps/api/src/service.tsimplementing Inngest event + run fetchingfetchDeploymentJobs: the full event list is passed tobuildDeploymentRowsFromRunsbut only the first 50 events per server have their runs populated, causing events beyond position 50 to always display as"pending"regardless of their actual statequeueListfetches each server's jobs sequentially rather than concurrently, which will add latency when an org has multiple serversConfidence Score: 3/5
buildDeploymentRowsFromRunscall is fixed.fetchDeploymentJobs— events beyond the first 50 fetched for a server will always render as "pending" in the Queue tab due to passing the full unfiltered event list tobuildDeploymentRowsFromRunsinstead of the slicedtoFetchlist. This is a functional bug that will show stale/incorrect state to users. The sequential server fetching is a performance concern but not a correctness issue.apps/api/src/service.tsneeds thebuildDeploymentRowsFromRunscall fixed (passtoFetchinstead ofevents).apps/dokploy/server/api/routers/deployment.tsshould parallelize server fetching withPromise.all.Last reviewed commit: edceebe