stampeded 0.4.0-x86_64-linux-gnu → 0.4.1-x86_64-linux-gnu

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cad7f788cd761495c62f13f696e9a8b6a278fe20cddaf2973deed5fc58e1fb1f
4
- data.tar.gz: 28788406522070a1ed14f54d8b855e26c7c3c0501c4b69bf6c4466d66f575807
3
+ metadata.gz: 4485b1e18988e4c2c276bd0a870f85269a5b4e52474f30fced2f96f3b2aae07f
4
+ data.tar.gz: b04edfe17a6776c9a056b8ea0ab649a20aca8ebc8d136e391c487d9d8ce1840b
5
5
  SHA512:
6
- metadata.gz: 47083a221b84efec03e9693cd4cc543307c9c59f35aad9772a8d43b8de48c99fb31b0a770e5ee178ba693c2505b1afba9f0a30a08018528fb51a2d0f46ee9d1e
7
- data.tar.gz: bb24cac65641ca47c82780535a3325bfab125306a7d14a9ed0536d0bcabbbe77c93c76aa97335fea0820a67a8be71ffc35bd971776d57034fcdd7035432e4ede
6
+ metadata.gz: 017f98fb4a6cc157f9727385b384efa94c60028644efb4b650893b2083ed15581b50a2ce6d903bff6ce83dc77f6eec86258b813a880ba6c9fb6557229d42ea70
7
+ data.tar.gz: 2c42fb9d96bd810a97cb2f5a7e7b374e7b1761751b813fc43cb0562cc050d679d78be2b7cb242fa1400aeb7d83d14ac6a85bd357f4c3243d786f88d8c0ecf0d3
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "digest"
4
+
3
5
  module Stampeded
4
6
  module Schema
5
- FILES = %w[schema.sql].freeze
7
+ # Where the daemon's sqlx migrator records what it applied.
8
+ TABLE = "stampeded_migrations"
6
9
 
7
10
  module_function
8
11
 
@@ -15,15 +18,40 @@ module Stampeded
15
18
  raise(Error, "cannot find schema/*.sql (looked in #{candidates.join(", ")})")
16
19
  end
17
20
 
18
- def sql
19
- FILES.map { |f| File.read(File.join(root, f)) }.join("\n")
21
+ # [version, description, sql] per migration, in order: sqlx's names.
22
+ def migrations
23
+ Dir[File.join(root, "*.sql")].sort.map do |path|
24
+ version, name = File.basename(path, ".sql").split("_", 2)
25
+ [Integer(version, 10), name.tr("_", " "), File.read(path)]
26
+ end
20
27
  end
21
28
 
29
+ def sql = migrations.map(&:last).join("\n")
30
+
31
+ # A fresh install, recorded as sqlx records it, so the daemon's
32
+ # --migrate finds nothing to apply.
22
33
  def install!(conn = nil)
23
34
  run = lambda do |c|
24
35
  c.exec("BEGIN")
25
36
  begin
26
- c.exec(sql)
37
+ c.exec(<<~SQL)
38
+ CREATE TABLE #{TABLE} (
39
+ version BIGINT PRIMARY KEY,
40
+ description TEXT NOT NULL,
41
+ installed_on TIMESTAMPTZ NOT NULL DEFAULT now(),
42
+ success BOOLEAN NOT NULL,
43
+ checksum BYTEA NOT NULL,
44
+ execution_time BIGINT NOT NULL
45
+ )
46
+ SQL
47
+ migrations.each do |version, description, sql|
48
+ c.exec(sql)
49
+ c.exec_params(
50
+ "INSERT INTO #{TABLE} (version, description, success, checksum, execution_time) " \
51
+ "VALUES ($1, $2, true, decode($3, 'hex'), 0)",
52
+ [version, description, Digest::SHA384.hexdigest(sql)]
53
+ )
54
+ end
27
55
  c.exec("COMMIT")
28
56
  rescue StandardError
29
57
  c.exec("ROLLBACK")
@@ -40,7 +68,7 @@ module Stampeded
40
68
  DROP TABLE IF EXISTS stampeded_cron_occurrences, stampeded_schedules,
41
69
  stampeded_queue_policies, stampeded_queue_counts,
42
70
  stampeded_jobs, stampeded_workers,
43
- stampeded_schema CASCADE;
71
+ stampeded_schema, stampeded_migrations CASCADE;
44
72
  DO $$
45
73
  DECLARE r record;
46
74
  BEGIN
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stampeded
4
- VERSION = "0.4.0" # x-release-please-version
4
+ VERSION = "0.4.1" # x-release-please-version
5
5
  end
