@dbos-inc/dbos-sdk 0.7.18-preview

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/dbos-config.schema.json +121 -0
  4. package/dbos-test-config.yaml +16 -0
  5. package/dist/schemas/system_db_schema.d.ts +34 -0
  6. package/dist/schemas/system_db_schema.d.ts.map +1 -0
  7. package/dist/schemas/system_db_schema.js +75 -0
  8. package/dist/schemas/system_db_schema.js.map +1 -0
  9. package/dist/schemas/user_db_schema.d.ts +11 -0
  10. package/dist/schemas/user_db_schema.d.ts.map +1 -0
  11. package/dist/schemas/user_db_schema.js +16 -0
  12. package/dist/schemas/user_db_schema.js.map +1 -0
  13. package/dist/src/cloud-cli/applications/configure.d.ts +2 -0
  14. package/dist/src/cloud-cli/applications/configure.d.ts.map +1 -0
  15. package/dist/src/cloud-cli/applications/configure.js +57 -0
  16. package/dist/src/cloud-cli/applications/configure.js.map +1 -0
  17. package/dist/src/cloud-cli/applications/delete-app.d.ts +2 -0
  18. package/dist/src/cloud-cli/applications/delete-app.d.ts.map +1 -0
  19. package/dist/src/cloud-cli/applications/delete-app.js +36 -0
  20. package/dist/src/cloud-cli/applications/delete-app.js.map +1 -0
  21. package/dist/src/cloud-cli/applications/deploy-app-code.d.ts +2 -0
  22. package/dist/src/cloud-cli/applications/deploy-app-code.d.ts.map +1 -0
  23. package/dist/src/cloud-cli/applications/deploy-app-code.js +64 -0
  24. package/dist/src/cloud-cli/applications/deploy-app-code.js.map +1 -0
  25. package/dist/src/cloud-cli/applications/get-app-logs.d.ts +2 -0
  26. package/dist/src/cloud-cli/applications/get-app-logs.d.ts.map +1 -0
  27. package/dist/src/cloud-cli/applications/get-app-logs.js +37 -0
  28. package/dist/src/cloud-cli/applications/get-app-logs.js.map +1 -0
  29. package/dist/src/cloud-cli/applications/index.d.ts +8 -0
  30. package/dist/src/cloud-cli/applications/index.d.ts.map +1 -0
  31. package/dist/src/cloud-cli/applications/index.js +18 -0
  32. package/dist/src/cloud-cli/applications/index.js.map +1 -0
  33. package/dist/src/cloud-cli/applications/list-apps.d.ts +2 -0
  34. package/dist/src/cloud-cli/applications/list-apps.d.ts.map +1 -0
  35. package/dist/src/cloud-cli/applications/list-apps.js +45 -0
  36. package/dist/src/cloud-cli/applications/list-apps.js.map +1 -0
  37. package/dist/src/cloud-cli/applications/register-app.d.ts +2 -0
  38. package/dist/src/cloud-cli/applications/register-app.d.ts.map +1 -0
  39. package/dist/src/cloud-cli/applications/register-app.js +41 -0
  40. package/dist/src/cloud-cli/applications/register-app.js.map +1 -0
  41. package/dist/src/cloud-cli/applications/types.d.ts +7 -0
  42. package/dist/src/cloud-cli/applications/types.d.ts.map +1 -0
  43. package/dist/src/cloud-cli/applications/types.js +3 -0
  44. package/dist/src/cloud-cli/applications/types.js.map +1 -0
  45. package/dist/src/cloud-cli/applications/update-app.d.ts +2 -0
  46. package/dist/src/cloud-cli/applications/update-app.d.ts.map +1 -0
  47. package/dist/src/cloud-cli/applications/update-app.js +42 -0
  48. package/dist/src/cloud-cli/applications/update-app.js.map +1 -0
  49. package/dist/src/cloud-cli/cli.d.ts +3 -0
  50. package/dist/src/cloud-cli/cli.d.ts.map +1 -0
  51. package/dist/src/cloud-cli/cli.js +148 -0
  52. package/dist/src/cloud-cli/cli.js.map +1 -0
  53. package/dist/src/cloud-cli/login.d.ts +7 -0
  54. package/dist/src/cloud-cli/login.d.ts.map +1 -0
  55. package/dist/src/cloud-cli/login.js +40 -0
  56. package/dist/src/cloud-cli/login.js.map +1 -0
  57. package/dist/src/cloud-cli/register.d.ts +2 -0
  58. package/dist/src/cloud-cli/register.d.ts.map +1 -0
  59. package/dist/src/cloud-cli/register.js +35 -0
  60. package/dist/src/cloud-cli/register.js.map +1 -0
  61. package/dist/src/cloud-cli/userdb.d.ts +4 -0
  62. package/dist/src/cloud-cli/userdb.d.ts.map +1 -0
  63. package/dist/src/cloud-cli/userdb.js +149 -0
  64. package/dist/src/cloud-cli/userdb.js.map +1 -0
  65. package/dist/src/cloud-cli/utils.d.ts +3 -0
  66. package/dist/src/cloud-cli/utils.d.ts.map +1 -0
  67. package/dist/src/cloud-cli/utils.js +17 -0
  68. package/dist/src/cloud-cli/utils.js.map +1 -0
  69. package/dist/src/communicator.d.ts +24 -0
  70. package/dist/src/communicator.d.ts.map +1 -0
  71. package/dist/src/communicator.js +26 -0
  72. package/dist/src/communicator.js.map +1 -0
  73. package/dist/src/context.d.ts +60 -0
  74. package/dist/src/context.d.ts.map +1 -0
  75. package/dist/src/context.js +94 -0
  76. package/dist/src/context.js.map +1 -0
  77. package/dist/src/data_validation.d.ts +3 -0
  78. package/dist/src/data_validation.d.ts.map +1 -0
  79. package/dist/src/data_validation.js +168 -0
  80. package/dist/src/data_validation.js.map +1 -0
  81. package/dist/src/dbos-executor.d.ts +79 -0
  82. package/dist/src/dbos-executor.d.ts.map +1 -0
  83. package/dist/src/dbos-executor.js +408 -0
  84. package/dist/src/dbos-executor.js.map +1 -0
  85. package/dist/src/dbos-runtime/TypeParser.d.ts +33 -0
  86. package/dist/src/dbos-runtime/TypeParser.d.ts.map +1 -0
  87. package/dist/src/dbos-runtime/TypeParser.js +104 -0
  88. package/dist/src/dbos-runtime/TypeParser.js.map +1 -0
  89. package/dist/src/dbos-runtime/applicationVersion.d.ts +3 -0
  90. package/dist/src/dbos-runtime/applicationVersion.d.ts.map +1 -0
  91. package/dist/src/dbos-runtime/applicationVersion.js +13 -0
  92. package/dist/src/dbos-runtime/applicationVersion.js.map +1 -0
  93. package/dist/src/dbos-runtime/cli.d.ts +8 -0
  94. package/dist/src/dbos-runtime/cli.d.ts.map +1 -0
  95. package/dist/src/dbos-runtime/cli.js +52 -0
  96. package/dist/src/dbos-runtime/cli.js.map +1 -0
  97. package/dist/src/dbos-runtime/config.d.ts +28 -0
  98. package/dist/src/dbos-runtime/config.d.ts.map +1 -0
  99. package/dist/src/dbos-runtime/config.js +111 -0
  100. package/dist/src/dbos-runtime/config.js.map +1 -0
  101. package/dist/src/dbos-runtime/init.d.ts +7 -0
  102. package/dist/src/dbos-runtime/init.d.ts.map +1 -0
  103. package/dist/src/dbos-runtime/init.js +51 -0
  104. package/dist/src/dbos-runtime/init.js.map +1 -0
  105. package/dist/src/dbos-runtime/openApi.d.ts +35 -0
  106. package/dist/src/dbos-runtime/openApi.d.ts.map +1 -0
  107. package/dist/src/dbos-runtime/openApi.js +595 -0
  108. package/dist/src/dbos-runtime/openApi.js.map +1 -0
  109. package/dist/src/dbos-runtime/runtime.d.ts +28 -0
  110. package/dist/src/dbos-runtime/runtime.d.ts.map +1 -0
  111. package/dist/src/dbos-runtime/runtime.js +96 -0
  112. package/dist/src/dbos-runtime/runtime.js.map +1 -0
  113. package/dist/src/dbos-runtime/tsDiagUtil.d.ts +16 -0
  114. package/dist/src/dbos-runtime/tsDiagUtil.d.ts.map +1 -0
  115. package/dist/src/dbos-runtime/tsDiagUtil.js +72 -0
  116. package/dist/src/dbos-runtime/tsDiagUtil.js.map +1 -0
  117. package/dist/src/decorators.d.ts +118 -0
  118. package/dist/src/decorators.d.ts.map +1 -0
  119. package/dist/src/decorators.js +467 -0
  120. package/dist/src/decorators.js.map +1 -0
  121. package/dist/src/error.d.ts +44 -0
  122. package/dist/src/error.d.ts.map +1 -0
  123. package/dist/src/error.js +164 -0
  124. package/dist/src/error.js.map +1 -0
  125. package/dist/src/httpServer/handler.d.ts +62 -0
  126. package/dist/src/httpServer/handler.d.ts.map +1 -0
  127. package/dist/src/httpServer/handler.js +168 -0
  128. package/dist/src/httpServer/handler.js.map +1 -0
  129. package/dist/src/httpServer/middleware.d.ts +56 -0
  130. package/dist/src/httpServer/middleware.d.ts.map +1 -0
  131. package/dist/src/httpServer/middleware.js +57 -0
  132. package/dist/src/httpServer/middleware.js.map +1 -0
  133. package/dist/src/httpServer/server.d.ts +40 -0
  134. package/dist/src/httpServer/server.d.ts.map +1 -0
  135. package/dist/src/httpServer/server.js +231 -0
  136. package/dist/src/httpServer/server.js.map +1 -0
  137. package/dist/src/index.d.ts +12 -0
  138. package/dist/src/index.d.ts.map +1 -0
  139. package/dist/src/index.js +75 -0
  140. package/dist/src/index.js.map +1 -0
  141. package/dist/src/provenance/provenance_daemon.d.ts +34 -0
  142. package/dist/src/provenance/provenance_daemon.d.ts.map +1 -0
  143. package/dist/src/provenance/provenance_daemon.js +86 -0
  144. package/dist/src/provenance/provenance_daemon.js.map +1 -0
  145. package/dist/src/system_database.d.ts +69 -0
  146. package/dist/src/system_database.d.ts.map +1 -0
  147. package/dist/src/system_database.js +384 -0
  148. package/dist/src/system_database.js.map +1 -0
  149. package/dist/src/telemetry/collector.d.ts +17 -0
  150. package/dist/src/telemetry/collector.d.ts.map +1 -0
  151. package/dist/src/telemetry/collector.js +77 -0
  152. package/dist/src/telemetry/collector.js.map +1 -0
  153. package/dist/src/telemetry/exporters.d.ts +29 -0
  154. package/dist/src/telemetry/exporters.d.ts.map +1 -0
  155. package/dist/src/telemetry/exporters.js +186 -0
  156. package/dist/src/telemetry/exporters.js.map +1 -0
  157. package/dist/src/telemetry/index.d.ts +7 -0
  158. package/dist/src/telemetry/index.d.ts.map +1 -0
  159. package/dist/src/telemetry/index.js +3 -0
  160. package/dist/src/telemetry/index.js.map +1 -0
  161. package/dist/src/telemetry/logs.d.ts +25 -0
  162. package/dist/src/telemetry/logs.d.ts.map +1 -0
  163. package/dist/src/telemetry/logs.js +91 -0
  164. package/dist/src/telemetry/logs.js.map +1 -0
  165. package/dist/src/telemetry/signals.d.ts +30 -0
  166. package/dist/src/telemetry/signals.d.ts.map +1 -0
  167. package/dist/src/telemetry/signals.js +11 -0
  168. package/dist/src/telemetry/signals.js.map +1 -0
  169. package/dist/src/telemetry/traces.d.ts +17 -0
  170. package/dist/src/telemetry/traces.d.ts.map +1 -0
  171. package/dist/src/telemetry/traces.js +76 -0
  172. package/dist/src/telemetry/traces.js.map +1 -0
  173. package/dist/src/testing/testing_runtime.d.ts +76 -0
  174. package/dist/src/testing/testing_runtime.d.ts.map +1 -0
  175. package/dist/src/testing/testing_runtime.js +147 -0
  176. package/dist/src/testing/testing_runtime.js.map +1 -0
  177. package/dist/src/transaction.d.ts +28 -0
  178. package/dist/src/transaction.d.ts.map +1 -0
  179. package/dist/src/transaction.js +27 -0
  180. package/dist/src/transaction.js.map +1 -0
  181. package/dist/src/user_database.d.ts +132 -0
  182. package/dist/src/user_database.d.ts.map +1 -0
  183. package/dist/src/user_database.js +324 -0
  184. package/dist/src/user_database.js.map +1 -0
  185. package/dist/src/utils.d.ts +6 -0
  186. package/dist/src/utils.d.ts.map +1 -0
  187. package/dist/src/utils.js +35 -0
  188. package/dist/src/utils.js.map +1 -0
  189. package/dist/src/workflow.d.ts +179 -0
  190. package/dist/src/workflow.d.ts.map +1 -0
  191. package/dist/src/workflow.js +446 -0
  192. package/dist/src/workflow.js.map +1 -0
  193. package/examples/hello/README.md +41 -0
  194. package/examples/hello/dbos-config.yaml +15 -0
  195. package/examples/hello/jest.config.js +8 -0
  196. package/examples/hello/knexfile.ts +23 -0
  197. package/examples/hello/migrations/create_dbos_hello_tables.ts +12 -0
  198. package/examples/hello/package.json +21 -0
  199. package/examples/hello/src/operations.test.ts +38 -0
  200. package/examples/hello/src/operations.ts +21 -0
  201. package/examples/hello/start_postgres_docker.sh +23 -0
  202. package/examples/hello/tsconfig.json +24 -0
  203. package/package.json +78 -0
