diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98e6ef6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.db diff --git a/cmd/alpenqueue/main.go b/cmd/alpenqueue/main.go index 5e3881a..5ec6e0c 100644 --- a/cmd/alpenqueue/main.go +++ b/cmd/alpenqueue/main.go @@ -1,12 +1,42 @@ package main import ( + "alpenqueue/pkg/db" + "alpenqueue/pkg/worker" + "fmt" + "log" "net/http" ) func main() { + database, err := db.Init("./alpenqueue.db") + if err != nil { + log.Fatal(err) + } + defer database.Close() + + worker.Start(database) + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("AlpenQueue running!")) }) + + http.HandleFunc("/jobs", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + id, err := db.CreateJob(database) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, "Job %d created\n", id) + }) + + log.Println("Server starting on :8080") http.ListenAndServe(":8080", nil) } diff --git a/go.mod b/go.mod index 21bc865..10bcc37 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module alpenqueue go 1.25.4 + +require github.com/mattn/go-sqlite3 v1.14.32 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..66f7516 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= +github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= diff --git a/pkg/db/db.go b/pkg/db/db.go new file mode 100644 index 0000000..fd75fcd --- /dev/null +++ b/pkg/db/db.go @@ -0,0 +1,66 @@ +package db + +import ( + "database/sql" + "time" + + _ "github.com/mattn/go-sqlite3" +) + +type Job struct { + ID int + Status string + CreatedAt time.Time +} + +func Init(dbPath string) (*sql.DB, error) { + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return nil, err + } + + schema := ` + CREATE TABLE IF NOT EXISTS jobs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + status TEXT NOT NULL DEFAULT 'pending', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + );` + + _, err = db.Exec(schema) + if err != nil { + return nil, err + } + + return db, nil +} + +func CreateJob(db *sql.DB) (int64, error) { + result, err := db.Exec("INSERT INTO jobs (status) VALUES ('pending')") + if err != nil { + return 0, err + } + return result.LastInsertId() +} + +func GetPendingJobs(db *sql.DB) ([]Job, error) { + rows, err := db.Query("SELECT id, status, created_at FROM jobs WHERE status = 'pending'") + if err != nil { + return nil, err + } + defer rows.Close() + + var jobs []Job + for rows.Next() { + var job Job + if err := rows.Scan(&job.ID, &job.Status, &job.CreatedAt); err != nil { + return nil, err + } + jobs = append(jobs, job) + } + return jobs, nil +} + +func MarkJobDone(db *sql.DB, id int) error { + _, err := db.Exec("UPDATE jobs SET status = 'done' WHERE id = ?", id) + return err +} diff --git a/pkg/worker/worker.go b/pkg/worker/worker.go new file mode 100644 index 0000000..fe7e525 --- /dev/null +++ b/pkg/worker/worker.go @@ -0,0 +1,34 @@ +package worker + +import ( + "alpenqueue/pkg/db" + "database/sql" + "log" + "time" +) + +func Start(database *sql.DB) { + go func() { + for { + jobs, err := db.GetPendingJobs(database) + if err != nil { + log.Printf("Error fetching jobs: %v", err) + time.Sleep(5 * time.Second) + continue + } + + for _, job := range jobs { + log.Printf("Processing job %d", job.ID) + time.Sleep(2 * time.Second) + + if err := db.MarkJobDone(database, job.ID); err != nil { + log.Printf("Error marking job %d done: %v", job.ID, err) + } else { + log.Printf("Job %d completed", job.ID) + } + } + + time.Sleep(5 * time.Second) + } + }() +}