Skip to content

Commit 73e3a59

Browse files
committed
doc.go + a few scope updates
1 parent 42b5dc6 commit 73e3a59

File tree

9 files changed

+200
-229
lines changed

9 files changed

+200
-229
lines changed

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
#### [Documentation](https://docs.dbos.dev/)      [Examples](https://docs.dbos.dev/examples)      [Github](https://github.com/dbos-inc)
1313
</div>
1414

15-
#### This Golang version of DBOS Transact is in Alpha!
16-
For production ready Transacts, check our [Python](https://github.com/dbos-inc/dbos-transact-py) and [TypeScript](https://github.com/dbos-inc/dbos-transact-ts) versions.
17-
1815
---
1916

2017
## What is DBOS?
@@ -74,7 +71,7 @@ func stepTwo(ctx context.Context) (string, error) {
7471
}
7572
func main() {
7673
// Initialize a DBOS context
77-
ctx, err := dbos.NewDBOSContext(dbos.Config{
74+
ctx, err := dbos.NewDBOSContext(context.Background(), dbos.Config{
7875
DatabaseURL: os.Getenv("DBOS_SYSTEM_DATABASE_URL"),
7976
AppName: "myapp",
8077
})
@@ -147,7 +144,7 @@ func task(ctx dbos.DBOSContext, i int) (int, error) {
147144

148145
func main() {
149146
// Initialize a DBOS context
150-
ctx, err := dbos.NewDBOSContext(dbos.Config{
147+
ctx, err := dbos.NewDBOSContext(context.Background(), dbos.Config{
151148
DatabaseURL: os.Getenv("DBOS_SYSTEM_DATABASE_URL"),
152149
AppName: "myapp",
153150
})

cmd/dbos/cli_integration_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,11 @@ func buildCLI(t *testing.T) string {
693693
// Delete any existing binary before building
694694
os.Remove(cliPath)
695695

696+
// Install Transact from main
697+
installCmd := exec.Command("go", "get", "github.com/dbos-inc/dbos-transact-golang@main")
698+
installOutput, installErr := installCmd.CombinedOutput()
699+
require.NoError(t, installErr, "Failed to install Transact: %s", string(installOutput))
700+
696701
// Build the CLI from the cmd directory
697702
buildCmd := exec.Command("go", "build", "-o", "dbos-cli-test", ".")
698703
buildCmd.Dir = cmdDir

cmd/dbos/cli_test_app.go.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func ScheduledWorkflow(ctx dbos.DBOSContext, scheduledTime time.Time) (string, e
8686
func main() {
8787
// Create DBOS context
8888
var err error
89-
dbosCtx, err = dbos.NewDBOSContext(dbos.Config{
89+
dbosCtx, err = dbos.NewDBOSContext(context.Background(), dbos.Config{
9090
DatabaseURL: os.Getenv("DBOS_SYSTEM_DATABASE_URL"),
9191
AppName: "cli-test",
9292
AdminServer: true,

dbos/conductor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ type Conductor struct {
5555
pingCancel context.CancelFunc
5656
}
5757

58-
// Launch starts the conductor main goroutine
59-
func (c *Conductor) Launch() {
58+
// launch starts the conductor main goroutine
59+
func (c *Conductor) launch() {
6060
c.logger.Info("Launching conductor")
6161
c.wg.Add(1)
6262
go c.run()
6363
}
6464

65-
func NewConductor(dbosCtx *dbosContext, config ConductorConfig) (*Conductor, error) {
65+
func newConductor(dbosCtx *dbosContext, config ConductorConfig) (*Conductor, error) {
6666
if config.apiKey == "" {
6767
return nil, fmt.Errorf("conductor API key is required")
6868
}
@@ -96,7 +96,7 @@ func NewConductor(dbosCtx *dbosContext, config ConductorConfig) (*Conductor, err
9696
return c, nil
9797
}
9898

99-
func (c *Conductor) Shutdown(timeout time.Duration) {
99+
func (c *Conductor) shutdown(timeout time.Duration) {
100100
c.stopOnce.Do(func() {
101101
if c.pingCancel != nil {
102102
c.pingCancel()

dbos/conductor_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ func TestConductorReconnection(t *testing.T) {
316316
}
317317

318318
// Create conductor
319-
conductor, err := NewConductor(dbosCtx, config)
319+
conductor, err := newConductor(dbosCtx, config)
320320
require.NoError(t, err)
321321

322322
// Speed up intervals for testing
@@ -325,7 +325,7 @@ func TestConductorReconnection(t *testing.T) {
325325
conductor.reconnectWait = 100 * time.Millisecond
326326

327327
// Launch conductor
328-
conductor.Launch()
328+
conductor.launch()
329329

330330
// Wait for initial connection
331331
assert.True(t, mockServer.waitForConnection(5*time.Second), "Should establish initial connection")
@@ -406,7 +406,7 @@ func TestConductorReconnection(t *testing.T) {
406406
}
407407

408408
// Create conductor
409-
conductor, err := NewConductor(dbosCtx, config)
409+
conductor, err := newConductor(dbosCtx, config)
410410
require.NoError(t, err)
411411

412412
// Speed up intervals for testing
@@ -415,7 +415,7 @@ func TestConductorReconnection(t *testing.T) {
415415
conductor.reconnectWait = 100 * time.Millisecond
416416

417417
// Launch conductor
418-
conductor.Launch()
418+
conductor.launch()
419419

420420
// Wait for initial connection
421421
assert.True(t, mockServer.waitForConnection(5*time.Second), "Should establish initial connection")
@@ -494,7 +494,7 @@ func TestConductorReconnection(t *testing.T) {
494494
}
495495

496496
// Create conductor
497-
conductor, err := NewConductor(dbosCtx, config)
497+
conductor, err := newConductor(dbosCtx, config)
498498
require.NoError(t, err)
499499

500500
// Speed up intervals for testing
@@ -503,7 +503,7 @@ func TestConductorReconnection(t *testing.T) {
503503
conductor.reconnectWait = 100 * time.Millisecond
504504

505505
// Launch conductor
506-
conductor.Launch()
506+
conductor.launch()
507507

508508
// Wait for initial connection
509509
assert.True(t, mockServer.waitForConnection(5*time.Second), "Should establish initial connection")
@@ -587,7 +587,7 @@ func TestConductorReconnection(t *testing.T) {
587587
}
588588

589589
// Create conductor
590-
conductor, err := NewConductor(dbosCtx, config)
590+
conductor, err := newConductor(dbosCtx, config)
591591
require.NoError(t, err)
592592

593593
// Speed up intervals for testing
@@ -596,7 +596,7 @@ func TestConductorReconnection(t *testing.T) {
596596
conductor.reconnectWait = 100 * time.Millisecond
597597

598598
// Launch conductor
599-
conductor.Launch()
599+
conductor.launch()
600600

601601
// Wait for initial connection
602602
assert.True(t, mockServer.waitForConnection(5*time.Second), "Should establish initial connection")

dbos/dbos.go

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
// Package dbos provides a Go SDK for building durable applications with DBOS Transact.
2-
//
3-
// DBOS Transact enables developers to write resilient distributed applications using workflows
4-
// and steps backed by PostgreSQL. All application state is automatically persisted, providing
5-
// exactly-once execution guarantees and automatic recovery from failures.
61
package dbos
72

83
import (
@@ -44,7 +39,6 @@ type Config struct {
4439
Context context.Context // User Context
4540
}
4641

47-
// processConfig enforces mandatory fields and applies defaults.
4842
func processConfig(inputConfig *Config) (*Config, error) {
4943
// First check required fields
5044
if len(inputConfig.DatabaseURL) == 0 {
@@ -103,8 +97,8 @@ type DBOSContext interface {
10397
context.Context
10498

10599
// Context Lifecycle
106-
Launch() error // Launch the DBOS runtime including system database, queues, admin server, and workflow recovery
107-
Shutdown(timeout time.Duration) // Gracefully shutdown all DBOS runtime components with ordered cleanup sequence
100+
Launch() error // Launch the DBOS runtime including system database, queues, and perform a workflow recovery for the local executor
101+
Shutdown(timeout time.Duration) // Gracefully shutdown all DBOS resources
108102

109103
// Workflow operations
110104
RunAsStep(_ DBOSContext, fn StepFunc, opts ...StepOption) (any, error) // Execute a function as a durable step within a workflow
@@ -167,7 +161,6 @@ type dbosContext struct {
167161
logger *slog.Logger
168162
}
169163

170-
// Implement contex.Context interface methods
171164
func (c *dbosContext) Deadline() (deadline time.Time, ok bool) {
172165
return c.ctx.Deadline()
173166
}
@@ -209,7 +202,7 @@ func WithValue(ctx DBOSContext, key, val any) DBOSContext {
209202
}
210203

211204
// WithoutCancel returns a copy of the DBOS context that is not canceled when the parent context is canceled.
212-
// This is useful for operations that should continue even after a workflow is cancelled.
205+
// This can be used to detach a child workflow.
213206
// No-op if the provided context is not a concrete dbos.dbosContext.
214207
func WithoutCancel(ctx DBOSContext) DBOSContext {
215208
if ctx == nil {
@@ -275,17 +268,16 @@ func (c *dbosContext) GetApplicationID() string {
275268
}
276269

277270
// NewDBOSContext creates a new DBOS context with the provided configuration.
278-
// The context must be launched with Launch() before use and should be shut down with Shutdown().
279-
// This function initializes the DBOS system database, sets up the queue sub-system,
280-
// and prepares the workflow registry.
271+
// The context must be launched with Launch() for workflow execution and should be shut down with Shutdown().
272+
// This function initializes the DBOS system database, sets up the queue sub-system, and prepares the workflow registry.
281273
//
282274
// Example:
283275
//
284276
// config := dbos.Config{
285277
// DatabaseURL: "postgres://user:pass@localhost:5432/dbname",
286278
// AppName: "my-app",
287279
// }
288-
// ctx, err := dbos.NewDBOSContext(config)
280+
// ctx, err := dbos.NewDBOSContext(context.Background(), config)
289281
// if err != nil {
290282
// log.Fatal(err)
291283
// }
@@ -355,7 +347,7 @@ func NewDBOSContext(ctx context.Context, inputConfig Config) (DBOSContext, error
355347
apiKey: config.ConductorAPIKey,
356348
appName: config.AppName,
357349
}
358-
conductor, err := NewConductor(initExecutor, conductorConfig)
350+
conductor, err := newConductor(initExecutor, conductorConfig)
359351
if err != nil {
360352
return nil, newInitializationError(fmt.Sprintf("failed to initialize conductor: %v", err))
361353
}
@@ -367,9 +359,8 @@ func NewDBOSContext(ctx context.Context, inputConfig Config) (DBOSContext, error
367359
}
368360

369361
// Launch initializes and starts the DBOS runtime components including the system database,
370-
// admin server (if configured), queue runner, workflow scheduler, and performs recovery
371-
// of any pending workflows on this executor. This method must be called before using the DBOS context
372-
// for workflow execution and should only be called once.
362+
// admin server (if enabled), queue runner, workflow scheduler, and performs recovery
363+
// of any pending workflows on this executor.
373364
//
374365
// Returns an error if the context is already launched or if any component fails to start.
375366
func (c *dbosContext) Launch() error {
@@ -380,7 +371,7 @@ func (c *dbosContext) Launch() error {
380371
// Start the system database
381372
c.systemDB.launch(c)
382373

383-
// Start the admin server if configured
374+
// Start the admin server if enabled
384375
if c.config.AdminServer {
385376
adminServer := newAdminServer(c, c.config.AdminServerPort)
386377
err := adminServer.Start()
@@ -407,7 +398,7 @@ func (c *dbosContext) Launch() error {
407398

408399
// Start the conductor if it has been initialized
409400
if c.conductor != nil {
410-
c.conductor.Launch()
401+
c.conductor.launch()
411402
c.logger.Debug("Conductor started")
412403
}
413404

@@ -459,7 +450,6 @@ func (c *dbosContext) Shutdown(timeout time.Duration) {
459450
case <-done:
460451
c.logger.Debug("All workflows completed")
461452
case <-time.After(timeout):
462-
// For now just log a warning: eventually we might want Cancel to return an error.
463453
c.logger.Warn("Timeout waiting for workflows to complete", "timeout", timeout)
464454
}
465455

@@ -491,7 +481,7 @@ func (c *dbosContext) Shutdown(timeout time.Duration) {
491481
// Shutdown the conductor
492482
if c.conductor != nil {
493483
c.logger.Debug("Shutting down conductor")
494-
c.conductor.Shutdown(timeout)
484+
c.conductor.shutdown(timeout)
495485
}
496486

497487
// Shutdown the admin server

dbos/doc.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Package dbos provides lightweight durable workflow orchestration with Postgres.
2+
//
3+
// DBOS Transact enables developers to write resilient distributed applications using workflows
4+
// and steps backed by PostgreSQL. All application state is automatically persisted, providing
5+
// exactly-once execution guarantees and automatic recovery from failures.
6+
//
7+
// # Getting Started
8+
//
9+
// Create a DBOS context to start building durable applications:
10+
//
11+
// dbosContext, err := dbos.NewDBOSContext(context.Background(), dbos.Config{
12+
// AppName: "my-app",
13+
// DatabaseURL: os.Getenv("DATABASE_URL"),
14+
// })
15+
// defer dbosContext.Shutdown(5 * time.Second)
16+
//
17+
// // Register workflows before launching
18+
// dbos.RegisterWorkflow(dbosContext, myWorkflow)
19+
//
20+
// // Launch the context to start processing
21+
// err = dbosContext.Launch()
22+
//
23+
// # Workflows
24+
//
25+
// Workflows provide durable execution, automatically resuming from the last completed step
26+
// after any failure. Write workflows as normal Go functions that take a DBOSContext and
27+
// return serializable values:
28+
//
29+
// func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
30+
// // Workflow logic here
31+
// result, err := dbos.RunAsStep(ctx, someOperation)
32+
// if err != nil {
33+
// return "", err
34+
// }
35+
// return result, nil
36+
// }
37+
//
38+
// Key workflow features:
39+
// - Automatic recovery: Workflows resume from the last completed step after crashes
40+
// - Idempotency: Assign workflow IDs to ensure operations run exactly once
41+
// - Determinism: Workflow functions must be deterministic; use steps for non-deterministic operations
42+
// - Timeouts: Set durable timeouts that persist across restarts
43+
// - Events & messaging: Workflows can emit events and receive messages for coordination
44+
//
45+
// # Steps
46+
//
47+
// Steps wrap non-deterministic operations (API calls, random numbers, current time) within workflows.
48+
// If a workflow is interrupted, it resumes from the last completed step:
49+
//
50+
// func fetchData(ctx context.Context) (string, error) {
51+
// resp, err := http.Get("https://api.example.com/data")
52+
// // Handle response...
53+
// return data, nil
54+
// }
55+
//
56+
// func workflow(ctx dbos.DBOSContext, input string) (string, error) {
57+
// data, err := dbos.RunAsStep(ctx, fetchData,
58+
// dbos.WithStepName("fetchData"),
59+
// dbos.WithStepMaxRetries(3))
60+
// if err != nil {
61+
// return "", err
62+
// }
63+
// return data, nil
64+
// }
65+
//
66+
// Steps support configurable retries with exponential backoff for handling transient failures.
67+
//
68+
// # Queues
69+
//
70+
// Queues manage workflow concurrency and rate limiting:
71+
//
72+
// queue := dbos.NewWorkflowQueue(dbosContext, "task_queue",
73+
// dbos.WithWorkerConcurrency(5), // Max 5 concurrent workflows per process
74+
// dbos.WithRateLimiter(&dbos.RateLimiter{
75+
// Limit: 100,
76+
// Period: 60 * time.Second, // 100 workflows per 60 seconds
77+
// }))
78+
//
79+
// // Enqueue workflows with optional deduplication and priority
80+
// handle, err := dbos.RunWorkflow(ctx, taskWorkflow, input,
81+
// dbos.WithQueue(queue.Name),
82+
// dbos.WithDeduplicationID("unique-id"),
83+
// dbos.WithPriority(10))
84+
//
85+
// # Workflow Management
86+
//
87+
// DBOS provides comprehensive workflow management capabilities:
88+
//
89+
// // List workflows
90+
// workflows, err := dbos.ListWorkflows(ctx)
91+
//
92+
// // Cancel a running workflow
93+
// err = dbos.CancelWorkflow(ctx, workflowID)
94+
//
95+
// // Resume a cancelled workflow
96+
// err = dbos.ResumeWorkflow(ctx, workflowID)
97+
//
98+
// // Fork a workflow from a specific step
99+
// newID, err := dbos.ForkWorkflow(ctx, originalID, stepNumber)
100+
//
101+
// Workflows can also be visualized and managed through the DBOS Console web UI.
102+
//
103+
// # Testing
104+
//
105+
// DBOSContext is fully mockable for unit testing:
106+
//
107+
// func TestWorkflow(t *testing.T) {
108+
// mockCtx := mocks.NewMockDBOSContext(t)
109+
// mockCtx.On("RunAsStep", mockCtx, mock.Anything, mock.Anything).Return("result", nil)
110+
//
111+
// result, err := myWorkflow(mockCtx, "input")
112+
// assert.NoError(t, err)
113+
// assert.Equal(t, "expected", result)
114+
// }
115+
//
116+
// For detailed documentation and examples, see https://docs.dbos.dev/golang
117+
118+
package dbos

0 commit comments

Comments
 (0)