@nmakarov/cli-toolkit 0.25.0 → 0.29.0

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.
package/dist/tasks.js CHANGED
@@ -183,7 +183,7 @@ function defineTasksTable(t, db, tableNameForIndex) {
183
183
  t.timestamp("past_due").defaultTo(null);
184
184
  t.text("name").notNullable();
185
185
  t.text("opid");
186
- t.json("params");
186
+ t.jsonb("params");
187
187
  t.text("service_group");
188
188
  t.integer("instance_number");
189
189
  t.text("service_name");
@@ -192,7 +192,7 @@ function defineTasksTable(t, db, tableNameForIndex) {
192
192
  t.timestamp("status_changed_at").defaultTo(null);
193
193
  t.text("progress");
194
194
  t.boolean("success");
195
- t.json("results");
195
+ t.jsonb("results");
196
196
  t.index(["service_group", "status", "priority", "created_at"], `${tableNameForIndex}_claim_idx`);
197
197
  t.index(["service_group", "name"], `${tableNameForIndex}_group_name_idx`);
198
198
  }
@@ -207,11 +207,29 @@ function taskHistoryInsertFromQueueRow(row, overrides) {
207
207
  async function ensureTaskTables(context, options = {}) {
208
208
  const queueName = options.queueName ?? "tasks";
209
209
  const recreate = options.recreate ?? false;
210
+ const dryRun = options.dryRun ?? false;
210
211
  const db = getDb(context);
212
+ const log = context.logger ?? console;
211
213
  const { tasksTable, historyTable, registryTable } = queueToTableNames(queueName);
212
214
  const needsTasks = recreate ? true : !await db.tableExists(tasksTable);
213
215
  const needsHistory = recreate ? true : !await db.tableExists(historyTable);
214
216
  const needsRegistry = recreate ? true : !await db.tableExists(registryTable);
217
+ if (dryRun) {
218
+ const plan = [];
219
+ if (recreate) {
220
+ plan.push(`DROP TABLE IF EXISTS ${historyTable}, ${tasksTable}, ${registryTable}`);
221
+ }
222
+ if (needsTasks) plan.push(`CREATE TABLE ${tasksTable} (tasks queue)`);
223
+ if (needsHistory) plan.push(`CREATE TABLE ${historyTable} (history mirror)`);
224
+ if (needsRegistry) plan.push(`CREATE TABLE ${registryTable} (services registry)`);
225
+ if (plan.length === 0) {
226
+ log.info?.(`[tasks-schema] dryRun \u2014 queue "${queueName}" already up to date; no DDL`);
227
+ } else {
228
+ log.info?.(`[tasks-schema] dryRun \u2014 would run ${plan.length} statement(s) for queue "${queueName}":`);
229
+ for (const s of plan) log.info?.(` - ${s}`);
230
+ }
231
+ return;
232
+ }
215
233
  if (recreate) {
216
234
  await db.schema.dropTableIfExists(historyTable);
217
235
  await db.schema.dropTableIfExists(tasksTable);
@@ -2705,8 +2723,7 @@ function forwardChildLogToParent(context, prefix, message) {
2705
2723
  }
2706
2724
  function buildNodeArgs(scriptPath, cliArgs) {
2707
2725
  const inheritedExecArgs = Array.isArray(process.execArgv) ? [...process.execArgv] : [];
2708
- const hasTsRuntimeInParent = inheritedExecArgs.some((arg) => /tsx|ts-node/i.test(arg));
2709
- return hasTsRuntimeInParent ? [...inheritedExecArgs, scriptPath, ...cliArgs] : ["--import", "tsx", scriptPath, ...cliArgs];
2726
+ return [...inheritedExecArgs, scriptPath, ...cliArgs];
2710
2727
  }
2711
2728
  function resolveTasksTableName(context) {
2712
2729
  return context.tasksQueueName || context.params?.get?.("table") || "tasks";
@@ -2946,9 +2963,8 @@ async function executeClaimedTask(context, tasksTable, historyTable, row, regist
2946
2963
  const dbName = String(context?.params?.get?.("dbName") || "local");
2947
2964
  const tableName = String(context?.params?.get?.("table") || "tasks");
2948
2965
  const fallbackRecoverCommand = [
2949
- "npx",
2950
- "tsx",
2951
- "examples/tasks/recover-task.ts",
2966
+ "node",
2967
+ "examples/tasks/recover-task.js",
2952
2968
  `--dbName='${dbName.replace(/'/g, `'\\''`)}'`,
2953
2969
  `--table='${tableName.replace(/'/g, `'\\''`)}'`,
2954
2970
  `--id='${String(row.id).replace(/'/g, `'\\''`)}'`
@@ -3014,6 +3030,8 @@ async function claimNextRunnableTask(context, tasksTable, serviceGroup, registry
3014
3030
  const db = getDb3(context);
3015
3031
  let query = db(tasksTable).where({ status: "idle" }).where(function() {
3016
3032
  this.whereNull("service_group").orWhere({ service_group: serviceGroup });
3033
+ }).where(function() {
3034
+ this.whereNull("next_run_at").orWhere("next_run_at", "<=", db.fn.now());
3017
3035
  }).orderByRaw("CASE WHEN past_due IS NULL THEN 1 ELSE 0 END ASC").orderBy([{ column: "priority", order: "asc" }]).orderByRaw("CASE WHEN completed_at IS NULL THEN 0 ELSE 1 END ASC").orderBy([{ column: "completed_at", order: "asc" }, { column: "created_at", order: "asc" }]).limit(scanLimit);
3018
3036
  if (taskNames && taskNames.length > 0) {
3019
3037
  query = query.whereIn("name", taskNames);