@@ -0,0 +1,446 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RetrievedHandle = exports.InvokedHandle = exports.WorkflowContextImpl = exports.StatusString = void 0;
4
+ /* eslint-disable @typescript-eslint/no-explicit-any */
5
+ const dbos_executor_1 = require("./dbos-executor");
6
+ const transaction_1 = require("./transaction");
7
+ const communicator_1 = require("./communicator");
8
+ const error_1 = require("./error");
9
+ const serialize_error_1 = require("serialize-error");
10
+ const utils_1 = require("./utils");
11
+ const api_1 = require("@opentelemetry/api");
12
+ const context_1 = require("./context");
13
+ const decorators_1 = require("./decorators");
14
+ exports.StatusString = {
15
+ PENDING: "PENDING",
16
+ SUCCESS: "SUCCESS",
17
+ ERROR: "ERROR",
18
+ };
19
+ class WorkflowContextImpl extends context_1.DBOSContextImpl {
20
+ workflowConfig;
21
+ functionID = 0;
22
+ #wfe;
23
+ resultBuffer = new Map();
24
+ isTempWorkflow;
25
+ constructor(wfe, parentCtx, workflowUUID, workflowConfig, workflowName) {
26
+ const span = wfe.tracer.startSpan(workflowName, {
27
+ workflowUUID: workflowUUID,
28
+ operationName: workflowName,
29
+ runAs: parentCtx?.authenticatedUser ?? "",
30
+ }, parentCtx?.span);
31
+ super(workflowName, span, wfe.logger, parentCtx);
32
+ this.workflowConfig = workflowConfig;
33
+ this.workflowUUID = workflowUUID;
34
+ this.#wfe = wfe;
35
+ this.isTempWorkflow = wfe.tempWorkflowName === workflowName;
36
+ if (wfe.config.application) {
37
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
38
+ this.applicationConfig = wfe.config.application;
39
+ }
40
+ }
41
+ functionIDGetIncrement() {
42
+ return this.functionID++;
43
+ }
44
+ /**
45
+ * Check if an operation has already executed in a workflow.
46
+ * If it previously executed succesfully, return its output.
47
+ * If it previously executed and threw an error, throw that error.
48
+ * Otherwise, return DBOSNull.
49
+ * Also return the transaction snapshot information of this current transaction.
50
+ */
51
+ async checkExecution(client, funcID) {
52
+ // Note: we read the current snapshot, not the recorded one!
53
+ const rows = await this.#wfe.userDatabase.queryWithClient(client, "(SELECT output, error, pg_current_snapshot()::text as txn_snapshot, true as recorded FROM dbos.transaction_outputs WHERE workflow_uuid=$1 AND function_id=$2 UNION ALL SELECT null as output, null as error, pg_current_snapshot()::text as txn_snapshot, false as recorded) ORDER BY recorded", this.workflowUUID, funcID);
54
+ if (rows.length === 0 || rows.length > 2) {
55
+ this.logger.error("Unexpected! This should never happen. Returned rows: " + rows.toString());
56
+ throw new error_1.DBOSError("This should never happen. Returned rows: " + rows.toString());
57
+ }
58
+ const res = {
59
+ output: dbos_executor_1.dbosNull,
60
+ txn_snapshot: ""
61
+ };
62
+ // recorded=false row will be first because we used ORDER BY.
63
+ res.txn_snapshot = rows[0].txn_snapshot;
64
+ if (rows.length == 2) {
65
+ if (JSON.parse(rows[1].error) !== null) {
66
+ throw (0, serialize_error_1.deserializeError)(JSON.parse(rows[1].error));
67
+ }
68
+ else {
69
+ res.output = JSON.parse(rows[1].output);
70
+ }
71
+ }
72
+ return res;
73
+ }
74
+ /**
75
+ * Write all entries in the workflow result buffer to the database.
76
+ * If it encounters a primary key error, this indicates a concurrent execution with the same UUID, so throw an DBOSError.
77
+ */
78
+ async flushResultBuffer(client) {
79
+ const funcIDs = Array.from(this.resultBuffer.keys());
80
+ if (funcIDs.length === 0) {
81
+ return;
82
+ }
83
+ funcIDs.sort();
84
+ try {
85
+ let sqlStmt = "INSERT INTO dbos.transaction_outputs (workflow_uuid, function_id, output, error, txn_id, txn_snapshot) VALUES ";
86
+ let paramCnt = 1;
87
+ const values = [];
88
+ for (const funcID of funcIDs) {
89
+ // Capture output and also transaction snapshot information.
90
+ // Initially, no txn_id because no queries executed.
91
+ const recorded = this.resultBuffer.get(funcID);
92
+ const output = recorded.output;
93
+ const txnSnapshot = recorded.txn_snapshot;
94
+ if (paramCnt > 1) {
95
+ sqlStmt += ", ";
96
+ }
97
+ sqlStmt += `($${paramCnt++}, $${paramCnt++}, $${paramCnt++}, $${paramCnt++}, null, $${paramCnt++})`;
98
+ values.push(this.workflowUUID, funcID, JSON.stringify(output), JSON.stringify(null), txnSnapshot);
99
+ }
100
+ this.logger.debug(sqlStmt);
101
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
102
+ await this.#wfe.userDatabase.queryWithClient(client, sqlStmt, ...values);
103
+ }
104
+ catch (error) {
105
+ if (this.#wfe.userDatabase.isKeyConflictError(error)) {
106
+ // Serialization and primary key conflict (Postgres).
107
+ throw new error_1.DBOSWorkflowConflictUUIDError(this.workflowUUID);
108
+ }
109
+ else {
110
+ throw error;
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Buffer a placeholder value to guard an operation against concurrent executions with the same UUID.
116
+ */
117
+ guardOperation(funcID, txnSnapshot) {
118
+ const guardOutput = {
119
+ output: null,
120
+ txn_snapshot: txnSnapshot,
121
+ };
122
+ this.resultBuffer.set(funcID, guardOutput);
123
+ }
124
+ /**
125
+ * Write a guarded operation's output to the database.
126
+ */
127
+ async recordGuardedOutput(client, funcID, output) {
128
+ const serialOutput = JSON.stringify(output);
129
+ const rows = await this.#wfe.userDatabase.queryWithClient(client, "UPDATE dbos.transaction_outputs SET output=$1, txn_id=(select pg_current_xact_id_if_assigned()::text) WHERE workflow_uuid=$2 AND function_id=$3 RETURNING txn_id;", serialOutput, this.workflowUUID, funcID);
130
+ return rows[0].txn_id; // Must have a transaction ID because we inserted the guard before.
131
+ }
132
+ /**
133
+ * Record an error in a guarded operation to the database.
134
+ */
135
+ async recordGuardedError(client, funcID, err) {
136
+ const serialErr = JSON.stringify((0, serialize_error_1.serializeError)(err));
137
+ await this.#wfe.userDatabase.queryWithClient(client, "UPDATE dbos.transaction_outputs SET error=$1 WHERE workflow_uuid=$2 AND function_id=$3;", serialErr, this.workflowUUID, funcID);
138
+ }
139
+ /**
140
+ * Invoke another workflow as its child workflow and return a workflow handle.
141
+ * The child workflow is guaranteed to be executed exactly once, even if the workflow is retried with the same UUID.
142
+ * We pass in itself as a parent context adn assign the child workflow with a derministic UUID "this.workflowUUID-functionID", which appends a function ID to its own UUID.
143
+ */
144
+ async childWorkflow(wf, ...args) {
145
+ // Note: cannot use invoke for childWorkflow because of potential recursive types on the workflow itself.
146
+ const funcId = this.functionIDGetIncrement();
147
+ const childUUID = this.workflowUUID + "-" + funcId;
148
+ return this.#wfe.workflow(wf, { parentCtx: this, workflowUUID: childUUID }, ...args);
149
+ }
150
+ /**
151
+ * Execute a transactional function.
152
+ * The transaction is guaranteed to execute exactly once, even if the workflow is retried with the same UUID.
153
+ * If the transaction encounters a Postgres serialization error, retry it.
154
+ * If it encounters any other error, throw it.
155
+ */
156
+ async transaction(txn, ...args) {
157
+ const config = this.#wfe.transactionConfigMap.get(txn.name);
158
+ if (config === undefined) {
159
+ throw new error_1.DBOSNotRegisteredError(txn.name);
160
+ }
161
+ const readOnly = config.readOnly ?? false;
162
+ let retryWaitMillis = 1;
163
+ const backoffFactor = 2;
164
+ const funcId = this.functionIDGetIncrement();
165
+ const span = this.#wfe.tracer.startSpan(txn.name, {
166
+ workflowUUID: this.workflowUUID,
167
+ operationName: txn.name,
168
+ runAs: this.authenticatedUser,
169
+ readOnly: readOnly,
170
+ isolationLevel: config.isolationLevel,
171
+ }, this.span);
172
+ // eslint-disable-next-line no-constant-condition
173
+ while (true) {
174
+ const wrappedTransaction = async (client) => {
175
+ // Check if this execution previously happened, returning its original result if it did.
176
+ const tCtxt = new transaction_1.TransactionContextImpl(this.#wfe.userDatabase.getName(), client, this, span, this.#wfe.logger, funcId, txn.name);
177
+ const check = await this.checkExecution(client, funcId);
178
+ if (check.output !== dbos_executor_1.dbosNull) {
179
+ tCtxt.span.setAttribute("cached", true);
180
+ tCtxt.span.setStatus({ code: api_1.SpanStatusCode.OK });
181
+ this.#wfe.tracer.endSpan(tCtxt.span);
182
+ return check.output;
183
+ }
184
+ // TODO: record snapshot information in result buffer.
185
+ // Flush the result buffer, setting a guard to block concurrent executions with the same UUID.
186
+ this.guardOperation(funcId, check.txn_snapshot);
187
+ if (!readOnly) {
188
+ await this.flushResultBuffer(client);
189
+ }
190
+ // Execute the user's transaction.
191
+ const result = await txn(tCtxt, ...args);
192
+ // Record the execution, commit, and return.
193
+ if (readOnly) {
194
+ // Buffer the output of read-only transactions instead of synchronously writing it.
195
+ const guardOutput = {
196
+ output: result,
197
+ txn_snapshot: check.txn_snapshot,
198
+ };
199
+ this.resultBuffer.set(funcId, guardOutput);
200
+ }
201
+ else {
202
+ // Synchronously record the output of write transactions and obtain the transaction ID.
203
+ const pg_txn_id = await this.recordGuardedOutput(client, funcId, result);
204
+ tCtxt.span.setAttribute("transaction_id", pg_txn_id);
205
+ this.resultBuffer.clear();
206
+ }
207
+ return result;
208
+ };
209
+ try {
210
+ const result = await this.#wfe.userDatabase.transaction(wrappedTransaction, config);
211
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
212
+ return result;
213
+ }
214
+ catch (err) {
215
+ if (this.#wfe.userDatabase.isRetriableTransactionError(err)) {
216
+ // serialization_failure in PostgreSQL
217
+ span.addEvent("TXN SERIALIZATION FAILURE", { retryWaitMillis });
218
+ // Retry serialization failures.
219
+ await (0, utils_1.sleep)(retryWaitMillis);
220
+ retryWaitMillis *= backoffFactor;
221
+ continue;
222
+ }
223
+ // Record and throw other errors.
224
+ const e = err;
225
+ await this.#wfe.userDatabase.transaction(async (client) => {
226
+ await this.flushResultBuffer(client);
227
+ await this.recordGuardedError(client, funcId, e);
228
+ }, { isolationLevel: transaction_1.IsolationLevel.ReadCommitted });
229
+ this.resultBuffer.clear();
230
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: e.message });
231
+ throw err;
232
+ }
233
+ finally {
234
+ this.#wfe.tracer.endSpan(span);
235
+ }
236
+ }
237
+ }
238
+ /**
239
+ * Execute a communicator function.
240
+ * If it encounters any error, retry according to its configured retry policy until the maximum number of attempts is reached, then throw an DBOSError.
241
+ * The communicator may execute many times, but once it is complete, it will not re-execute.
242
+ */
243
+ async external(commFn, ...args) {
244
+ const commConfig = this.#wfe.communicatorConfigMap.get(commFn.name);
245
+ if (commConfig === undefined) {
246
+ throw new error_1.DBOSNotRegisteredError(commFn.name);
247
+ }
248
+ const funcID = this.functionIDGetIncrement();
249
+ const span = this.#wfe.tracer.startSpan(commFn.name, {
250
+ workflowUUID: this.workflowUUID,
251
+ operationName: commFn.name,
252
+ runAs: this.authenticatedUser,
253
+ retriesAllowed: commConfig.retriesAllowed,
254
+ intervalSeconds: commConfig.intervalSeconds,
255
+ maxAttempts: commConfig.maxAttempts,
256
+ backoffRate: commConfig.backoffRate,
257
+ }, this.span);
258
+ const ctxt = new communicator_1.CommunicatorContextImpl(this, funcID, span, this.#wfe.logger, commConfig, commFn.name);
259
+ await this.#wfe.userDatabase.transaction(async (client) => {
260
+ await this.flushResultBuffer(client);
261
+ }, { isolationLevel: transaction_1.IsolationLevel.ReadCommitted });
262
+ this.resultBuffer.clear();
263
+ // Check if this execution previously happened, returning its original result if it did.
264
+ const check = await this.#wfe.systemDatabase.checkOperationOutput(this.workflowUUID, ctxt.functionID);
265
+ if (check !== dbos_executor_1.dbosNull) {
266
+ ctxt.span.setAttribute("cached", true);
267
+ ctxt.span.setStatus({ code: api_1.SpanStatusCode.OK });
268
+ this.#wfe.tracer.endSpan(ctxt.span);
269
+ return check;
270
+ }
271
+ // Execute the communicator function. If it throws an exception, retry with exponential backoff.
272
+ // After reaching the maximum number of retries, throw an DBOSError.
273
+ let result = dbos_executor_1.dbosNull;
274
+ let err = dbos_executor_1.dbosNull;
275
+ if (ctxt.retriesAllowed) {
276
+ let numAttempts = 0;
277
+ let intervalSeconds = ctxt.intervalSeconds;
278
+ while (result === dbos_executor_1.dbosNull && numAttempts++ < ctxt.maxAttempts) {
279
+ try {
280
+ result = await commFn(ctxt, ...args);
281
+ }
282
+ catch (error) {
283
+ if (numAttempts < ctxt.maxAttempts) {
284
+ // Sleep for an interval, then increase the interval by backoffRate.
285
+ await (0, utils_1.sleep)(intervalSeconds);
286
+ intervalSeconds *= ctxt.backoffRate;
287
+ }
288
+ ctxt.span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
289
+ this.#wfe.tracer.endSpan(ctxt.span);
290
+ }
291
+ }
292
+ }
293
+ else {
294
+ try {
295
+ result = await commFn(ctxt, ...args);
296
+ }
297
+ catch (error) {
298
+ err = error;
299
+ ctxt.span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
300
+ this.#wfe.tracer.endSpan(ctxt.span);
301
+ }
302
+ }
303
+ // `result` can only be dbosNull when the communicator timed out
304
+ if (result === dbos_executor_1.dbosNull) {
305
+ // Record the error, then throw it.
306
+ err = err === dbos_executor_1.dbosNull ? new error_1.DBOSError("Communicator reached maximum retries.", 1) : err;
307
+ await this.#wfe.systemDatabase.recordOperationError(this.workflowUUID, ctxt.functionID, err);
308
+ ctxt.span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: err.message });
309
+ this.#wfe.tracer.endSpan(ctxt.span);
310
+ throw err;
311
+ }
312
+ else {
313
+ // Record the execution and return.
314
+ await this.#wfe.systemDatabase.recordOperationOutput(this.workflowUUID, ctxt.functionID, result);
315
+ ctxt.span.setStatus({ code: api_1.SpanStatusCode.OK });
316
+ this.#wfe.tracer.endSpan(ctxt.span);
317
+ return result;
318
+ }
319
+ }
320
+ /**
321
+ * Send a message to a workflow identified by a UUID.
322
+ * The message can optionally be tagged with a topic.
323
+ */
324
+ async send(destinationUUID, message, topic) {
325
+ const functionID = this.functionIDGetIncrement();
326
+ await this.#wfe.userDatabase.transaction(async (client) => {
327
+ await this.flushResultBuffer(client);
328
+ }, { isolationLevel: transaction_1.IsolationLevel.ReadCommitted });
329
+ this.resultBuffer.clear();
330
+ await this.#wfe.systemDatabase.send(this.workflowUUID, functionID, destinationUUID, message, topic);
331
+ }
332
+ /**
333
+ * Consume and return the oldest unconsumed message sent to your UUID.
334
+ * If a topic is specified, retrieve the oldest message tagged with that topic.
335
+ * Otherwise, retrieve the oldest message with no topic.
336
+ */
337
+ async recv(topic, timeoutSeconds = dbos_executor_1.DBOSExecutor.defaultNotificationTimeoutSec) {
338
+ const functionID = this.functionIDGetIncrement();
339
+ await this.#wfe.userDatabase.transaction(async (client) => {
340
+ await this.flushResultBuffer(client);
341
+ }, { isolationLevel: transaction_1.IsolationLevel.ReadCommitted });
342
+ this.resultBuffer.clear();
343
+ return this.#wfe.systemDatabase.recv(this.workflowUUID, functionID, topic, timeoutSeconds);
344
+ }
345
+ /**
346
+ * Emit a workflow event, represented as a key-value pair.
347
+ * Events are immutable once set.
348
+ */
349
+ async setEvent(key, value) {
350
+ const functionID = this.functionIDGetIncrement();
351
+ await this.#wfe.userDatabase.transaction(async (client) => {
352
+ await this.flushResultBuffer(client);
353
+ }, { isolationLevel: transaction_1.IsolationLevel.ReadCommitted });
354
+ this.resultBuffer.clear();
355
+ await this.#wfe.systemDatabase.setEvent(this.workflowUUID, functionID, key, value);
356
+ }
357
+ /**
358
+ * Generate a proxy object for the provided class that wraps direct calls (i.e. OpClass.someMethod(param))
359
+ * to use WorkflowContext.Transaction(OpClass.someMethod, param);
360
+ */
361
+ invoke(object) {
362
+ const ops = (0, decorators_1.getRegisteredOperations)(object);
363
+ const proxy = {};
364
+ for (const op of ops) {
365
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
366
+ proxy[op.name] = op.txnConfig
367
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
368
+ ? (...args) => this.transaction(op.registeredFunction, ...args)
369
+ : op.commConfig
370
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
371
+ ? (...args) => this.external(op.registeredFunction, ...args)
372
+ : undefined;
373
+ }
374
+ return proxy;
375
+ }
376
+ /**
377
+ * Wait for a workflow to emit an event, then return its value.
378
+ */
379
+ getEvent(targetUUID, key, timeoutSeconds = dbos_executor_1.DBOSExecutor.defaultNotificationTimeoutSec) {
380
+ const functionID = this.functionIDGetIncrement();
381
+ return this.#wfe.systemDatabase.getEvent(targetUUID, key, timeoutSeconds, this.workflowUUID, functionID);
382
+ }
383
+ /**
384
+ * Retrieve a handle for a workflow UUID.
385
+ */
386
+ retrieveWorkflow(targetUUID) {
387
+ const functionID = this.functionIDGetIncrement();
388
+ return new RetrievedHandle(this.#wfe.systemDatabase, targetUUID, this.workflowUUID, functionID);
389
+ }
390
+ }
391
+ exports.WorkflowContextImpl = WorkflowContextImpl;
392
+ /**
393
+ * The handle returned when invoking a workflow with DBOSExecutor.workflow
394
+ */
395
+ class InvokedHandle {
396
+ systemDatabase;
397
+ workflowPromise;
398
+ workflowUUID;
399
+ workflowName;
400
+ callerUUID;
401
+ callerFunctionID;
402
+ constructor(systemDatabase, workflowPromise, workflowUUID, workflowName, callerUUID, callerFunctionID) {
403
+ this.systemDatabase = systemDatabase;
404
+ this.workflowPromise = workflowPromise;
405
+ this.workflowUUID = workflowUUID;
406
+ this.workflowName = workflowName;
407
+ this.callerUUID = callerUUID;
408
+ this.callerFunctionID = callerFunctionID;
409
+ }
410
+ getWorkflowUUID() {
411
+ return this.workflowUUID;
412
+ }
413
+ async getStatus() {
414
+ return this.systemDatabase.getWorkflowStatus(this.workflowUUID, this.callerUUID, this.callerFunctionID);
415
+ }
416
+ async getResult() {
417
+ return this.workflowPromise;
418
+ }
419
+ }
420
+ exports.InvokedHandle = InvokedHandle;
421
+ /**
422
+ * The handle returned when retrieving a workflow with DBOSExecutor.retrieve
423
+ */
424
+ class RetrievedHandle {
425
+ systemDatabase;
426
+ workflowUUID;
427
+ callerUUID;
428
+ callerFunctionID;
429
+ constructor(systemDatabase, workflowUUID, callerUUID, callerFunctionID) {
430
+ this.systemDatabase = systemDatabase;
431
+ this.workflowUUID = workflowUUID;
432
+ this.callerUUID = callerUUID;
433
+ this.callerFunctionID = callerFunctionID;
434
+ }
435
+ getWorkflowUUID() {
436
+ return this.workflowUUID;
437
+ }
438
+ async getStatus() {
439
+ return await this.systemDatabase.getWorkflowStatus(this.workflowUUID, this.callerUUID, this.callerFunctionID);
440
+ }
441
+ async getResult() {
442
+ return await this.systemDatabase.getWorkflowResult(this.workflowUUID);
443
+ }
444
+ }
445
+ exports.RetrievedHandle = RetrievedHandle;
446
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ # DBOS Hello
2
+
3
+ This is a [DBOS app](https://docs.dbos.dev/) bootstrapped with `dbos init`.
4
+
5
+ ## Getting Started
6
+
7
+ First, start the database.
8
+ DBOS workflow works with any Postgres database, but to make things easier, we've provided a nifty script that starts Postgres locally in a Docker container and creates a database:
9
+
10
+ ```bash
11
+ export PGPASSWORD=dbos
12
+ ./start_postgres_docker.sh
13
+ ```
14
+
15
+ Then, create some database tables.
16
+ In this quickstart, we use [knex.js](https://knexjs.org/) to manage database migrations.
17
+ Run our provided migration to create a database table:
18
+
19
+ ```bash
20
+ npx knex migrate:latest
21
+ ```
22
+
23
+ Next, build and run the app:
24
+
25
+ ```bash
26
+ npm run build
27
+ npx dbos start
28
+ ```
29
+
30
+ Finally, curl the server to see that it's working!
31
+
32
+ ```bash
33
+ curl http://localhost:3000/greeting/dbos
34
+ ```
35
+
36
+ You can add more functionality to the app by modifying `src/operations.ts`, then re-building and re-starting it.
37
+ We can help you get started in our [programming quickstart](https://docs.dbos.dev/getting-started/quickstart-programming-1).
38
+
39
+ ## Learn More
40
+
41
+ To learn more about DBOS, take a look at [our documentation](https://docs.dbos.dev/) or our [source code](https://github.com/dbos-inc/dbos-sdk).
@@ -0,0 +1,15 @@
1
+ # To enable auto-completion and validation for this file in VSCode, install the RedHat YAML extension
2
+ # https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml
3
+
4
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/dbos-inc/dbos-sdk/main/dbos-config.schema.json
5
+
6
+ database:
7
+ hostname: 'localhost'
8
+ port: 5432
9
+ username: 'postgres'
10
+ password: ${PGPASSWORD}
11
+ user_database: 'hello'
12
+ system_database: 'hello_systemdb'
13
+ connectionTimeoutMillis: 3000
14
+ user_dbclient: 'knex'
15
+ version: "1.0"
@@ -0,0 +1,8 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ testRegex: '((\\.|/)(test|spec))\\.ts?$',
6
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
7
+ modulePaths: ["./"],
8
+ };
@@ -0,0 +1,23 @@
1
+ // knexfile.ts
2
+
3
+ import { Knex } from 'knex';
4
+ import { parseConfigFile } from '@dbos-inc/dbos-sdk/dist/src/dbos-runtime/config'
5
+ import { DBOSConfig } from '@dbos-inc/dbos-sdk/dist/src/dbos-executor';
6
+
7
+ const [dbosConfig, ]: [DBOSConfig, unknown] = parseConfigFile();
8
+
9
+ const config: Knex.Config = {
10
+ client: 'pg',
11
+ connection: {
12
+ host: dbosConfig.poolConfig.host,
13
+ user: dbosConfig.poolConfig.user,
14
+ password: dbosConfig.poolConfig.password,
15
+ database: dbosConfig.poolConfig.database,
16
+ ssl: dbosConfig.poolConfig.ssl,
17
+ },
18
+ migrations: {
19
+ directory: './migrations'
20
+ }
21
+ };
22
+
23
+ export default config;
@@ -0,0 +1,12 @@
1
+ import { Knex } from "knex";
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ return knex.schema.createTable('dbos_hello', table => {
5
+ table.text('name').primary();
6
+ table.integer('greet_count').defaultTo(0);
7
+ });
8
+ }
9
+
10
+ export async function down(knex: Knex): Promise<void> {
11
+ return knex.schema.dropTable('dbos_hello');
12
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "dbos-hello",
3
+ "version": "0.0.1",
4
+ "scripts": {
5
+ "build": "tsc",
6
+ "test": "npx knex migrate:rollback && npx knex migrate:up && jest"
7
+ },
8
+ "devDependencies": {
9
+ "@types/jest": "^29.5.5",
10
+ "@types/supertest": "^2.0.14",
11
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
12
+ "jest": "^29.7.0",
13
+ "supertest": "^6.3.3",
14
+ "ts-jest": "^29.1.1",
15
+ "typescript": "^5.2.2"
16
+ },
17
+ "dependencies": {
18
+ "@dbos-inc/dbos-sdk": "../..",
19
+ "ts-node": "^10.9.1"
20
+ }
21
+ }
@@ -0,0 +1,38 @@
1
+ import { TestingRuntime, createTestingRuntime } from "@dbos-inc/dbos-sdk";
2
+ import { Hello, dbos_hello } from "./operations";
3
+ import request from "supertest";
4
+
5
+ describe("operations-test", () => {
6
+ let testRuntime: TestingRuntime;
7
+
8
+ beforeAll(async () => {
9
+ testRuntime = await createTestingRuntime([Hello]);
10
+ });
11
+
12
+ afterAll(async () => {
13
+ await testRuntime.destroy();
14
+ });
15
+
16
+ /**
17
+ * Test the transaction.
18
+ */
19
+ test("test-transaction", async () => {
20
+ const res = await testRuntime.invoke(Hello).helloTransaction("dbos");
21
+ expect(res).toMatch("Hello, dbos! You have been greeted");
22
+
23
+ // Check the greet count.
24
+ const rows = await testRuntime.queryUserDB<dbos_hello>("SELECT * FROM dbos_hello WHERE name=$1", "dbos");
25
+ expect(rows[0].greet_count).toBe(1);
26
+ });
27
+
28
+ /**
29
+ * Test the HTTP endpoint.
30
+ */
31
+ test("test-endpoint", async () => {
32
+ const res = await request(testRuntime.getHandlersCallback()).get(
33
+ "/greeting/dbos"
34
+ );
35
+ expect(res.statusCode).toBe(200);
36
+ expect(res.text).toMatch("Hello, dbos! You have been greeted");
37
+ });
38
+ });
@@ -0,0 +1,21 @@
1
+ import { TransactionContext, Transaction, GetApi, ArgSource, ArgSources } from '@dbos-inc/dbos-sdk'
2
+ import { Knex } from 'knex';
3
+
4
+ // The schema of the database table used in this example.
5
+ export interface dbos_hello {
6
+ name: string;
7
+ greet_count: number;
8
+ }
9
+
10
+ export class Hello {
11
+
12
+ @GetApi('/greeting/:user') // Serve this function from HTTP GET requests to the /greeting endpoint with 'user' as a path parameter
13
+ @Transaction() // Run this function as a database transaction
14
+ static async helloTransaction(ctxt: TransactionContext<Knex>, @ArgSource(ArgSources.URL) user: string) {
15
+ // Retrieve and increment the number of times this user has been greeted.
16
+ const query = "INSERT INTO dbos_hello (name, greet_count) VALUES (?, 1) ON CONFLICT (name) DO UPDATE SET greet_count = dbos_hello.greet_count + 1 RETURNING greet_count;"
17
+ const { rows } = await ctxt.client.raw(query, [user]) as { rows: dbos_hello[] };
18
+ const greet_count = rows[0].greet_count;
19
+ return `Hello, ${user}! You have been greeted ${greet_count} times.\n`;
20
+ }
21
+ }