filed

Job queue using FUSE

git clone git://mccd.space/filed

commit 605a6c515830a2686d84e78ef6b1f4a1430e051a
parent eb48a9bef8f67523d79bb32b171968172f35b397
Author: Marc Coquand <marc@coquand.email>
Date:   Wed, 17 Dec 2025 12:14:14 +0100

Add support for killing jobs

Diffstat:
Mfiled.1.scd | 3++-
Mjobdir.go | 12+++++++++---
Mmanager.go | 3++-
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/filed.1.scd b/filed.1.scd
@@ -23,7 +23,8 @@ directories are:
 	is the command that will be executed with sh.
 
 	*/active* - currently running jobs. It is possible to access logs of
-	the running jobs by inspecting the files.
+	the running jobs by inspecting the files. It is also possible to 
+	remove an active job, which will kill the process.
 
 	*/failed* - jobs that exceeded retry count. You can retry a job by
 	moving them back to pending. You can also safely remove jobs here.
diff --git a/jobdir.go b/jobdir.go
@@ -79,10 +79,15 @@ func (jd JobDir) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
 		return syscall.EIO
 	}
 	if job.State == store.StateRunning {
-		// XXX Delete the running job instead
-		return syscall.EPERM
+		val, ok := jd.manager.activeJobs.Load(job.ID)
+		if !ok {
+			// Assume that job is already complete
+			return jd.manager.store.DeleteJob(job.ID)
+		}
+		activeJob := val.(*ActiveJob)
+		activeJob.cancel()
 	}
-	return jd.manager.store.DeleteJob(req.Name)
+	return jd.manager.store.DeleteJob(job.ID)
 }
 
 func (d JobDir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Node) error {
@@ -97,6 +102,7 @@ func (d JobDir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.N
 	}
 
 	if req.OldName != req.NewName {
+		// XXX Maybe support?
 		slog.Warn("Renaming job IDs is not supported", "old", req.OldName, "new", req.NewName)
 		return syscall.EPERM
 	}
diff --git a/manager.go b/manager.go
@@ -19,6 +19,7 @@ type JobManager struct {
 
 type ActiveJob struct {
 	mu     sync.Mutex
+	cancel context.CancelFunc
 	output bytes.Buffer
 }
 
@@ -107,7 +108,7 @@ func (jm *JobManager) runJob(id, commandStr string) {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout_seconds)*time.Second)
 	defer cancel()
 
-	active := &ActiveJob{}
+	active := &ActiveJob{cancel: cancel}
 	jm.activeJobs.Store(id, active)
 	defer jm.activeJobs.Delete(id)