async-background 0.7.0 → 0.7.1

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: 851bdc350f52df868547200fe10a0d93b06b692b605c6e761b28262e2691a4df
4
- data.tar.gz: 8eccc004e5250df5349135a979a59e52f7450ee356245e8cab17b4b6e2a9a9f6
3
+ metadata.gz: a8f8593628f08094cc53b6c69eff34e3a4be9e8c12de5bd72f1447857aab2682
4
+ data.tar.gz: e9e441eb2b6f775cd52d2704c8a2b24d9ac771a24beb07d33f78d81285d41f1c
5
5
  SHA512:
6
- metadata.gz: 7ce63c6e58d96670add9cbfc438ab5cb33d2472c3ef6d4484cde4682f3416749f946cadc1fe00333e1e6e68b1b861df8d6d9cb88a7e520f48f73ecc9b4c86265
7
- data.tar.gz: e4f7fc4fb560dba97580f0bd1ea446ade22edb219e1fba7d725ecb4b798b2feddf76b5266f3e408516b33d880046c481ca7b0746ae08accd70a1665466143019
6
+ metadata.gz: 194c82e280d24821e756849cc9f3f74db8cbadc424d4984fb3a58d10d21864cbe13b1adfa84aa3bf1bd6b9996d59e1d423d5c865c2d1ec33846679ed2ab936f0
7
+ data.tar.gz: 518bc2a692d0ade6ea02ff18ebca2a3078e02365ffd77fe9850d8bccc64b7243ea871efeec2913f33fe7ecdaeb8fa6a56067e57f36d5852adf59302cc656416e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.1
4
+
5
+ ### Features
6
+ - **Tunable `Store` options via `StoreOptions`** — three knobs exposed for SQLite tuning, validated at construction time so misconfigurations fail fast at boot:
7
+ - `mmap` (`true`/`false`, default `true`) — toggle memory-mapped I/O
8
+ - `synchronous` (`:normal`/`:full`/`:extra`, default `:normal`) — durability vs throughput
9
+ - `wal_autocheckpoint` (`Integer` in `100..10_000`, default `1_000`) — WAL checkpoint frequency in pages
10
+
11
+ Range and enum validation prevent foot-guns (e.g. `wal_autocheckpoint: 100_000` would bloat WAL beyond `journal_size_limit`). See [Get Started → Store tuning](docs/GET_STARTED.md) for trade-offs of each knob
12
+
13
+ ### Breaking changes
14
+ - `Store.new(path:, mmap:)` → `Store.new(path:, options: { mmap: ... })`. Direct `mmap:` keyword argument removed in favor of the unified `options:` hash. Users who construct `Store` manually (e.g. for web-worker enqueue) need to update the call site
15
+
3
16
  ## 0.6.2
4
17
 
5
18
  ### Features
@@ -6,6 +6,49 @@ require_relative '../clock'
6
6
  module Async
7
7
  module Background
8
8
  module Queue
9
+ SYNCHRONOUS_LEVELS = { normal: 'NORMAL', full: 'FULL', extra: 'EXTRA' }.freeze
10
+ WAL_AUTOCHECKPOINT_RANGE = 100..10_000
11
+ DEFAULTS = { mmap: true, synchronous: :normal, wal_autocheckpoint: 1_000 }.freeze
12
+ MMAP_SIZE = 268_435_456
13
+
14
+ StoreOptions = Data.define(:mmap, :synchronous, :wal_autocheckpoint) do
15
+ def self.build(value = {}) = value.is_a?(self) ? value : new(**DEFAULTS, **value)
16
+
17
+ def initialize(mmap:, synchronous:, wal_autocheckpoint:)
18
+ unless mmap == true || mmap == false
19
+ raise ArgumentError, "mmap must be true or false, got #{mmap.inspect}"
20
+ end
21
+
22
+ unless SYNCHRONOUS_LEVELS.key?(synchronous)
23
+ raise ArgumentError,
24
+ "synchronous must be one of #{SYNCHRONOUS_LEVELS.keys.inspect}, got #{synchronous.inspect}"
25
+ end
26
+
27
+ unless wal_autocheckpoint.is_a?(Integer) && WAL_AUTOCHECKPOINT_RANGE.cover?(wal_autocheckpoint)
28
+ raise ArgumentError,
29
+ "wal_autocheckpoint must be an Integer in #{WAL_AUTOCHECKPOINT_RANGE}, " \
30
+ "got #{wal_autocheckpoint.inspect}"
31
+ end
32
+
33
+ super
34
+ end
35
+
36
+ def synchronous_pragma = SYNCHRONOUS_LEVELS.fetch(synchronous)
37
+ def mmap_size = mmap ? MMAP_SIZE : 0
38
+
39
+ def pragma_sql
40
+ <<~SQL
41
+ PRAGMA journal_mode = WAL;
42
+ PRAGMA synchronous = #{synchronous_pragma};
43
+ PRAGMA mmap_size = #{mmap_size};
44
+ PRAGMA cache_size = -16000;
45
+ PRAGMA temp_store = MEMORY;
46
+ PRAGMA journal_size_limit = 67108864;
47
+ PRAGMA wal_autocheckpoint = #{wal_autocheckpoint};
48
+ SQL
49
+ end
50
+ end
51
+
9
52
  class Store
