Skip to content

SDK Guidelines

The SDK guidelines define the canonical patterns, naming conventions, and quality standards for OJS SDK implementations across all languages.

  1. Idiomatic: Use language-native patterns. A Go SDK should feel like Go, not like a Java port.
  2. Consistent: The same concepts have the same names across SDKs (adapted to language conventions).
  3. Progressive disclosure: Simple things should be simple, complex things should be possible.
  4. Pit of success: The default behavior should be correct and safe.

Every SDK provides three roles:

RoleResponsibilityKey Methods
Client (Producer)Enqueue jobsenqueue(), enqueueBatch(), cancel(), getJob()
Worker (Consumer)Process jobsregister(), start(), stop()
Admin (Operator)Manage the backendpauseQueue(), listWorkers(), stats()
ConceptGoTypeScriptPythonJavaRubyRust
EnqueueEnqueueenqueueenqueueenqueueenqueueenqueue
Job typestringstringstrStringString&str
HandlerHandlerFuncJobHandlerhandlerJobHandlerhandlerJobHandler
MiddlewareMiddlewareFuncMiddlewaremiddlewareMiddlewaremiddlewareMiddleware

SDKs MUST support configuration via:

  1. Builder pattern (primary)
  2. Environment variables (fallback)
  3. Sensible defaults (always)
client := ojs.NewClient(
ojs.WithURL("http://localhost:8080"),
ojs.WithTimeout(30 * time.Second),
)
const client = new OJSClient({
url: process.env.OJS_URL || 'http://localhost:8080',
timeout: 30_000,
});

SDKs MUST provide a typed error hierarchy:

Error TypeDescription
ConnectionErrorCannot reach the backend
ValidationErrorRequest validation failed
ConflictErrorState conflict (e.g., duplicate job)
NotFoundErrorJob or resource not found
RateLimitErrorRate limit exceeded (includes retry_after)
BackendErrorInternal backend failure

Errors MUST include the original OJS error code and message for debugging.

Each language uses its native async model:

LanguageAsync Model
GoGoroutines + context cancellation
TypeScriptasync/await + Promise
Pythonasyncio + async/await
JavaCompletableFuture or virtual threads
Rusttokio + async/await
RubyThreads

SDKs MUST support both enqueue and execution middleware chains:

worker.use(async (job, next) => {
console.log(`Processing ${job.type}`);
const start = Date.now();
await next();
console.log(`Completed in ${Date.now() - start}ms`);
});

SDKs MUST provide testing utilities (see Testing):

  • Fake mode (in-memory, no backend)
  • Inline mode (synchronous execution)
  • Assertion helpers (assertEnqueued, refuteEnqueued)

SDKs SHOULD:

  • Inject W3C Trace Context into meta.traceparent on enqueue
  • Extract trace context on execution and create linked spans
  • Emit structured logs with job context
  • Export OpenTelemetry metrics

SDKs are thin HTTP wrappers. All intelligence (scheduling, retry evaluation, workflow orchestration, state management) lives in the backend server. This keeps SDKs simple, minimizes cross-language divergence, and ensures behavioral consistency.