gencow 0.1.123 → 0.1.124

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/bin/gencow.mjs CHANGED
@@ -4587,6 +4587,7 @@ process.exit(0);
4587
4587
 
4588
4588
  const res = await platformFetch(creds, `/platform/apps/${appName}/deploy`, {
4589
4589
  method: "POST", body: form,
4590
+ headers: { "X-Deploy-Local-Dir": process.cwd() },
4590
4591
  });
4591
4592
  const data = await res.json();
4592
4593
  const elapsed = ((Date.now() - startMs) / 1000).toFixed(1);
package/core/index.js CHANGED
@@ -1595,8 +1595,9 @@ function getSchedulerInfo() {
1595
1595
  failedJobs: _failedJobs
1596
1596
  };
1597
1597
  }
1598
- function createScheduler() {
1598
+ function createScheduler(options) {
1599
1599
  const timers = /* @__PURE__ */ new Map();
1600
+ const isDurable = !!(options?.persistJob && options?.removeJob);
1600
1601
  const cronJobs2 = /* @__PURE__ */ new Map();
1601
1602
  const actions = /* @__PURE__ */ new Map();
1602
1603
  let jobCounter = 0;
@@ -1624,54 +1625,89 @@ function createScheduler() {
1624
1625
  await handler(args);
1625
1626
  console.log(`[scheduler] Action "${action}" completed`);
1626
1627
  }
1628
+ function scheduleInMemory(id, ms, action, args, scheduleOpts, jobEntry) {
1629
+ const timer = setTimeout(async () => {
1630
+ jobEntry.status = "running";
1631
+ try {
1632
+ await executeAction(action, args);
1633
+ jobEntry.status = "completed";
1634
+ } catch (error) {
1635
+ const err = error instanceof Error ? error : new Error(String(error));
1636
+ jobEntry.status = "failed";
1637
+ console.error(`[scheduler] Action "${action}" failed (job: ${id}):`, err.message);
1638
+ recordFailure(id, action, args, err);
1639
+ if (scheduleOpts?.onError) {
1640
+ try {
1641
+ await executeAction(scheduleOpts.onError, {
1642
+ failedAction: action,
1643
+ failedJobId: id,
1644
+ error: err.message,
1645
+ originalArgs: args
1646
+ });
1647
+ console.log(`[scheduler] onError handler "${scheduleOpts.onError}" completed for "${action}"`);
1648
+ } catch (onErrorErr) {
1649
+ console.error(`[scheduler] onError handler "${scheduleOpts.onError}" also failed:`, onErrorErr);
1650
+ }
1651
+ }
1652
+ } finally {
1653
+ timers.delete(id);
1654
+ setTimeout(() => {
1655
+ const idx = _pendingJobs.findIndex((j) => j.id === id);
1656
+ if (idx >= 0) _pendingJobs.splice(idx, 1);
1657
+ }, 6e4);
1658
+ }
1659
+ }, ms);
1660
+ timers.set(id, timer);
1661
+ console.log(
1662
+ `[scheduler] Scheduled "${action}" to run after ${ms}ms (id: ${id})${scheduleOpts?.onError ? ` [onError: ${scheduleOpts.onError}]` : ""}`
1663
+ );
1664
+ }
1627
1665
  return {
1628
- runAfter(ms, action, args, options) {
1666
+ runAfter(ms, action, args, scheduleOpts) {
1629
1667
  const id = generateId();
1630
1668
  const jobEntry = { id, action, scheduledAt: (/* @__PURE__ */ new Date()).toISOString(), status: "pending" };
1631
1669
  _pendingJobs.push(jobEntry);
1632
- const timer = setTimeout(async () => {
1633
- jobEntry.status = "running";
1634
- try {
1635
- await executeAction(action, args);
1636
- jobEntry.status = "completed";
1637
- } catch (error) {
1638
- const err = error instanceof Error ? error : new Error(String(error));
1639
- jobEntry.status = "failed";
1640
- console.error(`[scheduler] Action "${action}" failed (job: ${id}):`, err.message);
1641
- recordFailure(id, action, args, err);
1642
- if (options?.onError) {
1643
- try {
1644
- await executeAction(options.onError, {
1645
- failedAction: action,
1646
- failedJobId: id,
1647
- error: err.message,
1648
- originalArgs: args
1649
- });
1650
- console.log(`[scheduler] onError handler "${options.onError}" completed for "${action}"`);
1651
- } catch (onErrorErr) {
1652
- console.error(`[scheduler] onError handler "${options.onError}" also failed:`, onErrorErr);
1653
- }
1654
- }
1655
- } finally {
1656
- timers.delete(id);
1657
- setTimeout(() => {
1658
- const idx = _pendingJobs.findIndex((j) => j.id === id);
1659
- if (idx >= 0) _pendingJobs.splice(idx, 1);
1660
- }, 6e4);
1661
- }
1662
- }, ms);
1663
- timers.set(id, timer);
1664
- console.log(
1665
- `[scheduler] Scheduled "${action}" to run after ${ms}ms (id: ${id})${options?.onError ? ` [onError: ${options.onError}]` : ""}`
1666
- );
1670
+ if (isDurable) {
1671
+ const runAt = new Date(Date.now() + ms);
1672
+ options.persistJob({
1673
+ id,
1674
+ action,
1675
+ args: args ?? {},
1676
+ runAt,
1677
+ onErrorAction: scheduleOpts?.onError
1678
+ }).then(() => {
1679
+ console.log(
1680
+ `[scheduler] Persisted "${action}" to run at ${runAt.toISOString()} (id: ${id}, durable)${scheduleOpts?.onError ? ` [onError: ${scheduleOpts.onError}]` : ""}`
1681
+ );
1682
+ }).catch((err) => {
1683
+ console.error(`[scheduler] Failed to persist job ${id}:`, err instanceof Error ? err.message : err);
1684
+ scheduleInMemory(id, ms, action, args, scheduleOpts, jobEntry);
1685
+ });
1686
+ return id;
1687
+ }
1688
+ scheduleInMemory(id, ms, action, args, scheduleOpts, jobEntry);
1667
1689
  return id;
1668
1690
  },
1669
- runAt(timestamp, action, args, options) {
1691
+ runAt(timestamp, action, args, options2) {
1670
1692
  const target = timestamp instanceof Date ? timestamp.getTime() : timestamp;
1671
1693
  const ms = Math.max(0, target - Date.now());
1672
- return this.runAfter(ms, action, args, options);
1694
+ return this.runAfter(ms, action, args, options2);
1673
1695
  },
1674
1696
  cancel(jobId) {
1697
+ if (isDurable) {
1698
+ const idx = _pendingJobs.findIndex((j) => j.id === jobId);
1699
+ if (idx >= 0) {
1700
+ _pendingJobs.splice(idx, 1);
1701
+ options.removeJob(jobId).catch((err) => {
1702
+ console.error(`[scheduler] Failed to remove persisted job ${jobId}:`, err instanceof Error ? err.message : err);
1703
+ });
1704
+ console.log(`[scheduler] Cancelled job ${jobId} (durable)`);
1705
+ return true;
1706
+ }
1707
+ options.removeJob(jobId).catch(() => {
1708
+ });
1709
+ return false;
1710
+ }
1675
1711
  const timer = timers.get(jobId);
1676
1712
  if (timer) {
1677
1713
  clearTimeout(timer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.123",
3
+ "version": "0.1.124",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {