@dbos-inc/dbos-sdk 0.7.18-preview

Sign up to get free protection for your applications and to get access to all the features.
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
+ }