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