Binary file
data/libexec/stampeded CHANGED
Binary file
@@ -65,20 +65,15 @@ CREATE TABLE stampeded_jobs (
65
65
  dedup_period text CHECK (dedup_period IN
66
66
  ('minute','hour','day','week','month')),
67
67
 
68
- -- Scope, period and bucket: buckets of two periods start together (an
69
- -- hour and its day at midnight UTC), so the period keeps them apart.
70
- -- Joined as bytea with a raw zero byte: no `text` value can ever decode
71
- -- to one (chr(0) itself is refused), so a crafted dedup_scope can never
72
- -- forge the separator and so never forge another row's key.
73
68
  dedup_key bytea GENERATED ALWAYS AS (
74
- sha256(
75
- dedup_scope::bytea || '\x00'::bytea || coalesce(
76
- dedup_period::bytea || '\x00'::bytea || extract(
69
+ sha256((
70
+ dedup_scope || coalesce(
71
+ ':' || extract(
77
72
  epoch FROM (date_trunc(dedup_period, inserted_at, 'UTC') - to_timestamp(0))
78
- )::bigint::text::bytea,
79
- ''::bytea
73
+ )::bigint::text,
74
+ ''
80
75
  )
81
- )
76
+ )::bytea)
82
77
  ) STORED,
83
78
 
84
79
  failure_kind text,
@@ -1052,13 +1047,3 @@ CREATE TABLE stampeded_queue_policies (
1052
1047
  created_at timestamptz NOT NULL DEFAULT now(),
1053
1048
  updated_at timestamptz NOT NULL DEFAULT now()
1054
1049
  );
1055
-
1056
- -- Which schema this database holds, one row: `stampeded::schema::migrate`
1057
- -- upgrades from it and refuses one newer than itself. Raised by each upgrade.
1058
- CREATE TABLE stampeded_schema (
1059
- version integer NOT NULL CHECK (version > 0),
1060
- changed_at timestamptz NOT NULL DEFAULT now()
1061
- );
1062
- CREATE UNIQUE INDEX stampeded_schema_one_row ON stampeded_schema ((true));
1063
- -- Must match schema::VERSION.
1064
- INSERT INTO stampeded_schema (version) VALUES (3);
@@ -0,0 +1,14 @@
1
+ -- Schema 2: the dedup key names its period. Without it, an hourly and a
2
+ -- daily unique job of the same scope shared a key whenever their buckets
3
+ -- started together (every midnight UTC, Mondays, the 1st of a month) and
4
+ -- refused each other. The new key is strictly finer: no row can collide.
5
+ ALTER TABLE stampeded_jobs ALTER COLUMN dedup_key SET EXPRESSION AS (
6
+ sha256((
7
+ dedup_scope || coalesce(
8
+ ':' || dedup_period || ':' || extract(
9
+ epoch FROM (date_trunc(dedup_period, inserted_at, 'UTC') - to_timestamp(0))
10
+ )::bigint::text,
11
+ ''
12
+ )
13
+ )::bytea)
14
+ );
@@ -0,0 +1,17 @@
1
+ -- Schema 3: the dedup key joins scope/period/bucket as bytea with a raw
2
+ -- zero byte. The old ':' join let a crafted dedup_scope (e.g.
3
+ -- 'a:hour:1700000000') forge the exact key of an unrelated periodic job
4
+ -- (scope 'a', period 'hour', that epoch) -- same sha256, same unique index,
5
+ -- wrongly rejected as a duplicate. No `text` value can ever decode to a
6
+ -- zero byte (chr(0) itself is refused by Postgres), so the new separator
7
+ -- can never be forged.
8
+ ALTER TABLE stampeded_jobs ALTER COLUMN dedup_key SET EXPRESSION AS (
9
+ sha256(
10
+ dedup_scope::bytea || '\x00'::bytea || coalesce(
11
+ dedup_period::bytea || '\x00'::bytea || extract(
12
+ epoch FROM (date_trunc(dedup_period, inserted_at, 'UTC') - to_timestamp(0))
13
+ )::bigint::text::bytea,
14
+ ''::bytea
15
+ )
16
+ )
17
+ );
@@ -0,0 +1,12 @@
1
+ -- Backslashes are doubled so `::bytea` keeps the scope's own bytes instead
2
+ -- of reading escapes: `a` and `\x61` are distinct scopes.
3
+ ALTER TABLE stampeded_jobs ALTER COLUMN dedup_key SET EXPRESSION AS (
4
+ sha256(
5
+ replace(dedup_scope, '\', '\\')::bytea || '\x00'::bytea || coalesce(
6
+ dedup_period::bytea || '\x00'::bytea || extract(
7
+ epoch FROM (date_trunc(dedup_period, inserted_at, 'UTC') - to_timestamp(0))
8
+ )::bigint::text::bytea,
9
+ ''::bytea
10
+ )
11
+ )
12
+ );
@@ -0,0 +1,9 @@
1
+ -- stampeded 0.4 reads this and refuses a version above 3, rather than
2
+ -- mistaking this database for an unversioned one and rewriting it.
3
+ CREATE TABLE IF NOT EXISTS stampeded_schema (
4
+ version integer NOT NULL CHECK (version > 0),
5
+ changed_at timestamptz NOT NULL DEFAULT now()
6
+ );
7
+ CREATE UNIQUE INDEX IF NOT EXISTS stampeded_schema_one_row ON stampeded_schema ((true));
8
+ DELETE FROM stampeded_schema;
9
+ INSERT INTO stampeded_schema (version) VALUES (5);
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stampeded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: x86_64-linux-gnu
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -83,7 +83,11 @@ files:
83
83
  - lib/stampeded/worker.rb
84
84
  - libexec/libstampeded_ffi.so
85
85
  - libexec/stampeded
86
- - schema/schema.sql
86
+ - schema/0001_init.sql
87
+ - schema/0002_dedup_key_period.sql
88
+ - schema/0003_dedup_key_separator.sql
89
+ - schema/0004_dedup_key_raw_scope.sql
90
+ - schema/0005_schema_version_guard.sql
87
91
  homepage: https://github.com/seuros/stampeded
88
92
  licenses:
89
93
  - BSD-3-Clause