Skip to main content

Configuration and application lifecycle

Options override environment variables.

OptionEnvironment variableDefault
WithEnabledSYNAPSYS_ENABLEDtrue
WithCoreURLSYNAPSYS_CORE_URLrequired when enabled
WithCoreTokenSYNAPSYS_CORE_TOKENnone; missing token warns
WithWorkerNameSYNAPSYS_WORKER_NAMEexecutable name
WithHostSYNAPSYS_HOSTmachine hostname
WithHeartbeatIntervalSYNAPSYS_HEARTBEAT_INTERVAL5s; positive whole seconds
WithFailFastSYNAPSYS_FAIL_FASTfalse
WithConnectTimeoutSYNAPSYS_CONNECT_TIMEOUT2s
WithRequestTimeoutSYNAPSYS_REQUEST_TIMEOUT5s
WithConsoleCaptureSYNAPSYS_CAPTURE_CONSOLEtrue
WithLoggernoneslog.Default()

Environment durations use time.ParseDuration syntax and require a unit. Options accept time.Duration. WithEnabled(false) makes startup a runtime no-op; invalid declarations still return errors when registered.

Start and graceful stop​

Start() performs a bounded unauthenticated health probe, logs configuration once, and starts an immediate, non-overlapping fixed-delay heartbeat. Core being down is non-fatal unless WithFailFast(true) is set.

Go uses the caller's shutdown context instead of a shutdown-timeout setting:

if err := worker.Start(); err != nil {
return err
}

shutdown, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := worker.Stop(shutdown); err != nil {
logger.Warn("Synapsys shutdown deadline expired", "error", err)
}

Stop is idempotent. It stops the heartbeat goroutine, cancels active process contexts, waits within the deadline, sends a final request whose commands are ignored if time remains, and closes SDK-owned idle connections. A goroutine that ignores its context is not killed; it remains stopping and blocks replacement.

Structured and text logging​

The SDK does not replace process-global os.Stdout or os.Stderr: goroutines have no local execution context that could attribute concurrent writes safely. Use explicit process-scoped sinks:

processLog := worker.Logger("invoice-consumer")
processLog.Info("invoice received", "invoiceId", invoice.ID)

output := worker.Writer("legacy-listener", synapsys.Stdout, os.Stdout)
legacyLog := log.New(output, "", log.LstdFlags)

The slog.Logger passes records to the application logger and queues Info-or-higher records only during the named active run. Writer is a tee. Both are bounded and disabled by WithConsoleCapture(false). Plain fmt.Print is never captured.

Current v0.1.0 caveat: an empty 2xx heartbeat body is accepted instead of treated as a protocol failure. See current client differences.