- Add worker storage layer with PostgreSQL/sqlc setup - Add migration files for worker backbone schema - Add job runner and built-in jobs implementation - Add Redis key definitions for worker state management - Archive socket-session-loop milestone (completed/renamed) - Update roadmap current.md and foundation-alignment phase - Add socket endpoint integration and runtime smoke tests - Add infra-check, worker-storage-check, worker-storage-gen CLI tools - Update API socket server and config - Add pubspec dependencies and client socket endpoint changes - Add config tests for API and worker services
110 lines
2.4 KiB
Go
110 lines
2.4 KiB
Go
package jobs
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func TestRunnerDispatchesRegisteredHandler(t *testing.T) {
|
|
runner := NewRunner()
|
|
called := false
|
|
var receivedPayload json.RawMessage
|
|
|
|
testKind := Kind("test_job")
|
|
runner.Register(testKind, func(ctx context.Context, payload json.RawMessage) error {
|
|
called = true
|
|
receivedPayload = payload
|
|
return nil
|
|
})
|
|
|
|
job := Job{
|
|
ID: "job-1",
|
|
Kind: testKind,
|
|
Payload: json.RawMessage(`{"key":"value"}`),
|
|
}
|
|
|
|
err := runner.Execute(context.Background(), job)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if !called {
|
|
t.Error("expected handler to be called, but it was not")
|
|
}
|
|
|
|
if string(receivedPayload) != `{"key":"value"}` {
|
|
t.Errorf("expected payload %q, got %q", `{"key":"value"}`, string(receivedPayload))
|
|
}
|
|
}
|
|
|
|
func TestRunnerRejectsUnknownKind(t *testing.T) {
|
|
runner := NewRunner()
|
|
job := Job{
|
|
ID: "job-2",
|
|
Kind: Kind("non_existent"),
|
|
}
|
|
|
|
err := runner.Execute(context.Background(), job)
|
|
if err == nil {
|
|
t.Fatal("expected error for unknown job kind, got nil")
|
|
}
|
|
}
|
|
|
|
func TestRunnerRespectsCanceledContext(t *testing.T) {
|
|
runner := NewRunner()
|
|
testKind := Kind("cancellation_test")
|
|
|
|
runner.Register(testKind, func(ctx context.Context, payload json.RawMessage) error {
|
|
return nil
|
|
})
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel() // Cancel context immediately
|
|
|
|
job := Job{
|
|
ID: "job-3",
|
|
Kind: testKind,
|
|
}
|
|
|
|
err := runner.Execute(ctx, job)
|
|
if err == nil {
|
|
t.Fatal("expected error due to canceled context, got nil")
|
|
}
|
|
if !errors.Is(err, context.Canceled) {
|
|
t.Errorf("expected error %v, got %v", context.Canceled, err)
|
|
}
|
|
}
|
|
|
|
func TestRunnerHandlesPanic(t *testing.T) {
|
|
runner := NewRunner()
|
|
panicKind := Kind("panic_job")
|
|
|
|
runner.Register(panicKind, func(ctx context.Context, payload json.RawMessage) error {
|
|
panic("something went critically wrong")
|
|
})
|
|
|
|
job := Job{
|
|
ID: "job-4",
|
|
Kind: panicKind,
|
|
}
|
|
|
|
err := runner.Execute(context.Background(), job)
|
|
if err == nil {
|
|
t.Fatal("expected error from panic recovery, got nil")
|
|
}
|
|
if err.Error() != "job panicked: something went critically wrong" {
|
|
t.Errorf("unexpected error message: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRegisterBuiltins(t *testing.T) {
|
|
runner := NewRunner()
|
|
RegisterBuiltins(runner)
|
|
|
|
expectedCount := 3
|
|
if runner.Len() != expectedCount {
|
|
t.Errorf("expected %d registered built-in handlers, got %d", expectedCount, runner.Len())
|
|
}
|
|
}
|