Dev command engine URL now configurable via the webapp (#1948)

* return dev engine url from config call

* set and use engine url from dev config reply
This commit is contained in:
nicktrn
2025-04-18 11:11:11 +01:00
committed by GitHub
parent f683fe8d2d
commit aa74260646
5 changed files with 23 additions and 8 deletions
+3
View File
@@ -624,6 +624,9 @@ const EnvironmentSchema = z.object({
/** The maximum concurrent local run processes executing at once in dev */
DEV_MAX_CONCURRENT_RUNS: z.coerce.number().int().default(25),
/** The CLI should connect to this for dev runs */
DEV_ENGINE_URL: z.string().default(process.env.APP_ORIGIN ?? "http://localhost:3030"),
LEGACY_RUN_ENGINE_WORKER_ENABLED: z.string().default(process.env.WORKER_ENABLED ?? "true"),
LEGACY_RUN_ENGINE_WORKER_CONCURRENCY_WORKERS: z.coerce.number().int().default(2),
LEGACY_RUN_ENGINE_WORKER_CONCURRENCY_TASKS_PER_WORKER: z.coerce.number().int().default(1),
@@ -21,6 +21,7 @@ export const loader = createLoaderApiRoute(
dequeueIntervalWithRun: env.DEV_DEQUEUE_INTERVAL_WITH_RUN,
dequeueIntervalWithoutRun: env.DEV_DEQUEUE_INTERVAL_WITHOUT_RUN,
maxConcurrentRuns: env.DEV_MAX_CONCURRENT_RUNS,
engineUrl: env.DEV_ENGINE_URL,
});
} catch (error) {
logger.error("Failed to get dev settings", {
+16 -8
View File
@@ -45,12 +45,15 @@ import {
} from "@trigger.dev/core/v3/workers";
export class CliApiClient {
private engineURL: string;
constructor(
public readonly apiURL: string,
// TODO: consider making this required
public readonly accessToken?: string
) {
this.apiURL = apiURL.replace(/\/$/, "");
this.engineURL = this.apiURL;
}
async createAuthorizationCode() {
@@ -418,6 +421,7 @@ export class CliApiClient {
heartbeatRun: this.devHeartbeatRun.bind(this),
startRunAttempt: this.devStartRunAttempt.bind(this),
completeRunAttempt: this.devCompleteRunAttempt.bind(this),
setEngineURL: this.setEngineURL.bind(this),
} as const;
}
@@ -486,7 +490,7 @@ export class CliApiClient {
throw new Error("devConfig: No access token");
}
return wrapZodFetch(DevConfigResponseBody, `${this.apiURL}/engine/v1/dev/config`, {
return wrapZodFetch(DevConfigResponseBody, `${this.engineURL}/engine/v1/dev/config`, {
headers: {
Authorization: `Bearer ${this.accessToken}`,
Accept: "application/json",
@@ -503,7 +507,7 @@ export class CliApiClient {
const maxRetries = 5;
const retryDelay = 1000; // Start with 1 second delay
const eventSource = new EventSource(`${this.apiURL}/engine/v1/dev/presence`, {
const eventSource = new EventSource(`${this.engineURL}/engine/v1/dev/presence`, {
fetch: (input, init) =>
fetch(input, {
...init,
@@ -557,7 +561,7 @@ export class CliApiClient {
throw new Error("devConfig: No access token");
}
return wrapZodFetch(DevDequeueResponseBody, `${this.apiURL}/engine/v1/dev/dequeue`, {
return wrapZodFetch(DevDequeueResponseBody, `${this.engineURL}/engine/v1/dev/dequeue`, {
method: "POST",
headers: {
Authorization: `Bearer ${this.accessToken}`,
@@ -575,7 +579,7 @@ export class CliApiClient {
throw new Error("devConfig: No access token");
}
return wrapZodFetch(z.unknown(), `${this.apiURL}/engine/v1/dev/runs/${runId}/logs/debug`, {
return wrapZodFetch(z.unknown(), `${this.engineURL}/engine/v1/dev/runs/${runId}/logs/debug`, {
method: "POST",
headers: {
Authorization: `Bearer ${this.accessToken}`,
@@ -591,7 +595,7 @@ export class CliApiClient {
): Promise<ApiResult<WorkloadRunLatestSnapshotResponseBody>> {
return wrapZodFetch(
WorkloadRunLatestSnapshotResponseBody,
`${this.apiURL}/engine/v1/dev/runs/${runId}/snapshots/latest`,
`${this.engineURL}/engine/v1/dev/runs/${runId}/snapshots/latest`,
{
method: "GET",
headers: {
@@ -609,7 +613,7 @@ export class CliApiClient {
): Promise<ApiResult<WorkloadHeartbeatResponseBody>> {
return wrapZodFetch(
WorkloadHeartbeatResponseBody,
`${this.apiURL}/engine/v1/dev/runs/${runId}/snapshots/${snapshotId}/heartbeat`,
`${this.engineURL}/engine/v1/dev/runs/${runId}/snapshots/${snapshotId}/heartbeat`,
{
method: "POST",
headers: {
@@ -628,7 +632,7 @@ export class CliApiClient {
): Promise<ApiResult<WorkloadRunAttemptStartResponseBody>> {
return wrapZodFetch(
WorkloadRunAttemptStartResponseBody,
`${this.apiURL}/engine/v1/dev/runs/${runId}/snapshots/${snapshotId}/attempts/start`,
`${this.engineURL}/engine/v1/dev/runs/${runId}/snapshots/${snapshotId}/attempts/start`,
{
method: "POST",
headers: {
@@ -648,7 +652,7 @@ export class CliApiClient {
): Promise<ApiResult<WorkloadRunAttemptCompleteResponseBody>> {
return wrapZodFetch(
WorkloadRunAttemptCompleteResponseBody,
`${this.apiURL}/engine/v1/dev/runs/${runId}/snapshots/${snapshotId}/attempts/complete`,
`${this.engineURL}/engine/v1/dev/runs/${runId}/snapshots/${snapshotId}/attempts/complete`,
{
method: "POST",
headers: {
@@ -659,4 +663,8 @@ export class CliApiClient {
}
);
}
private setEngineURL(engineURL: string) {
this.engineURL = engineURL.replace(/\/$/, "");
}
}
+2
View File
@@ -84,6 +84,8 @@ class DevSupervisor implements WorkerRuntime {
logger.debug("[DevSupervisor] Got dev settings", { settings: settings.data });
this.config = settings.data;
this.options.client.dev.setEngineURL(this.config.engineUrl);
const maxConcurrentRuns = Math.min(
this.config.maxConcurrentRuns,
this.options.args.maxConcurrentRuns ?? this.config.maxConcurrentRuns
+1
View File
@@ -432,6 +432,7 @@ export const DevConfigResponseBody = z.object({
dequeueIntervalWithRun: z.number(),
dequeueIntervalWithoutRun: z.number(),
maxConcurrentRuns: z.number(),
engineUrl: z.string(),
});
export type DevConfigResponseBody = z.infer<typeof DevConfigResponseBody>;