package dbos import ( "context" "fmt" "log" "reflect" "runtime" "strings" "time" "github.com/dbos-inc/dbos-transact-golang/dbos" ) type Client struct { c dbos.Client q string } func QueueClient(ctx context.Context, conn, q string, foo func(*Client) error) error { connctx, conncan := context.WithTimeout(ctx, 10*time.Second) defer conncan() c, err := dbos.NewClient(connctx, dbos.ClientConfig{ DatabaseURL: conn, }) if err != nil { return err } defer c.Shutdown(5 * time.Second) return foo(&Client{c: c, q: q}) } func (c *Client) WithQueue(q string) *Client { c2 := *c c2.q = q return &c2 } func Go[P any, R any](ctx context.Context, c *Client, foo dbos.Workflow[P, R], input P, globalDedupe, concurrentDedupe string) error { log.Printf("[client] going to %s#%s#%s", fooToName(foo), globalDedupe, concurrentDedupe) result := make(chan error) go func() { defer close(result) _, err := dbos.Enqueue[P, R](c.c, c.q, fooToName(foo), input, dbos.WithEnqueueDeduplicationID(concurrentDedupe), dbos.WithEnqueueApplicationVersion("latest"), dbos.WithEnqueueWorkflowID(globalDedupe)) select { case <-ctx.Done(): case result <- err: } }() select { case err := <-result: return err case <-ctx.Done(): } return ctx.Err() } // https://github.com/dbos-inc/dbos-transact-golang/blob/0d755bda26e3162c823f3e316aa0f88677b8b246/dbos/workflow.go#L577 func fooToName[P any, R any](fn dbos.Workflow[P, R]) string { ptr := reflect.ValueOf(fn).Pointer() fqn := runtime.FuncForPC(ptr).Name() // If this is a generic workflow, append the actual types to the FQN if strings.Contains(fqn, "[") { fqn = strings.Split(fqn, "[")[0] fqn = fmt.Sprintf("%s[%s,%s]", fqn, reflect.TypeFor[P]().String(), reflect.TypeFor[R]().String(), ) } return fqn }