···11+CREATE TABLE `auth_session` (
22+ `key` text PRIMARY KEY NOT NULL,
33+ `session` text NOT NULL
44+);
55+--> statement-breakpoint
66+CREATE TABLE `auth_state` (
77+ `key` text PRIMARY KEY NOT NULL,
88+ `state` text NOT NULL
99+);
1010+--> statement-breakpoint
1111+CREATE TABLE `status` (
1212+ `uri` text PRIMARY KEY NOT NULL,
1313+ `authorDid` text NOT NULL,
1414+ `status` text NOT NULL,
1515+ `createdAt` text NOT NULL,
1616+ `indexedAt` text NOT NULL
1717+);
···11+PRIVATE_KEY_1={"kty":"EC","d":"8rx-D2vaik7FgRUaMeK_M8yZQ57J5NFs4MP6300_gek","use":"sig","crv":"P-256","kid":"44J2ZYr_4O3wp1B8GSRPvHMb7Cf506Nss3ISOplRx9I","x":"f9RLs9sqKyL38dPKsQaX-P_qTHVnNRCXuzkjbPvh7Ls","y":"ZnH5GuTAl5TTb-hZzsVgf1kUl4OB6qCS0PmM4_SPXvw","alg":"ES256"}
22+PRIVATE_KEY_2={"kty":"EC","d":"5Rk8UuCz-chUX_OZ4WgB7lb3OELn-xlGEedk4P-qY_M","use":"sig","crv":"P-256","kid":"kzDrzoJdNtK3bfTiuJYQZSk_Z7nsZqEpzqYSqHVBN_Q","x":"WuMNQ3slMhmvUJze-q4pxmC_Xqu5MkpkD3eSh1dPDBs","y":"0CS96lObk2UWnRbbrhQQDbduyZ_A4zKZtwSQTfqVkcU","alg":"ES256"}
33+PRIVATE_KEY_3={"kty":"EC","d":"GvpzAoGaHCG3OFe8qqi8FRs3WShGvS8OAOhjcN2vyuQ","use":"sig","crv":"P-256","kid":"y0HFLgCqOSwfbRJdO48dM8prLrLrT-qxNs_UrdvrbNQ","x":"VJ13t663tWZa67wUNQw26iU9iatIg4ZIklNKOrqMiYw","y":"Fqyc7qiOfwaYDXO259G8T66Wg2Kf_WLEjyi0ZenX2pI","alg":"ES256"}
44+NODE_ENV=development # Options: development, production
55+PORT=3000 # The port your server will listen on
66+HOST=localhost # Hostname for the server
77+PUBLIC_URL= # Set when deployed publicly, e.g. "https://mysite.com". Informs OAuth client id.
88+DB_PATH=:memory: # The SQLite database path. Leave as ":memory:" to use a temporary in-memory database.
99+# Secrets
1010+# Must set this in production. May be generated with `openssl rand -base64 33`=undefined
1111+# COOKIE_SECRET=""
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+import { ValidationResult, BlobRef } from '@atproto/lexicon'
55+import { lexicons } from '../../../lexicons'
66+import { isObj, hasProp } from '../../../util'
77+import { CID } from 'multiformats/cid'
88+99+export interface Record {
1010+ status: string
1111+ createdAt: string
1212+ [k: string]: unknown
1313+}
1414+1515+export function isRecord(v: unknown): v is Record {
1616+ return (
1717+ isObj(v) &&
1818+ hasProp(v, '$type') &&
1919+ (v.$type === 'xyz.statusphere.status#main' ||
2020+ v.$type === 'xyz.statusphere.status')
2121+ )
2222+}
2323+2424+export function validateRecord(v: unknown): ValidationResult {
2525+ return lexicons.validate('xyz.statusphere.status#main', v)
2626+}
+13
apps/aqua/src/lexicon/util.ts
···11+/**
22+ * GENERATED CODE - DO NOT MODIFY
33+ */
44+export function isObj(v: unknown): v is Record<string, unknown> {
55+ return typeof v === 'object' && v !== null
66+}
77+88+export function hasProp<K extends PropertyKey>(
99+ data: object,
1010+ prop: K,
1111+): data is Record<K, unknown> {
1212+ return prop in data
1313+}
···11+// @ts-ignore
22+import ssr from "uhtml/ssr";
33+import type initSSR from "uhtml/types/init-ssr";
44+import type { Hole } from "uhtml/types/keyed";
55+66+export type { Hole };
77+88+export const { html }: ReturnType<typeof initSSR> = ssr();
99+1010+export function page(hole: Hole) {
1111+ return `<!DOCTYPE html>\n${hole.toDOM().toString()}`;
1212+}
···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+}
···1111 // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12121313 /* Language and Environment */
1414- "target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
1414+ "target": "ES2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
1515 // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
1616 // "jsx": "preserve", /* Specify what JSX code is generated. */
1717 // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
···2525 // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26262727 /* Modules */
2828- "module": "ES2022", /* Specify what module code is generated. */
2828+ "module": "ES2022" /* Specify what module code is generated. */,
2929 // "rootDir": "./", /* Specify the root folder within your source files. */
3030- "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
3030+ "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
3131 // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
3232- // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
3232+ //"paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */,
3333 // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
3434 // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
3535- "types": ["bun-types"], /* Specify type package names to be included without being referenced in a source file. */
3535+ // "types": [] /* Specify type package names to be included without being referenced in a source file. */,
3636 // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
3737 // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
3838 // "resolveJsonModule": true, /* Enable importing .json files. */
···7171 /* Interop Constraints */
7272 // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
7373 // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
7474- "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
7474+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
7575 // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
7676- "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
7676+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
77777878 /* Type Checking */
7979- "strict": true, /* Enable all strict type-checking options. */
7979+ "strict": true /* Enable all strict type-checking options. */,
8080 // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
8181 // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
8282 // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
···98989999 /* Completeness */
100100 // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
101101- "skipLibCheck": true /* Skip type checking all .d.ts files. */
101101+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
102102 }
103103}