···11+# Use the official Bun image as base
22+FROM oven/bun:1.0 AS builder
33+44+# Set working directory
55+WORKDIR /app
66+77+# Copy root workspace files
88+COPY package.json bun.lockb ./
99+1010+# Copy turbo.json
1111+COPY turbo.json ./
1212+1313+# Copy workspace packages
1414+COPY packages/db/ ./packages/db/
1515+COPY packages/lexicons/ ./packages/lexicons/
1616+COPY packages/tsconfig/ ./packages/tsconfig/
1717+1818+# Copy the aqua app
1919+COPY apps/aqua/ ./apps/aqua/
2020+2121+# Install dependencies
2222+RUN bun install
2323+2424+# Build workspace packages (if needed)
2525+RUN bun run build --filter=@teal/db
2626+RUN bun run build --filter=@teal/lexicons
2727+2828+# Build the aqua app
2929+WORKDIR /app/apps/aqua
3030+RUN bun run build
3131+3232+# Start production image (node lts ideally)
3333+FROM node:bookworm-slim
3434+3535+WORKDIR /app
3636+3737+# Copy built assets from builder
3838+COPY --from=builder /app/apps/aqua/dist ./dist
3939+# copy base node modules
4040+COPY --from=builder /app/node_modules ./node_modules
4141+COPY --from=builder /app/apps/aqua/node_modules ./node_modules
4242+COPY --from=builder /app/apps/aqua/package.json ./
4343+4444+# move public to cwd
4545+RUN mv ./dist/public ./public
4646+4747+# Set environment variables
4848+ENV NODE_ENV=production
4949+5050+# Expose the port your app runs on
5151+EXPOSE 3000
5252+5353+# Start the application
5454+CMD ["npm", "run", "start"]
···11-package main
22-33-import (
44- "fmt"
55- "sync"
66-77- server "viridian/server"
88- worker "viridian/worker"
99-)
1010-1111-func main() {
1212- var wg sync.WaitGroup
1313-1414- // Run the server in a goroutine
1515- go server.RunServer()
1616-1717- // Simulate workers, each running in a separate goroutine
1818- workerCount := worker.GetCoreCount()
1919- fmt.Printf("Starting %d workers\n", workerCount)
2020- for i := 1; i <= workerCount; i++ {
2121- fmt.Printf("Starting worker %d\n", i)
2222- workerID := fmt.Sprintf("worker-%d", i)
2323- wg.Add(1)
2424- go worker.RunWorker(workerID, &wg)
2525- }
2626-2727- // Wait for all workers to complete (this won't happen in this example since workers run indefinitely)
2828- wg.Wait()
2929-}
···11-package server
22-33-import (
44- "fmt"
55- "time"
66-77- "viridian/types"
88-99- zmq "github.com/pebbe/zmq4"
1010-)
1111-1212-// RunServer launches the server that distributes jobs to workers
1313-func RunServer() {
1414- server := &types.Server{
1515- Jobs: []types.Job{{"job1", "pending"}, {"job2", "pending"}, {"job3", "pending"}},
1616- WorkerJobs: make(map[string]string),
1717- JobStatus: make(map[string]string),
1818- }
1919-2020- // Initialize job status
2121- for _, job := range server.Jobs {
2222- server.JobStatus[job.ID] = "pending"
2323- }
2424-2525- // Create a ZeroMQ ROUTER socket for distributing jobs
2626- socket, _ := zmq.NewSocket(zmq.ROUTER)
2727- defer socket.Close()
2828- socket.Bind("tcp://*:5555")
2929-3030- for len(server.Jobs) > 0 {
3131- // Wait for a worker to send a ready message
3232- workerAddr, _ := socket.RecvMessage(0)
3333-3434- fmt.Printf("Received ready message from worker %s\n", workerAddr)
3535-3636- fmt.Print(workerAddr[2])
3737-3838- // Lock jobs to pick the next one safely
3939- server.Mu.Lock()
4040- if len(server.Jobs) == 0 {
4141- server.Mu.Unlock()
4242- continue
4343- }
4444- job := server.Jobs[0]
4545- server.Jobs = server.Jobs[1:]
4646- server.Mu.Unlock()
4747-4848- // Track the job for this worker
4949- server.TrackJob(workerAddr[0], job.ID)
5050-5151- // Send job to the worker
5252- fmt.Printf("Sending job %s to worker %s\n", job.ID, workerAddr[0])
5353- socket.SendMessage(workerAddr[0], "", job.ID)
5454-5555- time.Sleep(1 * time.Second) // Simulate a delay
5656-5757- // In a real-world scenario, this would be based on a worker response
5858- server.MarkJobCompleted(workerAddr[0])
5959- }
6060-6161- fmt.Println("All jobs processed")
6262-}
-46
apps/viridian/types/types.go
···11-package types
22-33-import (
44- "strconv"
55- "sync"
66-)
77-88-// Job represents a job with an ID and status
99-type Job struct {
1010- ID string
1111- Status string
1212-}
1313-1414-// Server represents the state of the server, including jobs, worker-job associations, and job status
1515-type Server struct {
1616- Jobs []Job // Job queue
1717- WorkerJobs map[string]string // Mapping worker ID -> job ID
1818- JobStatus map[string]string // Mapping job ID -> status
1919- Mu sync.Mutex // Mutex to handle concurrency
2020-}
2121-2222-func (s *Server) AddJob() Job {
2323- s.Mu.Lock()
2424- defer s.Mu.Unlock()
2525- job := Job{"job" + strconv.Itoa(len(s.Jobs)), "pending"}
2626- s.Jobs = append(s.Jobs, job)
2727-2828- return job
2929-}
3030-3131-// TrackJob assigns a job to a worker and marks it as in-progress
3232-func (s *Server) TrackJob(workerID, jobID string) {
3333- s.Mu.Lock()
3434- defer s.Mu.Unlock()
3535- s.WorkerJobs[workerID] = jobID
3636- s.JobStatus[jobID] = "in-progress"
3737-}
3838-3939-// MarkJobCompleted marks a job as completed and removes the worker-job association
4040-func (s *Server) MarkJobCompleted(workerID string) {
4141- s.Mu.Lock()
4242- defer s.Mu.Unlock()
4343- jobID := s.WorkerJobs[workerID]
4444- s.JobStatus[jobID] = "completed"
4545- delete(s.WorkerJobs, workerID) // Remove worker-job association
4646-}
···33import process from "node:process";
44import path from "node:path";
5566-console.log(
77- "Loading SQLite file at",
88- path.join(process.cwd(), "../../db.sqlite"),
99-);
66+console.log("Loading SQLite file at", path.join(process.cwd(), "./db.sqlite"));
107118export const db = drizzle({
129 connection:
1310 // default is in project root / db.sqlite
1411 process.env.DATABASE_URL ??
1515- "file:" + path.join(process.cwd(), "../../db.sqlite"),
1212+ "file:" + path.join(process.cwd(), "./db.sqlite"),
1613 // doesn't seem to work?
1714 //casing: "snake_case",
1815 schema: schema,
-2
packages/jetstring/src/index.ts
···22import { db } from "@teal/db/connect";
33import { status } from "@teal/db/schema";
44import { CommitCreateEvent, Jetstream } from "@skyware/jetstream";
55-import { server } from "@teal/lexicons/generated/server/types";
66-import ws from "ws";
7586class Handler {
97 private static instance: Handler;