worker

package module
v2.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 2, 2026 License: MIT Imports: 12 Imported by: 0

README

worker

A standalone JavaScript worker runtime for Go with dual-engine support: QuickJS (default, pure Go) and V8 (opt-in via build tag).

import "github.com/cryguy/worker"

Features

  • Dual JS engine support — QuickJS (default) or V8, selectable at build time
  • Cloudflare Workers-compatible API surface:
    • KV namespaces
    • R2 storage buckets
    • D1 databases (SQLite)
    • Durable Objects
    • Queue producers
    • Service bindings (worker-to-worker RPC)
    • Cache API
    • Static assets
    • Custom env bindings
  • Web standard APIs: fetch, crypto, streams, WebSocket, HTMLRewriter, URL, TextEncoder/Decoder
  • ES module bundling via esbuild
  • Resource limits: memory, execution timeout, fetch count
  • Cron scheduling support
  • Arbitrary function invocation via ExecuteFunction

Engines

The runtime ships with two interchangeable JavaScript backends. The public API is identical regardless of which engine you use — only the build step differs.

QuickJS (default)

QuickJS is the default engine. It compiles with pure Go (via modernc.org) and requires no CGO, making it easy to cross-compile and deploy anywhere.

go build ./...
go test ./...

Pros: no CGO, simple cross-compilation, smaller binary, works on any GOOS/GOARCH that Go supports. Cons: slower JS execution compared to V8.

V8 (opt-in)

V8 is available as an opt-in backend using the v8 build tag. It provides significantly faster JavaScript execution via JIT compilation but requires CGO and platform-specific V8 binaries.

go build -tags v8 ./...
go test -tags v8 ./...

Pros: much faster JS execution (JIT), full V8 feature set. Cons: requires CGO, Linux/macOS only (V8 binaries are platform-specific), larger binary.

Requirements

  • Go 1.25+
  • QuickJS backend: no additional requirements
  • V8 backend: CGO enabled, Linux or macOS

Usage

The API is the same for both engines. Your Go code does not change when switching backends — only the build command does.

package main

import "github.com/cryguy/worker"

func main() {
    cfg := worker.EngineConfig{
        PoolSize:         4,
        MemoryLimitMB:    128,
        ExecutionTimeout: 30000,
        MaxFetchRequests: 50,
    }

    engine := worker.NewEngine(cfg, mySourceLoader)
    defer engine.Shutdown()

    env := &worker.Env{
        Vars:    map[string]string{"API_KEY": "..."},
        Secrets: map[string]string{"SECRET": "..."},
        KV:      map[string]worker.KVStore{"MY_KV": myKVImpl},
    }

    result := engine.Execute("site-id", "deploy-key", env, &worker.WorkerRequest{
        Method:  "GET",
        URL:     "https://example.com/",
        Headers: map[string]string{},
    })
}

Build with QuickJS (default):

go build ./cmd/myapp

Build with V8:

go build -tags v8 ./cmd/myapp

Custom Env Bindings

Inject values into the worker's env object using CustomBindings. Each function receives the engine-agnostic JSRuntime interface and returns a value that gets set on env:

env := &worker.Env{
    Vars: map[string]string{"APP": "myapp"},
    CustomBindings: map[string]worker.EnvBindingFunc{
        "greeting": func(rt worker.JSRuntime) (any, error) {
            return "Hello from Go!", nil
        },
        "config": func(rt worker.JSRuntime) (any, error) {
            return map[string]any{"mode": "production", "debug": false}, nil
        },
    },
}

The worker script can then access env.greeting and env.config.mode. This works identically on both QuickJS and V8.

ExecuteFunction

Call any named export on a worker module with JSON-serializable arguments. The return value is JSON-serialized into result.Data:

source := `export default {
  add(env, a, b) {
    return { sum: a + b };
  },
};`

bytes, _ := engine.CompileAndCache("site", "deploy", source)
result := engine.ExecuteFunction("site", "deploy", env, "add", 3, 4)
// result.Data == `{"sum":7}`

This is useful for plugin-style architectures where Go orchestrates and JS modules provide the logic.

Interfaces

The runtime is decoupled from storage backends via interfaces. Implement these to provide platform bindings:

  • SourceLoader - Load worker JavaScript source code
  • KVStore - Key-value storage
  • CacheStore - HTTP cache
  • R2Store - Object storage (S3/R2 compatible)
  • DurableObjectStore - Durable Object storage
  • QueueSender - Message queue producer
  • AssetsFetcher - Static asset serving
  • WorkerDispatcher - Service binding dispatch

License

MIT

Documentation

Index

Constants

View Source
const MaxKVValueSize = core.MaxKVValueSize

Constants re-exported from core.

Variables

View Source
var DataDir = "./data"

DataDir is the base directory for cached polyfills. Defaults to "./data".

View Source
var DecodeCursor = core.DecodeCursor

