You've already forked agentic-coding-workflow
feat(jobs): migration 0005 + errs codes for jobs module
This commit is contained in:
@@ -66,6 +66,13 @@ const (
|
|||||||
// Storage 域
|
// Storage 域
|
||||||
CodeStoragePutFailed Code = "storage.put_failed"
|
CodeStoragePutFailed Code = "storage.put_failed"
|
||||||
CodeStorageGetFailed Code = "storage.get_failed"
|
CodeStorageGetFailed Code = "storage.get_failed"
|
||||||
|
|
||||||
|
// Jobs 域
|
||||||
|
CodeJobNotFound Code = "job.not_found"
|
||||||
|
CodeJobInvalidType Code = "job.invalid_type"
|
||||||
|
CodeJobPayloadInvalid Code = "job.payload_invalid"
|
||||||
|
CodeJobPayloadTooLarge Code = "job.payload_too_large"
|
||||||
|
CodeWebhookNotConfigured Code = "webhook.not_configured"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppError is the application's structured error type. It carries a stable
|
// AppError is the application's structured error type. It carries a stable
|
||||||
@@ -171,6 +178,12 @@ func HTTPStatus(code Code) int {
|
|||||||
return http.StatusBadGateway
|
return http.StatusBadGateway
|
||||||
case CodeLLMContextTooLong:
|
case CodeLLMContextTooLong:
|
||||||
return http.StatusBadRequest
|
return http.StatusBadRequest
|
||||||
|
case CodeJobNotFound:
|
||||||
|
return http.StatusNotFound
|
||||||
|
case CodeJobInvalidType, CodeJobPayloadInvalid, CodeJobPayloadTooLarge:
|
||||||
|
return http.StatusBadRequest
|
||||||
|
case CodeWebhookNotConfigured:
|
||||||
|
return http.StatusServiceUnavailable
|
||||||
default:
|
default:
|
||||||
return http.StatusInternalServerError
|
return http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ func TestHTTPStatus(t *testing.T) {
|
|||||||
// Storage codes
|
// Storage codes
|
||||||
CodeStoragePutFailed: http.StatusBadGateway,
|
CodeStoragePutFailed: http.StatusBadGateway,
|
||||||
CodeStorageGetFailed: http.StatusBadGateway,
|
CodeStorageGetFailed: http.StatusBadGateway,
|
||||||
|
// Jobs codes
|
||||||
|
CodeJobNotFound: http.StatusNotFound,
|
||||||
|
CodeJobInvalidType: http.StatusBadRequest,
|
||||||
|
CodeJobPayloadInvalid: http.StatusBadRequest,
|
||||||
|
CodeJobPayloadTooLarge: http.StatusBadRequest,
|
||||||
|
CodeWebhookNotConfigured: http.StatusServiceUnavailable,
|
||||||
}
|
}
|
||||||
for code, want := range cases {
|
for code, want := range cases {
|
||||||
require.Equal(t, want, HTTPStatus(code), "code=%s", code)
|
require.Equal(t, want, HTTPStatus(code), "code=%s", code)
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE workspace_worktrees DROP COLUMN IF EXISTS prune_warning_at;
|
||||||
|
DROP TABLE IF EXISTS jobs;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
-- ============ jobs(DB-backed 事件型任务) ============
|
||||||
|
CREATE TABLE jobs (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||||
|
status TEXT NOT NULL DEFAULT 'pending',
|
||||||
|
scheduled_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
attempts INT NOT NULL DEFAULT 0,
|
||||||
|
max_attempts INT NOT NULL DEFAULT 5,
|
||||||
|
leased_at TIMESTAMPTZ,
|
||||||
|
leased_by TEXT,
|
||||||
|
last_error TEXT,
|
||||||
|
completed_at TIMESTAMPTZ,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
CONSTRAINT jobs_status_check CHECK (status IN ('pending','running','completed','dead'))
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_jobs_pickup ON jobs(scheduled_at, status) WHERE status = 'pending';
|
||||||
|
CREATE INDEX idx_jobs_lease ON jobs(leased_at) WHERE status = 'running';
|
||||||
|
CREATE INDEX idx_jobs_purge ON jobs(completed_at) WHERE status IN ('completed', 'dead');
|
||||||
|
|
||||||
|
-- ============ ALTER workspace_worktrees: add prune_warning_at ============
|
||||||
|
ALTER TABLE workspace_worktrees
|
||||||
|
ADD COLUMN prune_warning_at TIMESTAMPTZ;
|
||||||
Reference in New Issue
Block a user