Skip to content

Commit 6ce631f

Browse files
ngnhngmaxdml
andauthored
Starter examples: replace dbos-toolbox with dbos-go-starter (#155)
## Summary Hi, thanks for the great project, I am currently trying to demo this my team but the current example sucked. So i went ahead and replace it with the dbos-go-starter. --------- Co-authored-by: Max dml <maxdemoulin@gmail.com>
1 parent fe30608 commit 6ce631f

File tree

7 files changed

+506
-239
lines changed

7 files changed

+506
-239
lines changed

cmd/dbos/init.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func runInit(cmd *cobra.Command, args []string) error {
2525
if len(args) > 0 {
2626
projectName = args[0]
2727
} else {
28-
projectName = "dbos-toolbox"
28+
projectName = "dbos-go-starter"
2929
}
3030

3131
// Check if directory already exists
@@ -45,9 +45,10 @@ func runInit(cmd *cobra.Command, args []string) error {
4545

4646
// Process and write each template file
4747
templates := map[string]string{
48-
"templates/dbos-toolbox/go.mod.tmpl": "go.mod",
49-
"templates/dbos-toolbox/main.go.tmpl": "main.go",
50-
"templates/dbos-toolbox/dbos-config.yaml.tmpl": "dbos-config.yaml",
48+
"templates/dbos-go-starter/go.mod.tmpl": "go.mod",
49+
"templates/dbos-go-starter/main.go.tmpl": "main.go",
50+
"templates/dbos-go-starter/dbos-config.yaml.tmpl": "dbos-config.yaml",
51+
"templates/dbos-go-starter/app.html": "html/app.html",
5152
}
5253

5354
for tmplPath, outputFile := range templates {
@@ -70,6 +71,9 @@ func runInit(cmd *cobra.Command, args []string) error {
7071

7172
// Write output file
7273
outputPath := filepath.Join(projectName, outputFile)
74+
if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
75+
return fmt.Errorf("failed to create directory for %s: %w", outputFile, err)
76+
}
7377
if err := os.WriteFile(outputPath, buf.Bytes(), 0644); err != nil {
7478
return fmt.Errorf("failed to write %s: %w", outputFile, err)
7579
}
@@ -79,7 +83,7 @@ func runInit(cmd *cobra.Command, args []string) error {
7983
fmt.Println("To get started:")
8084
fmt.Printf(" cd %s\n", projectName)
8185
fmt.Println(" go mod tidy")
82-
fmt.Println(" export DBOS_SYSTEM_DATABASE_URL=<your-database-url>")
86+
fmt.Println(" export DBOS_SYSTEM_DATABASE_URL=\"postgres://<user>:<password>@<host>:<port>/<db>\"")
8387
fmt.Println(" go run main.go")
8488

8589
return nil

cmd/dbos/templates.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import (
44
"embed"
55
)
66

7-
//go:embed templates/dbos-toolbox/*
8-
var templateFS embed.FS
7+
//go:embed templates/dbos-go-starter/*
8+
var templateFS embed.FS

cmd/dbos/templates/dbos-go-starter/app.html

Lines changed: 340 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
"os"
8+
"time"
9+
10+
"github.com/dbos-inc/dbos-transact-golang/dbos"
11+
"github.com/gin-gonic/gin"
12+
)
13+
14+
const STEPS_EVENT = "steps_event"
15+
16+
var dbosCtx dbos.DBOSContext
17+
18+
/*****************************/
19+
/**** WORKFLOWS AND STEPS ****/
20+
/*****************************/
21+
22+
func ExampleWorkflow(ctx dbos.DBOSContext, _ string) (string, error) {
23+
_, err := dbos.RunAsStep(ctx, func(stepCtx context.Context) (string, error) {
24+
return stepOne(stepCtx)
25+
})
26+
if err != nil {
27+
return "", err
28+
}
29+
err = dbos.SetEvent(ctx, STEPS_EVENT, 1)
30+
if err != nil {
31+
return "", err
32+
}
33+
_, err = dbos.RunAsStep(ctx, func(stepCtx context.Context) (string, error) {
34+
return stepTwo(stepCtx)
35+
})
36+
if err != nil {
37+
return "", err
38+
}
39+
err = dbos.SetEvent(ctx, STEPS_EVENT, 2)
40+
if err != nil {
41+
return "", err
42+
}
43+
_, err = dbos.RunAsStep(ctx, func(stepCtx context.Context) (string, error) {
44+
return stepThree(stepCtx)
45+
})
46+
if err != nil {
47+
return "", err
48+
}
49+
err = dbos.SetEvent(ctx, STEPS_EVENT, 3)
50+
if err != nil {
51+
return "", err
52+
}
53+
return "Workflow completed", nil
54+
}
55+
56+
func stepOne(ctx context.Context) (string, error) {
57+
time.Sleep(5 * time.Second)
58+
fmt.Println("Step one completed!")
59+
return "Step 1 completed", nil
60+
}
61+
62+
func stepTwo(ctx context.Context) (string, error) {
63+
time.Sleep(5 * time.Second)
64+
fmt.Println("Step two completed!")
65+
return "Step 2 completed", nil
66+
}
67+
68+
func stepThree(ctx context.Context) (string, error) {
69+
time.Sleep(5 * time.Second)
70+
fmt.Println("Step three completed!")
71+
return "Step 3 completed", nil
72+
}
73+
74+
/*****************************/
75+
/**** Main Function **********/
76+
/*****************************/
77+
78+
func main() {
79+
// Create DBOS context
80+
var err error
81+
dbosCtx, err = dbos.NewDBOSContext(context.Background(), dbos.Config{
82+
DatabaseURL: os.Getenv("DBOS_SYSTEM_DATABASE_URL"),
83+
AppName: "{{.ProjectName}}",
84+
AdminServer: true,
85+
})
86+
if err != nil {
87+
panic(err)
88+
}
89+
90+
// Register workflows
91+
dbos.RegisterWorkflow(dbosCtx, ExampleWorkflow)
92+
93+
// Launch DBOS
94+
err = dbosCtx.Launch()
95+
if err != nil {
96+
panic(err)
97+
}
98+
defer dbosCtx.Shutdown(10 * time.Second)
99+
100+
// Initialize Gin router
101+
router := gin.Default()
102+
103+
// HTTP Handlers
104+
router.StaticFile("/", "./html/app.html")
105+
router.GET("/workflow/:taskid", workflowHandler)
106+
router.GET("/last_step/:taskid", lastStepHandler)
107+
router.POST("/crash", crashHandler)
108+
109+
fmt.Println("Server starting on http://localhost:8080")
110+
err = router.Run(":8080")
111+
if err != nil {
112+
fmt.Printf("Error starting server: %s\n", err)
113+
}
114+
}
115+
116+
/*****************************/
117+
/**** HTTP HANDLERS **********/
118+
/*****************************/
119+
120+
func workflowHandler(c *gin.Context) {
121+
taskID := c.Param("taskid")
122+
123+
if taskID == "" {
124+
c.JSON(http.StatusBadRequest, gin.H{"error": "Task ID is required"})
125+
return
126+
}
127+
128+
_, err := dbos.RunWorkflow(dbosCtx, ExampleWorkflow, "", dbos.WithWorkflowID(taskID))
129+
if err != nil {
130+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
131+
return
132+
}
133+
}
134+
135+
func lastStepHandler(c *gin.Context) {
136+
taskID := c.Param("taskid")
137+
138+
if taskID == "" {
139+
c.JSON(http.StatusBadRequest, gin.H{"error": "Task ID is required"})
140+
return
141+
}
142+
143+
step, err := dbos.GetEvent[int](dbosCtx, taskID, STEPS_EVENT, 0)
144+
if err != nil {
145+
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
146+
return
147+
}
148+
149+
c.String(http.StatusOK, fmt.Sprintf("%d", step))
150+
}
151+
152+
// This endpoint crashes the application. For demonstration purposes only :)
153+
func crashHandler(c *gin.Context) {
154+
os.Exit(1)
155+
}

0 commit comments

Comments
 (0)