Functions re-exported from core.

View Source
var EncodeCursor = core.EncodeCursor

Functions

func BundleWorkerScript

func BundleWorkerScript(deployPath string) (string, error)

BundleWorkerScript uses esbuild to bundle a worker's _worker.js entry point with all its imports into a single self-contained script. This enables ES module import/export support for worker scripts.

If the source doesn't contain any import statements, it's returned as-is to avoid unnecessary processing.

func ResetUnenvCache

func ResetUnenvCache()

ResetUnenvCache clears the cached unenv path (used in tests).

func ValidateCron

func ValidateCron(expr string) error

ValidateCron checks if a cron expression is a valid 5-field format. Fields: minute(0-59) hour(0-23) day(1-31) month(1-12) weekday(0-6).

Types

type AssetsFetcher

type AssetsFetcher = core.AssetsFetcher

type CacheEntry

type CacheEntry = core.CacheEntry

type CacheStore

type CacheStore = core.CacheStore

type CryptoKeyEntry

type CryptoKeyEntry = core.CryptoKeyEntry

type D1ExecResult

type D1ExecResult = core.D1ExecResult

type D1Meta

type D1Meta = core.D1Meta

type D1Store

type D1Store = core.D1Store

type DurableObjectStore

type DurableObjectStore = core.DurableObjectStore

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine wraps a backend JS engine (QuickJS by default, V8 with -tags v8).

func NewEngine

func NewEngine(cfg EngineConfig, loader SourceLoader) *Engine

NewEngine creates a new Engine with the given config and source loader.

func (*Engine) CompileAndCache

func (e *Engine) CompileAndCache(siteID, deployKey, source string) ([]byte, error)

CompileAndCache compiles the source and caches the bytecode.

func (*Engine) EnsureSource

func (e *Engine) EnsureSource(siteID, deployKey string) error

EnsureSource ensures the source for the given site/deploy is loaded.

func (*Engine) Execute

func (e *Engine) Execute(siteID, deployKey string, env *Env, req *WorkerRequest) *WorkerResult

Execute runs the worker's fetch handler for the given request.

func (*Engine) ExecuteFunction

func (e *Engine) ExecuteFunction(siteID, deployKey string, env *Env, fnName string, args ...any) *WorkerResult

ExecuteFunction calls a named exported function on the worker module.

func (*Engine) ExecuteScheduled

func (e *Engine) ExecuteScheduled(siteID, deployKey string, env *Env, cron string) *WorkerResult

ExecuteScheduled runs the worker's scheduled handler.

func (*Engine) ExecuteTail

func (e *Engine) ExecuteTail(siteID, deployKey string, env *Env, events []TailEvent) *WorkerResult

ExecuteTail runs the worker's tail handler.

func (*Engine) InvalidatePool

func (e *Engine) InvalidatePool(siteID, deployKey string)

InvalidatePool marks the pool for the given site as invalid.

func (*Engine) MaxResponseBytes

func (e *Engine) MaxResponseBytes() int

MaxResponseBytes returns the configured max response body size.

func (*Engine) SetDispatcher

func (e *Engine) SetDispatcher(d WorkerDispatcher)

SetDispatcher sets the worker dispatcher for service bindings.

func (*Engine) Shutdown

func (e *Engine) Shutdown()

Shutdown disposes of all pools and workers.

type EngineConfig

type EngineConfig = core.EngineConfig

type Env

type Env = core.Env

type EnvBindingFunc

type EnvBindingFunc = core.EnvBindingFunc

type JSRuntime

type JSRuntime = core.JSRuntime

type KVListResult

type KVListResult = core.KVListResult

type KVPair

type KVPair = core.KVPair

type KVStore

type KVStore = core.KVStore

type KVValueWithMetadata

type KVValueWithMetadata = core.KVValueWithMetadata

type LogEntry

type LogEntry = core.LogEntry

type QueueMessageInput

type QueueMessageInput = core.QueueMessageInput

type QueueSender

type QueueSender = core.QueueSender

type R2ListOptions

type R2ListOptions = core.R2ListOptions

type R2ListResult

type R2ListResult = core.R2ListResult

type R2Object

type R2Object = core.R2Object

type R2PutOptions

type R2PutOptions = core.R2PutOptions

type R2Store

type R2Store = core.R2Store

type ServiceBindingConfig

type ServiceBindingConfig = core.ServiceBindingConfig

type SourceLoader

type SourceLoader = core.SourceLoader

type TailEvent

type TailEvent = core.TailEvent

type WebSocketBridger

type WebSocketBridger = core.WebSocketBridger

type WorkerDispatcher

type WorkerDispatcher = core.WorkerDispatcher

type WorkerRequest

type WorkerRequest = core.WorkerRequest

type WorkerResponse

type WorkerResponse = core.WorkerResponse

type WorkerResult

type WorkerResult = core.WorkerResult

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL