pg-boss 12.34.0 → 12.35.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/README.md +1 -2
- package/dist/activity.d.ts +15 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +95 -0
- package/dist/attorney.d.ts.map +1 -1
- package/dist/attorney.js +1 -0
- package/dist/boss.d.ts.map +1 -1
- package/dist/boss.js +50 -13
- package/dist/claimTimer.d.ts.map +1 -1
- package/dist/claimTimer.js +19 -1
- package/dist/clock.d.ts +10 -7
- package/dist/clock.d.ts.map +1 -1
- package/dist/clock.js +67 -38
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -6
- package/dist/manager.d.ts +6 -5
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +186 -67
- package/dist/migrationStore.d.ts.map +1 -1
- package/dist/migrationStore.js +166 -3
- package/dist/navigator.d.ts.map +1 -1
- package/dist/navigator.js +4 -0
- package/dist/plans.d.ts +22 -13
- package/dist/plans.d.ts.map +1 -1
- package/dist/plans.js +786 -202
- package/dist/schema.json +196 -2
- package/dist/timekeeper.d.ts +2 -1
- package/dist/timekeeper.d.ts.map +1 -1
- package/dist/timekeeper.js +17 -8
- package/dist/types.d.ts +89 -88
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/schema.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_generated": "Generated by scripts/gen-manifest.ts — do not edit by hand. Run `npm run gen:manifest`.",
|
|
3
|
-
"version":
|
|
3
|
+
"version": 43,
|
|
4
4
|
"schemaToken": "{{schema}}",
|
|
5
5
|
"partitioned": {
|
|
6
6
|
"tables": [
|
|
@@ -296,6 +296,13 @@
|
|
|
296
296
|
"notNull": false,
|
|
297
297
|
"default": null
|
|
298
298
|
},
|
|
299
|
+
{
|
|
300
|
+
"table": "job_common",
|
|
301
|
+
"column": "source_output",
|
|
302
|
+
"type": "jsonb",
|
|
303
|
+
"notNull": false,
|
|
304
|
+
"default": null
|
|
305
|
+
},
|
|
299
306
|
{
|
|
300
307
|
"table": "job_common",
|
|
301
308
|
"column": "source_retry_count",
|
|
@@ -303,6 +310,13 @@
|
|
|
303
310
|
"notNull": false,
|
|
304
311
|
"default": null
|
|
305
312
|
},
|
|
313
|
+
{
|
|
314
|
+
"table": "job_common",
|
|
315
|
+
"column": "source_root_id",
|
|
316
|
+
"type": "uuid",
|
|
317
|
+
"notNull": false,
|
|
318
|
+
"default": null
|
|
319
|
+
},
|
|
306
320
|
{
|
|
307
321
|
"table": "job_common",
|
|
308
322
|
"column": "start_after",
|
|
@@ -555,6 +569,13 @@
|
|
|
555
569
|
"notNull": false,
|
|
556
570
|
"default": null
|
|
557
571
|
},
|
|
572
|
+
{
|
|
573
|
+
"table": "job",
|
|
574
|
+
"column": "source_output",
|
|
575
|
+
"type": "jsonb",
|
|
576
|
+
"notNull": false,
|
|
577
|
+
"default": null
|
|
578
|
+
},
|
|
558
579
|
{
|
|
559
580
|
"table": "job",
|
|
560
581
|
"column": "source_retry_count",
|
|
@@ -562,6 +583,13 @@
|
|
|
562
583
|
"notNull": false,
|
|
563
584
|
"default": null
|
|
564
585
|
},
|
|
586
|
+
{
|
|
587
|
+
"table": "job",
|
|
588
|
+
"column": "source_root_id",
|
|
589
|
+
"type": "uuid",
|
|
590
|
+
"notNull": false,
|
|
591
|
+
"default": null
|
|
592
|
+
},
|
|
565
593
|
{
|
|
566
594
|
"table": "job",
|
|
567
595
|
"column": "start_after",
|
|
@@ -597,6 +625,20 @@
|
|
|
597
625
|
"notNull": true,
|
|
598
626
|
"default": "now()"
|
|
599
627
|
},
|
|
628
|
+
{
|
|
629
|
+
"table": "queue_stats",
|
|
630
|
+
"column": "completed_delta",
|
|
631
|
+
"type": "integer",
|
|
632
|
+
"notNull": false,
|
|
633
|
+
"default": null
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"table": "queue_stats",
|
|
637
|
+
"column": "created_delta",
|
|
638
|
+
"type": "integer",
|
|
639
|
+
"notNull": false,
|
|
640
|
+
"default": null
|
|
641
|
+
},
|
|
600
642
|
{
|
|
601
643
|
"table": "queue_stats",
|
|
602
644
|
"column": "deferred_count",
|
|
@@ -604,6 +646,20 @@
|
|
|
604
646
|
"notNull": true,
|
|
605
647
|
"default": "0"
|
|
606
648
|
},
|
|
649
|
+
{
|
|
650
|
+
"table": "queue_stats",
|
|
651
|
+
"column": "delta_on",
|
|
652
|
+
"type": "timestamp with time zone",
|
|
653
|
+
"notNull": false,
|
|
654
|
+
"default": null
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
"table": "queue_stats",
|
|
658
|
+
"column": "delta_seconds",
|
|
659
|
+
"type": "integer",
|
|
660
|
+
"notNull": false,
|
|
661
|
+
"default": null
|
|
662
|
+
},
|
|
607
663
|
{
|
|
608
664
|
"table": "queue_stats",
|
|
609
665
|
"column": "failed_count",
|
|
@@ -611,6 +667,13 @@
|
|
|
611
667
|
"notNull": true,
|
|
612
668
|
"default": "0"
|
|
613
669
|
},
|
|
670
|
+
{
|
|
671
|
+
"table": "queue_stats",
|
|
672
|
+
"column": "failed_delta",
|
|
673
|
+
"type": "integer",
|
|
674
|
+
"notNull": false,
|
|
675
|
+
"default": null
|
|
676
|
+
},
|
|
614
677
|
{
|
|
615
678
|
"table": "queue_stats",
|
|
616
679
|
"column": "id",
|
|
@@ -653,6 +716,20 @@
|
|
|
653
716
|
"notNull": true,
|
|
654
717
|
"default": "0"
|
|
655
718
|
},
|
|
719
|
+
{
|
|
720
|
+
"table": "queue",
|
|
721
|
+
"column": "completed_delta",
|
|
722
|
+
"type": "integer",
|
|
723
|
+
"notNull": true,
|
|
724
|
+
"default": "0"
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
"table": "queue",
|
|
728
|
+
"column": "created_delta",
|
|
729
|
+
"type": "integer",
|
|
730
|
+
"notNull": true,
|
|
731
|
+
"default": "0"
|
|
732
|
+
},
|
|
656
733
|
{
|
|
657
734
|
"table": "queue",
|
|
658
735
|
"column": "created_on",
|
|
@@ -681,6 +758,20 @@
|
|
|
681
758
|
"notNull": true,
|
|
682
759
|
"default": null
|
|
683
760
|
},
|
|
761
|
+
{
|
|
762
|
+
"table": "queue",
|
|
763
|
+
"column": "delta_on",
|
|
764
|
+
"type": "timestamp with time zone",
|
|
765
|
+
"notNull": false,
|
|
766
|
+
"default": null
|
|
767
|
+
},
|
|
768
|
+
{
|
|
769
|
+
"table": "queue",
|
|
770
|
+
"column": "delta_seconds",
|
|
771
|
+
"type": "integer",
|
|
772
|
+
"notNull": false,
|
|
773
|
+
"default": null
|
|
774
|
+
},
|
|
684
775
|
{
|
|
685
776
|
"table": "queue",
|
|
686
777
|
"column": "expire_seconds",
|
|
@@ -695,6 +786,13 @@
|
|
|
695
786
|
"notNull": true,
|
|
696
787
|
"default": "0"
|
|
697
788
|
},
|
|
789
|
+
{
|
|
790
|
+
"table": "queue",
|
|
791
|
+
"column": "failed_delta",
|
|
792
|
+
"type": "integer",
|
|
793
|
+
"notNull": true,
|
|
794
|
+
"default": "0"
|
|
795
|
+
},
|
|
698
796
|
{
|
|
699
797
|
"table": "queue",
|
|
700
798
|
"column": "heartbeat_seconds",
|
|
@@ -1111,6 +1209,12 @@
|
|
|
1111
1209
|
"valid": true,
|
|
1112
1210
|
"def": "CREATE INDEX job_common_i11 ON {{schema}}.job_common USING btree (name, priority DESC, created_on, start_after) WHERE ((state < 'active'::{{schema}}.job_state) AND (NOT blocked))"
|
|
1113
1211
|
},
|
|
1212
|
+
{
|
|
1213
|
+
"name": "job_common_i12",
|
|
1214
|
+
"table": "job_common",
|
|
1215
|
+
"valid": true,
|
|
1216
|
+
"def": "CREATE INDEX job_common_i12 ON {{schema}}.job_common USING btree (source_root_id) WHERE (source_root_id IS NOT NULL)"
|
|
1217
|
+
},
|
|
1114
1218
|
{
|
|
1115
1219
|
"name": "job_common_i2",
|
|
1116
1220
|
"table": "job_common",
|
|
@@ -1175,7 +1279,7 @@
|
|
|
1175
1279
|
"functions": [
|
|
1176
1280
|
{
|
|
1177
1281
|
"name": "create_queue",
|
|
1178
|
-
"def": "CREATE OR REPLACE FUNCTION {{schema}}.create_queue(queue_name text, options jsonb)\n RETURNS void\n LANGUAGE plpgsql\nAS $function$\n DECLARE\n tablename varchar := CASE WHEN options->>'partition' = 'true'\n THEN 'j' || encode(sha224(queue_name::bytea), 'hex')\n ELSE 'job_common'\n END;\n queue_created_on timestamptz;\n BEGIN\n\n WITH q as (\n INSERT INTO {{schema}}.queue (\n name,\n policy,\n retry_limit,\n retry_delay,\n retry_backoff,\n retry_delay_max,\n expire_seconds,\n retention_seconds,\n deletion_seconds,\n warning_queued,\n dead_letter,\n partition,\n table_name,\n heartbeat_seconds,\n notify,\n created_on,\n updated_on\n )\n VALUES (\n queue_name,\n options->>'policy',\n COALESCE((options->>'retryLimit')::int, 2),\n COALESCE((options->>'retryDelay')::int, 0),\n COALESCE((options->>'retryBackoff')::bool, false),\n (options->>'retryDelayMax')::int,\n COALESCE((options->>'expireInSeconds')::int, 900),\n COALESCE((options->>'retentionSeconds')::int, 1209600),\n COALESCE((options->>'deleteAfterSeconds')::int, 604800),\n COALESCE((options->>'warningQueueSize')::int, 0),\n options->>'deadLetter',\n COALESCE((options->>'partition')::bool, false),\n tablename,\n (options->>'heartbeatSeconds')::int,\n COALESCE((options->>'notify')::bool, false),\n {{schema}}.job_now(),\n {{schema}}.job_now()\n )\n ON CONFLICT DO NOTHING\n RETURNING created_on\n )\n SELECT created_on into queue_created_on from q;\n\n IF queue_created_on IS NULL OR options->>'partition' IS DISTINCT FROM 'true' THEN\n RETURN;\n END IF;\n\n EXECUTE format('CREATE TABLE {{schema}}.%I (LIKE {{schema}}.job INCLUDING DEFAULTS)', tablename);\n\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD PRIMARY KEY (name, id)$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD CONSTRAINT q_fkey FOREIGN KEY (name) REFERENCES {{schema}}.queue (name) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD CONSTRAINT dlq_fkey FOREIGN KEY (dead_letter) REFERENCES {{schema}}.queue (name) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED$cmd$, tablename);\n\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i11 ON {{schema}}.job (name, priority DESC, created_on, start_after) WHERE state < 'active' AND NOT blocked$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i4 ON {{schema}}.job (name, singleton_on, COALESCE(singleton_key, '')) WHERE state <> 'cancelled' AND singleton_on IS NOT NULL$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i7 ON {{schema}}.job (name, group_id) WHERE state = 'active' AND group_id IS NOT NULL$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i9 ON {{schema}}.job (name, id) WHERE blocking AND state = 'completed'$cmd$, tablename);\n\n IF options->>'policy' = 'short' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i1 ON {{schema}}.job (name, COALESCE(singleton_key, '')) WHERE state = 'created' AND policy = 'short'$cmd$, tablename);\n ELSIF options->>'policy' = 'singleton' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i2 ON {{schema}}.job (name, COALESCE(singleton_key, '')) WHERE state = 'active' AND policy = 'singleton'$cmd$, tablename);\n ELSIF options->>'policy' = 'stately' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i3 ON {{schema}}.job (name, state, COALESCE(singleton_key, '')) WHERE state <= 'active' AND policy = 'stately'$cmd$, tablename);\n ELSIF options->>'policy' = 'exclusive' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i6 ON {{schema}}.job (name, COALESCE(singleton_key, '')) WHERE state <= 'active' AND policy = 'exclusive'$cmd$, tablename);\n ELSIF options->>'policy' = 'key_strict_fifo' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i8 ON {{schema}}.job (name, singleton_key) WHERE state IN ('active', 'retry', 'failed') AND policy = 'key_strict_fifo'$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i10 ON {{schema}}.job (name, singleton_key, state DESC, created_on, id) INCLUDE (start_after) WHERE state < 'active' AND NOT blocked AND policy = 'key_strict_fifo'$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD CONSTRAINT job_key_strict_fifo_singleton_key_check CHECK (NOT (policy = 'key_strict_fifo' AND singleton_key IS NULL))$cmd$, tablename);\n END IF;\n\n EXECUTE format('ALTER TABLE {{schema}}.%I ADD CONSTRAINT cjc CHECK (name=%L)', tablename, queue_name);\n EXECUTE format('ALTER TABLE {{schema}}.job ATTACH PARTITION {{schema}}.%I FOR VALUES IN (%L)', tablename, queue_name);\n END;\n $function$\n"
|
|
1282
|
+
"def": "CREATE OR REPLACE FUNCTION {{schema}}.create_queue(queue_name text, options jsonb)\n RETURNS void\n LANGUAGE plpgsql\nAS $function$\n DECLARE\n tablename varchar := CASE WHEN options->>'partition' = 'true'\n THEN 'j' || encode(sha224(queue_name::bytea), 'hex')\n ELSE 'job_common'\n END;\n queue_created_on timestamptz;\n BEGIN\n\n WITH q as (\n INSERT INTO {{schema}}.queue (\n name,\n policy,\n retry_limit,\n retry_delay,\n retry_backoff,\n retry_delay_max,\n expire_seconds,\n retention_seconds,\n deletion_seconds,\n warning_queued,\n dead_letter,\n partition,\n table_name,\n heartbeat_seconds,\n notify,\n created_on,\n updated_on\n )\n VALUES (\n queue_name,\n options->>'policy',\n COALESCE((options->>'retryLimit')::int, 2),\n COALESCE((options->>'retryDelay')::int, 0),\n COALESCE((options->>'retryBackoff')::bool, false),\n (options->>'retryDelayMax')::int,\n COALESCE((options->>'expireInSeconds')::int, 900),\n COALESCE((options->>'retentionSeconds')::int, 1209600),\n COALESCE((options->>'deleteAfterSeconds')::int, 604800),\n COALESCE((options->>'warningQueueSize')::int, 0),\n options->>'deadLetter',\n COALESCE((options->>'partition')::bool, false),\n tablename,\n (options->>'heartbeatSeconds')::int,\n COALESCE((options->>'notify')::bool, false),\n {{schema}}.job_now(),\n {{schema}}.job_now()\n )\n ON CONFLICT DO NOTHING\n RETURNING created_on\n )\n SELECT created_on into queue_created_on from q;\n\n IF queue_created_on IS NULL OR options->>'partition' IS DISTINCT FROM 'true' THEN\n RETURN;\n END IF;\n\n EXECUTE format('CREATE TABLE {{schema}}.%I (LIKE {{schema}}.job INCLUDING DEFAULTS)', tablename);\n\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD PRIMARY KEY (name, id)$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD CONSTRAINT q_fkey FOREIGN KEY (name) REFERENCES {{schema}}.queue (name) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD CONSTRAINT dlq_fkey FOREIGN KEY (dead_letter) REFERENCES {{schema}}.queue (name) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED$cmd$, tablename);\n\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i11 ON {{schema}}.job (name, priority DESC, created_on, start_after) WHERE state < 'active' AND NOT blocked$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i4 ON {{schema}}.job (name, singleton_on, COALESCE(singleton_key, '')) WHERE state <> 'cancelled' AND singleton_on IS NOT NULL$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i7 ON {{schema}}.job (name, group_id) WHERE state = 'active' AND group_id IS NOT NULL$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i9 ON {{schema}}.job (name, id) WHERE blocking AND state = 'completed'$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i12 ON {{schema}}.job (source_root_id) WHERE source_root_id IS NOT NULL$cmd$, tablename);\n\n IF options->>'policy' = 'short' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i1 ON {{schema}}.job (name, COALESCE(singleton_key, '')) WHERE state = 'created' AND policy = 'short'$cmd$, tablename);\n ELSIF options->>'policy' = 'singleton' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i2 ON {{schema}}.job (name, COALESCE(singleton_key, '')) WHERE state = 'active' AND policy = 'singleton'$cmd$, tablename);\n ELSIF options->>'policy' = 'stately' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i3 ON {{schema}}.job (name, state, COALESCE(singleton_key, '')) WHERE state <= 'active' AND policy = 'stately'$cmd$, tablename);\n ELSIF options->>'policy' = 'exclusive' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i6 ON {{schema}}.job (name, COALESCE(singleton_key, '')) WHERE state <= 'active' AND policy = 'exclusive'$cmd$, tablename);\n ELSIF options->>'policy' = 'key_strict_fifo' THEN\n EXECUTE {{schema}}.job_table_format($cmd$CREATE UNIQUE INDEX job_i8 ON {{schema}}.job (name, singleton_key) WHERE state IN ('active', 'retry', 'failed') AND policy = 'key_strict_fifo'$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$CREATE INDEX job_i10 ON {{schema}}.job (name, singleton_key, state DESC, created_on, id) INCLUDE (start_after) WHERE state < 'active' AND NOT blocked AND policy = 'key_strict_fifo'$cmd$, tablename);\n EXECUTE {{schema}}.job_table_format($cmd$ALTER TABLE {{schema}}.job ADD CONSTRAINT job_key_strict_fifo_singleton_key_check CHECK (NOT (policy = 'key_strict_fifo' AND singleton_key IS NULL))$cmd$, tablename);\n END IF;\n\n EXECUTE format('ALTER TABLE {{schema}}.%I ADD CONSTRAINT cjc CHECK (name=%L)', tablename, queue_name);\n EXECUTE format('ALTER TABLE {{schema}}.job ATTACH PARTITION {{schema}}.%I FOR VALUES IN (%L)', tablename, queue_name);\n END;\n $function$\n"
|
|
1179
1283
|
},
|
|
1180
1284
|
{
|
|
1181
1285
|
"name": "delete_queue",
|
|
@@ -1528,6 +1632,13 @@
|
|
|
1528
1632
|
"notNull": false,
|
|
1529
1633
|
"default": null
|
|
1530
1634
|
},
|
|
1635
|
+
{
|
|
1636
|
+
"table": "job",
|
|
1637
|
+
"column": "source_output",
|
|
1638
|
+
"type": "jsonb",
|
|
1639
|
+
"notNull": false,
|
|
1640
|
+
"default": null
|
|
1641
|
+
},
|
|
1531
1642
|
{
|
|
1532
1643
|
"table": "job",
|
|
1533
1644
|
"column": "source_retry_count",
|
|
@@ -1535,6 +1646,13 @@
|
|
|
1535
1646
|
"notNull": false,
|
|
1536
1647
|
"default": null
|
|
1537
1648
|
},
|
|
1649
|
+
{
|
|
1650
|
+
"table": "job",
|
|
1651
|
+
"column": "source_root_id",
|
|
1652
|
+
"type": "uuid",
|
|
1653
|
+
"notNull": false,
|
|
1654
|
+
"default": null
|
|
1655
|
+
},
|
|
1538
1656
|
{
|
|
1539
1657
|
"table": "job",
|
|
1540
1658
|
"column": "start_after",
|
|
@@ -1570,6 +1688,20 @@
|
|
|
1570
1688
|
"notNull": true,
|
|
1571
1689
|
"default": "now()"
|
|
1572
1690
|
},
|
|
1691
|
+
{
|
|
1692
|
+
"table": "queue_stats",
|
|
1693
|
+
"column": "completed_delta",
|
|
1694
|
+
"type": "integer",
|
|
1695
|
+
"notNull": false,
|
|
1696
|
+
"default": null
|
|
1697
|
+
},
|
|
1698
|
+
{
|
|
1699
|
+
"table": "queue_stats",
|
|
1700
|
+
"column": "created_delta",
|
|
1701
|
+
"type": "integer",
|
|
1702
|
+
"notNull": false,
|
|
1703
|
+
"default": null
|
|
1704
|
+
},
|
|
1573
1705
|
{
|
|
1574
1706
|
"table": "queue_stats",
|
|
1575
1707
|
"column": "deferred_count",
|
|
@@ -1577,6 +1709,20 @@
|
|
|
1577
1709
|
"notNull": true,
|
|
1578
1710
|
"default": "0"
|
|
1579
1711
|
},
|
|
1712
|
+
{
|
|
1713
|
+
"table": "queue_stats",
|
|
1714
|
+
"column": "delta_on",
|
|
1715
|
+
"type": "timestamp with time zone",
|
|
1716
|
+
"notNull": false,
|
|
1717
|
+
"default": null
|
|
1718
|
+
},
|
|
1719
|
+
{
|
|
1720
|
+
"table": "queue_stats",
|
|
1721
|
+
"column": "delta_seconds",
|
|
1722
|
+
"type": "integer",
|
|
1723
|
+
"notNull": false,
|
|
1724
|
+
"default": null
|
|
1725
|
+
},
|
|
1580
1726
|
{
|
|
1581
1727
|
"table": "queue_stats",
|
|
1582
1728
|
"column": "failed_count",
|
|
@@ -1584,6 +1730,13 @@
|
|
|
1584
1730
|
"notNull": true,
|
|
1585
1731
|
"default": "0"
|
|
1586
1732
|
},
|
|
1733
|
+
{
|
|
1734
|
+
"table": "queue_stats",
|
|
1735
|
+
"column": "failed_delta",
|
|
1736
|
+
"type": "integer",
|
|
1737
|
+
"notNull": false,
|
|
1738
|
+
"default": null
|
|
1739
|
+
},
|
|
1587
1740
|
{
|
|
1588
1741
|
"table": "queue_stats",
|
|
1589
1742
|
"column": "id",
|
|
@@ -1626,6 +1779,20 @@
|
|
|
1626
1779
|
"notNull": true,
|
|
1627
1780
|
"default": "0"
|
|
1628
1781
|
},
|
|
1782
|
+
{
|
|
1783
|
+
"table": "queue",
|
|
1784
|
+
"column": "completed_delta",
|
|
1785
|
+
"type": "integer",
|
|
1786
|
+
"notNull": true,
|
|
1787
|
+
"default": "0"
|
|
1788
|
+
},
|
|
1789
|
+
{
|
|
1790
|
+
"table": "queue",
|
|
1791
|
+
"column": "created_delta",
|
|
1792
|
+
"type": "integer",
|
|
1793
|
+
"notNull": true,
|
|
1794
|
+
"default": "0"
|
|
1795
|
+
},
|
|
1629
1796
|
{
|
|
1630
1797
|
"table": "queue",
|
|
1631
1798
|
"column": "created_on",
|
|
@@ -1654,6 +1821,20 @@
|
|
|
1654
1821
|
"notNull": true,
|
|
1655
1822
|
"default": null
|
|
1656
1823
|
},
|
|
1824
|
+
{
|
|
1825
|
+
"table": "queue",
|
|
1826
|
+
"column": "delta_on",
|
|
1827
|
+
"type": "timestamp with time zone",
|
|
1828
|
+
"notNull": false,
|
|
1829
|
+
"default": null
|
|
1830
|
+
},
|
|
1831
|
+
{
|
|
1832
|
+
"table": "queue",
|
|
1833
|
+
"column": "delta_seconds",
|
|
1834
|
+
"type": "integer",
|
|
1835
|
+
"notNull": false,
|
|
1836
|
+
"default": null
|
|
1837
|
+
},
|
|
1657
1838
|
{
|
|
1658
1839
|
"table": "queue",
|
|
1659
1840
|
"column": "expire_seconds",
|
|
@@ -1668,6 +1849,13 @@
|
|
|
1668
1849
|
"notNull": true,
|
|
1669
1850
|
"default": "0"
|
|
1670
1851
|
},
|
|
1852
|
+
{
|
|
1853
|
+
"table": "queue",
|
|
1854
|
+
"column": "failed_delta",
|
|
1855
|
+
"type": "integer",
|
|
1856
|
+
"notNull": true,
|
|
1857
|
+
"default": "0"
|
|
1858
|
+
},
|
|
1671
1859
|
{
|
|
1672
1860
|
"table": "queue",
|
|
1673
1861
|
"column": "heartbeat_seconds",
|
|
@@ -2086,6 +2274,12 @@
|
|
|
2086
2274
|
"valid": true,
|
|
2087
2275
|
"def": "CREATE INDEX job_i11 ON {{schema}}.job USING btree (name, priority DESC, created_on, start_after) WHERE ((state < 'active'::{{schema}}.job_state) AND (NOT blocked))"
|
|
2088
2276
|
},
|
|
2277
|
+
{
|
|
2278
|
+
"name": "job_i12",
|
|
2279
|
+
"table": "job",
|
|
2280
|
+
"valid": true,
|
|
2281
|
+
"def": "CREATE INDEX job_i12 ON {{schema}}.job USING btree (source_root_id) WHERE (source_root_id IS NOT NULL)"
|
|
2282
|
+
},
|
|
2089
2283
|
{
|
|
2090
2284
|
"name": "job_i2",
|
|
2091
2285
|
"table": "job",
|
package/dist/timekeeper.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ declare class Timekeeper extends EventEmitter implements types.EventsMixin {
|
|
|
13
13
|
private stopped;
|
|
14
14
|
private cronMonitorTimer;
|
|
15
15
|
private skewMonitorTimer;
|
|
16
|
-
private
|
|
16
|
+
private _timekeeping;
|
|
17
17
|
private _checkingSkew;
|
|
18
18
|
private warnedSchedules;
|
|
19
19
|
clockSkew: number;
|
|
@@ -24,6 +24,7 @@ declare class Timekeeper extends EventEmitter implements types.EventsMixin {
|
|
|
24
24
|
};
|
|
25
25
|
constructor(db: types.IDatabase, manager: Manager, config: types.ResolvedConstructorOptions);
|
|
26
26
|
get checkingSkew(): boolean;
|
|
27
|
+
get timekeeping(): boolean;
|
|
27
28
|
private get databaseTime();
|
|
28
29
|
private get warningContext();
|
|
29
30
|
start(): Promise<void>;
|
package/dist/timekeeper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timekeeper.d.ts","sourceRoot":"","sources":["../src/timekeeper.ts"],"names":[],"mappings":"AAEA,OAAO,YAAY,MAAM,aAAa,CAAA;AAItC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAKvC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAGnC,eAAO,MAAM,MAAM;;CAElB,CAAA;AAwBD,kGAAkG;AAClG,eAAO,MAAM,iBAAiB,OAAO,CAAA;AA8MrC,cAAM,UAAW,SAAQ,YAAa,YAAW,KAAK,CAAC,WAAW;IAChE,EAAE,EAAE,KAAK,CAAC,SAAS,CAAA;IACnB,MAAM,EAAE,KAAK,CAAC,0BAA0B,CAAA;IACxC,OAAO,EAAE,OAAO,CAAA;IAEhB,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"timekeeper.d.ts","sourceRoot":"","sources":["../src/timekeeper.ts"],"names":[],"mappings":"AAEA,OAAO,YAAY,MAAM,aAAa,CAAA;AAItC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAKvC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAGnC,eAAO,MAAM,MAAM;;CAElB,CAAA;AAwBD,kGAAkG;AAClG,eAAO,MAAM,iBAAiB,OAAO,CAAA;AA8MrC,cAAM,UAAW,SAAQ,YAAa,YAAW,KAAK,CAAC,WAAW;IAChE,EAAE,EAAE,KAAK,CAAC,SAAS,CAAA;IACnB,MAAM,EAAE,KAAK,CAAC,0BAA0B,CAAA;IACxC,OAAO,EAAE,OAAO,CAAA;IAEhB,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAQ;IAS7B,OAAO,CAAC,eAAe,CAAoB;IAE3C,SAAS,SAAI;IACb,MAAM;;;;MAAS;gBAEF,EAAE,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,0BAA0B;IAQ5F,IAAI,YAAY,IAAK,OAAO,CAE3B;IAED,IAAI,WAAW,IAAK,OAAO,CAE1B;IAMD,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,cAAc,GASzB;IAEK,KAAK;IA4BL,IAAI;IAmCV,OAAO,CAAC,mBAAmB;IAUrB,cAAc;IA8Cd,MAAM;IAuDZ;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,eAAe;IAQvB;;;;;OAKG;IACG,IAAI,CAAE,WAAW,GAAE,OAAc;IAoIvC,YAAY,CAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,KAAK,CAAC,YAAwC;IAIlG;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,OAAO,CAAC,gBAAgB;IAgBxB;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAgB9B;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,iBAAiB;YAQX,QAAQ;YAsDR,aAAa;IAerB,YAAY,CAAE,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAiBrE,WAAW,CAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAK,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;IAe1E;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,CAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,KAAK,CAAC,sBAA2B,GAAG,IAAI,EAAE;IA0C5E,QAAQ,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,KAAK,CAAC,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6CzG,UAAU,CAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC;CAIzD;AAED,eAAe,UAAU,CAAA"}
|
package/dist/timekeeper.js
CHANGED
|
@@ -197,13 +197,13 @@ class Timekeeper extends EventEmitter {
|
|
|
197
197
|
stopped = true;
|
|
198
198
|
cronMonitorTimer;
|
|
199
199
|
skewMonitorTimer;
|
|
200
|
-
|
|
200
|
+
_timekeeping;
|
|
201
201
|
_checkingSkew = false;
|
|
202
202
|
// Rows already warned about, keyed on (name, key, cron, timezone). Unlike every other warning
|
|
203
203
|
// type, an unusable schedule never heals on its own: clock skew converges, a backlog drains, a
|
|
204
204
|
// slow query is a one-off, but a bad row sits there until a human edits it. Warning every pass
|
|
205
|
-
// would persist a row every cronMonitorIntervalSeconds
|
|
206
|
-
// default
|
|
205
|
+
// would persist a row every cronMonitorIntervalSeconds for as long as it stayed broken, a year's
|
|
206
|
+
// worth under the default warningRetentionDays from a single typo. Rebuilt each pass from
|
|
207
207
|
// the rows still broken, so a fixed or deleted schedule drops out and would warn again if it
|
|
208
208
|
// came back.
|
|
209
209
|
warnedSchedules = new Set();
|
|
@@ -218,6 +218,9 @@ class Timekeeper extends EventEmitter {
|
|
|
218
218
|
get checkingSkew() {
|
|
219
219
|
return this._checkingSkew;
|
|
220
220
|
}
|
|
221
|
+
get timekeeping() {
|
|
222
|
+
return !!this._timekeeping;
|
|
223
|
+
}
|
|
221
224
|
// The instance's reading of the database clock. previewSchedule() promises the reference point the
|
|
222
225
|
// cron pass evaluates against, so both read it here rather than each repeating the arithmetic.
|
|
223
226
|
// Zero skew until cacheClockSkew() has run, which start() only reaches when the instance was
|
|
@@ -271,7 +274,7 @@ class Timekeeper extends EventEmitter {
|
|
|
271
274
|
this.cronMonitorTimer.stop();
|
|
272
275
|
this.cronMonitorTimer = null;
|
|
273
276
|
}
|
|
274
|
-
while (this.
|
|
277
|
+
while (this._timekeeping || this._checkingSkew) {
|
|
275
278
|
await delay(10);
|
|
276
279
|
}
|
|
277
280
|
}
|
|
@@ -330,13 +333,19 @@ class Timekeeper extends EventEmitter {
|
|
|
330
333
|
}
|
|
331
334
|
}
|
|
332
335
|
async onCron() {
|
|
336
|
+
// Outside the try: the pass that is running owns the flag, and finally runs for every path
|
|
337
|
+
// through it, so an attempt that skips inside would clear the flag that pass is holding and let
|
|
338
|
+
// stop() return while it is still going. Same shape as Bam.#onPoll and cacheClockSkew above.
|
|
339
|
+
if (this.stopped || this._timekeeping)
|
|
340
|
+
return;
|
|
341
|
+
this._timekeeping = true;
|
|
333
342
|
try {
|
|
334
|
-
if (this.stopped || this.timekeeping)
|
|
335
|
-
return;
|
|
336
343
|
if (this.config.__test__force_cron_monitoring_error) {
|
|
337
344
|
throw new Error(this.config.__test__force_cron_monitoring_error);
|
|
338
345
|
}
|
|
339
|
-
this.
|
|
346
|
+
if (this.config.__test__delay_cron_ms) {
|
|
347
|
+
await delay(this.config.__test__delay_cron_ms);
|
|
348
|
+
}
|
|
340
349
|
const sql = plans.trySetCronTime(this.config.schema, this.config.cronMonitorIntervalSeconds);
|
|
341
350
|
if (!this.stopped) {
|
|
342
351
|
const { rows } = await this.db.executeSql(sql);
|
|
@@ -370,7 +379,7 @@ class Timekeeper extends EventEmitter {
|
|
|
370
379
|
this.emit(this.events.error, err);
|
|
371
380
|
}
|
|
372
381
|
finally {
|
|
373
|
-
this.
|
|
382
|
+
this._timekeeping = false;
|
|
374
383
|
}
|
|
375
384
|
}
|
|
376
385
|
/**
|