10
53
  include Clock
11
54
 
@@ -25,29 +68,17 @@ module Async
25
68
  CREATE INDEX IF NOT EXISTS idx_jobs_pending ON jobs(run_at, id) WHERE status = 'pending';
26
69
  SQL
27
70
 
28
- MMAP_SIZE = 268_435_456
29
- PRAGMAS = ->(mmap_size) {
30
- <<~SQL
31
- PRAGMA journal_mode = WAL;
32
- PRAGMA synchronous = NORMAL;
33
- PRAGMA mmap_size = #{mmap_size};
34
- PRAGMA cache_size = -16000;
35
- PRAGMA temp_store = MEMORY;
36
- PRAGMA busy_timeout = 5000;
37
- PRAGMA journal_size_limit = 67108864;
38
- SQL
39
- }.freeze
40
-
41
71
  CLEANUP_INTERVAL = 300
42
72
  CLEANUP_AGE = 3600
43
73
 
44
- attr_reader :path
74
+ attr_reader :path, :options
45
75
 
46
- def initialize(path: self.class.default_path, mmap: true)
47
- @path = path
48
- @pragma_sql = PRAGMAS.call(mmap ? MMAP_SIZE : 0).freeze
49
- @db = nil
50
- @schema_checked = false
76
+ def initialize(path: self.class.default_path, options: {})
77
+ @path = path
78
+ @options = StoreOptions.build(options)
79
+ @pragma_sql = @options.pragma_sql.freeze
80
+ @db = nil
81
+ @schema_checked = false
51
82
  @last_cleanup_at = nil
52
83
  end
53
84
 
@@ -78,8 +78,8 @@ module Async
78
78
 
79
79
  @listen_queue = true
80
80
  @queue_store = Queue::Store.new(
81
- path: queue_db_path || Queue::Store.default_path,
82
- mmap: queue_mmap
81
+ path: queue_db_path || Queue::Store.default_path,
82
+ options: { mmap: queue_mmap }
83
83
  )
84
84
 
85
85
  socket_path = File.join(queue_socket_dir, "async_bg_worker_#{worker_index}.sock")
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Async
4
4
  module Background
5
- VERSION = '0.7.0'
5
+ VERSION = '0.7.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-background
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Hajdarov
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2026-04-23 00:00:00.000000000 Z
11
+ date: 2026-05-02 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: async
@@ -113,6 +114,7 @@ metadata:
113
114
  source_code_uri: https://github.com/roman-haidarov/async-background
114
115
  changelog_uri: https://github.com/roman-haidarov/async-background/blob/main/CHANGELOG.md
115
116
  bug_tracker_uri: https://github.com/roman-haidarov/async-background/issues
117
+ post_install_message:
116
118
  rdoc_options: []
117
119
  require_paths:
118
120
  - lib
@@ -127,7 +129,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
129
  - !ruby/object:Gem::Version
128
130
  version: '0'
129
131
  requirements: []
130
- rubygems_version: 3.6.2
132
+ rubygems_version: 3.3.27
133
+ signing_key:
131
134
  specification_version: 4
132
135
  summary: Lightweight heap-based cron/interval scheduler for Async.
133
136
  test_files: []