filed
Job queue using FUSE
git clone git://mccd.space/filed
| Log | Files | Refs | README | LICENSE |
commit 4d3ecaa53688cd0cd5c24245a0d076142b799a54 parent 0a4ee2af087fa3aa1f0973c5a35692772398dc98 Author: Marc Coquand <marc@coquand.email> Date: Sun, 14 Dec 2025 20:15:21 +0100 Move out jobs Diffstat:
| M | main.go | | | 6 | +++--- |
| R | store/store.go -> store/jobs.go | | | 0 | |
| A | store/jobs_test.go | | | 157 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | store/store_test.go | | | 157 | ------------------------------------------------------------------------------- |
4 files changed, 160 insertions(+), 160 deletions(-)
diff --git a/main.go b/main.go
@@ -152,13 +152,13 @@ func (d PendingDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *f
return f, f, nil
}
func (jd PendingDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
- slog.Info("FUSE: Lookup", "name", name)
+ slog.Debug("FUSE: Lookup", "name", name)
job, err := jd.manager.store.GetJob(name)
if err != nil {
return nil, syscall.ENOENT
}
if job.State == store.StatePending {
- slog.Info("FUSE: Found job", "id", job.ID)
+ slog.Debug("FUSE: Found job", "id", job.ID)
return &File{job, jd.manager}, nil
} else {
return nil, syscall.ENOENT
@@ -187,7 +187,7 @@ func (f File) Attr(ctx context.Context, a *fuse.Attr) error {
}
func (f *File) ReadAll(ctx context.Context) ([]byte, error) {
- slog.Info("FUSE: Read file content")
+ slog.Debug("FUSE: Read file content")
return f.readContent()
}
diff --git a/store/store.go b/store/jobs.go
diff --git a/store/jobs_test.go b/store/jobs_test.go
@@ -0,0 +1,157 @@
+package store
+
+import (
+ "path/filepath"
+ "testing"
+)
+
+// Create a new store in a temporary directory for each test.
+func setupTestDB(t *testing.T) *Store {
+ t.Helper()
+ tmpDir := t.TempDir()
+ dbPath := filepath.Join(tmpDir, "jobs.db")
+
+ store, err := NewStore(dbPath)
+ if err != nil {
+ t.Fatalf("Failed to create store: %v", err)
+ }
+
+ t.Cleanup(func() {
+ store.Close()
+ })
+
+ return store
+}
+
+func TestCreateJob(t *testing.T) {
+ s := setupTestDB(t)
+
+ jobID := "job-123"
+ cmd := "echo hello"
+
+ job, err := s.CreateJob(jobID, cmd)
+ if err != nil {
+ t.Fatalf("Failed to create job: %v", err)
+ }
+
+ if job.ID != jobID {
+ t.Errorf("Expected ID %s, got %s", jobID, job.ID)
+ }
+ if job.State != StatePending {
+ t.Errorf("Expected state %s, got %s", StatePending, job.State)
+ }
+ if job.Command != cmd {
+ t.Errorf("Expected command %s, got %s", cmd, job.Command)
+ }
+}
+
+func TestGetJob(t *testing.T) {
+ s := setupTestDB(t)
+ jobID := "test-job-get"
+
+ _, err := s.CreateJob(jobID, "sleep 1")
+ if err != nil {
+ t.Fatalf("CreateJob failed: %v", err)
+ }
+
+ // Retrieve it
+ job, err := s.GetJob(jobID)
+ if err != nil {
+ t.Fatalf("GetJob failed: %v", err)
+ }
+
+ if job.ID != jobID {
+ t.Errorf("Expected retrieved ID to match")
+ }
+}
+
+func TestLifecycleTransitions(t *testing.T) {
+ s := setupTestDB(t)
+ jobID := "lifecycle-1"
+
+ _, err := s.CreateJob(jobID, "echo hello")
+ if err != nil {
+ t.Fatalf("CreateJob failed: %v", err)
+ }
+
+ // 1. Pending -> Running (AttemptJob)
+ if err := s.AttemptJob(jobID); err != nil {
+ t.Fatalf("AttemptJob failed: %v", err)
+ }
+
+ j, _ := s.GetJob(jobID)
+ if j.State != StateRunning {
+ t.Errorf("Expected state Running, got %s", j.State)
+ }
+ if j.Attempts != 1 {
+ t.Errorf("Expected attempts 1, got %d", j.Attempts)
+ }
+
+ // 2. Running -> Completed
+ if err := s.CompleteJob(jobID, []byte("hello")); err != nil {
+ t.Fatalf("CompleteJob failed: %v", err)
+ }
+
+ j, _ = s.GetJob(jobID)
+ if j.State != StateCompleted {
+ t.Errorf("Expected state Completed, got %s", j.State)
+ }
+
+ // 3. Restart (Completed -> Pending)
+ if err := s.RestartJob(jobID, nil); err != nil {
+ t.Fatalf("RestartJob failed: %v", err)
+ }
+
+ j, _ = s.GetJob(jobID)
+ if j.State != StatePending {
+ t.Errorf("Expected state Pending after restart, got %s", j.State)
+ }
+}
+
+func TestListJobsByState(t *testing.T) {
+ s := setupTestDB(t)
+
+ s.CreateJob("p1", "cmd1")
+ s.CreateJob("p2", "cmd2")
+
+ s.CreateJob("c1", "cmd3")
+ s.CompleteJob("c1", []byte("out"))
+
+ // List Pending
+ pending, err := s.ListJobsByState(StatePending)
+ if err != nil {
+ t.Fatalf("ListJobsByState failed: %v", err)
+ }
+
+ if len(pending) != 2 {
+ t.Errorf("Expected 2 pending jobs, got %d", len(pending))
+ }
+
+ // List Completed
+ completed, err := s.ListJobsByState(StateCompleted)
+ if err != nil {
+ t.Fatalf("ListJobsByState failed: %v", err)
+ }
+ if len(completed) != 1 {
+ t.Errorf("Expected 1 completed job, got %d", len(completed))
+ }
+ if completed[0].ID != "c1" {
+ t.Errorf("Expected completed job to be c1")
+ }
+}
+
+func TestDeleteJob(t *testing.T) {
+ s := setupTestDB(t)
+ jobID := "del-1"
+
+ s.CreateJob(jobID, "cmd")
+
+ if err := s.DeleteJob(jobID); err != nil {
+ t.Fatalf("DeleteJob failed: %v", err)
+ }
+
+ _, err := s.GetJob(jobID)
+ if err == nil {
+ t.Error("Expected error getting deleted job, got nil")
+ }
+}
diff --git a/store/store_test.go b/store/store_test.go
@@ -1,157 +0,0 @@
-package store
-
-import (
- "path/filepath"
- "testing"
-)
-
-// Create a new store in a temporary directory for each test.
-func setupTestDB(t *testing.T) *Store {
- t.Helper()
- tmpDir := t.TempDir()
- dbPath := filepath.Join(tmpDir, "jobs.db")
-
- store, err := NewStore(dbPath)
- if err != nil {
- t.Fatalf("Failed to create store: %v", err)
- }
-
- t.Cleanup(func() {
- store.Close()
- })
-
- return store
-}
-
-func TestCreateJob(t *testing.T) {
- s := setupTestDB(t)
-
- jobID := "job-123"
- cmd := "echo hello"
-
- job, err := s.CreateJob(jobID, cmd)
- if err != nil {
- t.Fatalf("Failed to create job: %v", err)
- }
-
- if job.ID != jobID {
- t.Errorf("Expected ID %s, got %s", jobID, job.ID)
- }
- if job.State != StatePending {
- t.Errorf("Expected state %s, got %s", StatePending, job.State)
- }
- if job.Command != cmd {
- t.Errorf("Expected command %s, got %s", cmd, job.Command)
- }
-}
-
-func TestGetJob(t *testing.T) {
- s := setupTestDB(t)
- jobID := "test-job-get"
-
- _, err := s.CreateJob(jobID, "sleep 1")
- if err != nil {
- t.Fatalf("CreateJob failed: %v", err)
- }
-
- // Retrieve it
- job, err := s.GetJob(jobID)
- if err != nil {
- t.Fatalf("GetJob failed: %v", err)
- }
-
- if job.ID != jobID {
- t.Errorf("Expected retrieved ID to match")
- }
-}
-
-func TestLifecycleTransitions(t *testing.T) {
- s := setupTestDB(t)
- jobID := "lifecycle-1"
-
- _, err := s.CreateJob(jobID, "echo hello")
- if err != nil {
- t.Fatalf("CreateJob failed: %v", err)
- }
-
- // 1. Pending -> Running (AttemptJob)
- if err := s.AttemptJob(jobID); err != nil {
- t.Fatalf("AttemptJob failed: %v", err)
- }
-
- j, _ := s.GetJob(jobID)
- if j.State != StateRunning {
- t.Errorf("Expected state Running, got %s", j.State)
- }
- if j.Attempts != 1 {
- t.Errorf("Expected attempts 1, got %d", j.Attempts)
- }
-
- // 2. Running -> Completed
- if err := s.CompleteJob(jobID, []byte("hello")); err != nil {
- t.Fatalf("CompleteJob failed: %v", err)
- }
-
- j, _ = s.GetJob(jobID)
- if j.State != StateCompleted {
- t.Errorf("Expected state Completed, got %s", j.State)
- }
-
- // 3. Restart (Completed -> Pending)
- if err := s.RestartJob(jobID); err != nil {
- t.Fatalf("RestartJob failed: %v", err)
- }
-
- j, _ = s.GetJob(jobID)
- if j.State != StatePending {
- t.Errorf("Expected state Pending after restart, got %s", j.State)
- }
-}
-
-func TestListJobsByState(t *testing.T) {
- s := setupTestDB(t)
-
- s.CreateJob("p1", "cmd1")
- s.CreateJob("p2", "cmd2")
-
- s.CreateJob("c1", "cmd3")
- s.CompleteJob("c1", []byte("out"))
-
- // List Pending
- pending, err := s.ListJobsByState(StatePending)
- if err != nil {
- t.Fatalf("ListJobsByState failed: %v", err)
- }
-
- if len(pending) != 2 {
- t.Errorf("Expected 2 pending jobs, got %d", len(pending))
- }
-
- // List Completed
- completed, err := s.ListJobsByState(StateCompleted)
- if err != nil {
- t.Fatalf("ListJobsByState failed: %v", err)
- }
- if len(completed) != 1 {
- t.Errorf("Expected 1 completed job, got %d", len(completed))
- }
- if completed[0].ID != "c1" {
- t.Errorf("Expected completed job to be c1")
- }
-}
-
-func TestDeleteJob(t *testing.T) {
- s := setupTestDB(t)
- jobID := "del-1"
-
- s.CreateJob(jobID, "cmd")
-
- if err := s.DeleteJob(jobID); err != nil {
- t.Fatalf("DeleteJob failed: %v", err)
- }
-
- _, err := s.GetJob(jobID)
- if err == nil {
- t.Error("Expected error getting deleted job, got nil")
- }
-}