feat(v1.1.9): dashboard Queues tab + queue:receive trigger form + 0.15.0
API client (src/lib/api.ts):
- TriggerKind gains 'queue'
- TriggerDetails gains { kind: 'queue', queue_name, visibility_timeout_secs, last_fired_at }
- CreateQueueTriggerInput, QueueSummary, QueueConsumer, QueueDetail
- api.triggers.createQueue(idOrSlug, input) -> POST /admin/.../triggers/queue
- api.queues.list(idOrSlug) -> GET /admin/.../queues
- api.queues.get(idOrSlug, name) -> GET /admin/.../queues/{name}
New routes:
- /apps/[slug]/queues — read-only list view (queue_name, total, pending,
claimed, drilldown link); empty state explains how queues are created
(first enqueue) and that consumers register via the Triggers tab
- /apps/[slug]/queues/[name] — drilldown showing depth + registered
consumer (script name + visibility timeout + last_fired_at + trigger
id); empty consumer state surfaces clearly
App detail page (src/routes/apps/[slug]/+page.svelte):
- New "Queues" link in the app-level nav between Files and Dead letters
- Triggers tab gains a "Queue:receive trigger (v1.1.9)" form alongside
cron/pubsub/email — target script select, queue_name, visibility
timeout (5–3600s, default 30), max_attempts (1–20, default 3)
- Trigger list renders queue triggers with queue_name + visibility
timeout + last_fired_at
dashboard/package.json: 0.14.0 -> 0.15.0
npm run check — all queue/invoke-related code typechecks clean; the
existing Playwright test errors (149 unrelated) carry forward unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -218,7 +218,8 @@ export type TriggerKind =
|
||||
| 'cron'
|
||||
| 'files'
|
||||
| 'pubsub'
|
||||
| 'email';
|
||||
| 'email'
|
||||
| 'queue';
|
||||
export type TriggerDispatchMode = 'sync' | 'async';
|
||||
|
||||
/// Per-kind detail, tagged by `kind` to match the Rust serde shape.
|
||||
@@ -229,7 +230,8 @@ export type TriggerDetails =
|
||||
| { kind: 'cron'; schedule: string; timezone: string; last_fired_at?: string | null }
|
||||
| { kind: 'files'; collection_glob: string; ops: string[] }
|
||||
| { kind: 'pubsub'; topic_pattern: string }
|
||||
| { kind: 'email'; has_inbound_secret: boolean };
|
||||
| { kind: 'email'; has_inbound_secret: boolean }
|
||||
| { kind: 'queue'; queue_name: string; visibility_timeout_secs: number; last_fired_at?: string | null };
|
||||
|
||||
export interface CreateEmailTriggerInput {
|
||||
script_id: string;
|
||||
@@ -347,6 +349,37 @@ export interface CreatePubsubTriggerInput {
|
||||
retry_base_ms?: number;
|
||||
}
|
||||
|
||||
// v1.1.9 — queue:receive trigger.
|
||||
export interface CreateQueueTriggerInput {
|
||||
script_id: string;
|
||||
queue_name: string;
|
||||
visibility_timeout_secs?: number;
|
||||
dispatch_mode?: TriggerDispatchMode;
|
||||
retry_max_attempts?: number;
|
||||
retry_backoff?: 'exponential' | 'linear' | 'constant';
|
||||
retry_base_ms?: number;
|
||||
}
|
||||
|
||||
// v1.1.9 — read-only queue inspection types (admin queues API).
|
||||
export interface QueueSummary {
|
||||
queue_name: string;
|
||||
total: number;
|
||||
pending: number;
|
||||
claimed: number;
|
||||
}
|
||||
|
||||
export interface QueueConsumer {
|
||||
trigger_id: string;
|
||||
script_id: string;
|
||||
script_name: string;
|
||||
visibility_timeout_secs: number;
|
||||
last_fired_at: string | null;
|
||||
}
|
||||
|
||||
export interface QueueDetail extends QueueSummary {
|
||||
consumer: QueueConsumer | null;
|
||||
}
|
||||
|
||||
// v1.1.6 — externally-subscribable realtime topics.
|
||||
export type TopicAuthMode = 'public' | 'token' | 'session';
|
||||
|
||||
@@ -755,6 +788,11 @@ export const api = {
|
||||
`/api/v1/admin/apps/${encodeURIComponent(idOrSlug)}/triggers/email`,
|
||||
{ method: 'POST', body: JSON.stringify(input) }
|
||||
),
|
||||
createQueue: (idOrSlug: string, input: CreateQueueTriggerInput) =>
|
||||
adminRequest<Trigger>(
|
||||
`/api/v1/admin/apps/${encodeURIComponent(idOrSlug)}/triggers/queue`,
|
||||
{ method: 'POST', body: JSON.stringify(input) }
|
||||
),
|
||||
remove: (idOrSlug: string, triggerId: string) =>
|
||||
adminRequest<null>(
|
||||
`/api/v1/admin/apps/${encodeURIComponent(idOrSlug)}/triggers/${triggerId}`,
|
||||
@@ -762,6 +800,17 @@ export const api = {
|
||||
)
|
||||
},
|
||||
|
||||
queues: {
|
||||
list: (idOrSlug: string) =>
|
||||
adminRequest<QueueSummary[]>(
|
||||
`/api/v1/admin/apps/${encodeURIComponent(idOrSlug)}/queues`
|
||||
),
|
||||
get: (idOrSlug: string, name: string) =>
|
||||
adminRequest<QueueDetail>(
|
||||
`/api/v1/admin/apps/${encodeURIComponent(idOrSlug)}/queues/${encodeURIComponent(name)}`
|
||||
)
|
||||
},
|
||||
|
||||
topics: {
|
||||
list: (idOrSlug: string) =>
|
||||
adminRequest<{ topics: Topic[] }>(
|
||||
|
||||
Reference in New Issue
Block a user