joblin 0.2.0 → 0.2.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 +4 -4
- data/lib/joblin/batching/context_hash.rb +18 -2
- data/lib/joblin/version.rb +1 -1
- data/spec/batching/context_hash_spec.rb +86 -0
- data/spec/internal/log/test.log +998 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2e541ee5d08b606fc0acf25a8e2aae3fb45a24d430befdfaadefd01b12e3c05c
|
|
4
|
+
data.tar.gz: 901c664b71c3f615d337f0c9a41f52d95153af1234632a4b9dd4d8d527c87afb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9baf25436897e081d908f8f77873b9409b7b1fde6c47925a4b4309875ba9bbc1445ed3ec8ec2f3591a395c90c47f98854d84b5cf5ee2ce01ce519dd9aa16c43c
|
|
7
|
+
data.tar.gz: 8f0b5f1a644913410633f52227d26c2eabfb1770aaf3452b511be8409f0245c605bfa803093bef8783811e2b86d710d5b1fa3e097d7a1d323e94efd121050cc9
|
|
@@ -107,7 +107,7 @@ module Joblin::Batching
|
|
|
107
107
|
private
|
|
108
108
|
|
|
109
109
|
def get_parent_hash(bid)
|
|
110
|
-
resolve_hash(get_parent_bid(bid))
|
|
110
|
+
resolve_hash(get_parent_bid(bid))
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
def get_parent_bid(bid)
|
|
@@ -153,11 +153,27 @@ module Joblin::Batching
|
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
def load_all
|
|
156
|
-
resolve_hash(@bid_stack[0])
|
|
156
|
+
resolve_hash(@bid_stack[0])
|
|
157
157
|
while @bid_stack[0].present?
|
|
158
158
|
get_parent_hash(@bid_stack[0])
|
|
159
159
|
end
|
|
160
|
+
freeze_inherited!
|
|
160
161
|
@hash_map
|
|
161
162
|
end
|
|
163
|
+
|
|
164
|
+
# Every hash but `local` is inherited: #[]=, #delete and #save! only ever touch `local`, so a
|
|
165
|
+
# write to any other hash would be silently dropped rather than persisted. Freeze those to
|
|
166
|
+
# surface the mistake.
|
|
167
|
+
#
|
|
168
|
+
# `local` itself is deliberately left as-is - `resolve_hash` has already frozen it unless the
|
|
169
|
+
# owning Batch set allow_context_changes, and re-freezing it here would break writes on an
|
|
170
|
+
# editable Batch as a side effect of merely _reading_ the context.
|
|
171
|
+
def freeze_inherited!
|
|
172
|
+
writable_bid = local_bid
|
|
173
|
+
@hash_map.each do |bid, hash|
|
|
174
|
+
next if hash.nil? || bid == writable_bid
|
|
175
|
+
hash.freeze
|
|
176
|
+
end
|
|
177
|
+
end
|
|
162
178
|
end
|
|
163
179
|
end
|
data/lib/joblin/version.rb
CHANGED
|
@@ -40,6 +40,92 @@ RSpec.describe Joblin::Batching::ContextHash do
|
|
|
40
40
|
Sidekiq::Worker.drain_all
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
describe 'writability of a resolved context' do
|
|
44
|
+
# A Batch that both reads and writes its own context - the ReportSyncTask pattern. Reading the
|
|
45
|
+
# context as a Hash (present?, blank?, each, to_h, ... all route through #flatten) used to
|
|
46
|
+
# freeze the underlying hash and defeat allow_context_changes for the rest of the job.
|
|
47
|
+
def editable_batch(context)
|
|
48
|
+
Joblin::Batching::Batch.new.tap do |b|
|
|
49
|
+
b.allow_context_changes = true
|
|
50
|
+
b.context = context
|
|
51
|
+
b.jobs { }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'stays writable after the context is read as a Hash' do
|
|
56
|
+
batch = editable_batch(report_class: 'SomeReport')
|
|
57
|
+
ctx = Joblin::Batching::Batch.new(batch.bid).context
|
|
58
|
+
|
|
59
|
+
expect(ctx.present?).to eq(true)
|
|
60
|
+
expect { ctx[:report_attempt] = 1 }.not_to raise_error
|
|
61
|
+
expect(ctx[:report_attempt]).to eq(1)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'persists writes made after the context was read' do
|
|
65
|
+
batch = editable_batch(report_class: 'SomeReport')
|
|
66
|
+
loaded = Joblin::Batching::Batch.new(batch.bid)
|
|
67
|
+
loaded.context.to_h
|
|
68
|
+
loaded.context[:report_id] = 'some_report/1'
|
|
69
|
+
loaded.save_context_changes
|
|
70
|
+
|
|
71
|
+
expect(Joblin::Batching::Batch.new(batch.bid).context[:report_id]).to eq('some_report/1')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'leaves a non-editable context frozen' do
|
|
75
|
+
batch = Joblin::Batching::Batch.new
|
|
76
|
+
batch.context = { report_class: 'SomeReport' }
|
|
77
|
+
batch.jobs { }
|
|
78
|
+
ctx = Joblin::Batching::Batch.new(batch.bid).context
|
|
79
|
+
ctx.present?
|
|
80
|
+
|
|
81
|
+
expect { ctx[:report_attempt] = 1 }.to raise_error(FrozenError)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# `local` is "the nearest ancestor that actually has a context", so for a context-less Batch
|
|
85
|
+
# the writable hash belongs to an ancestor - #save! writes it back to that ancestor's key.
|
|
86
|
+
it 'stays writable when the context lives on an ancestor Batch' do
|
|
87
|
+
parent = editable_batch(sync_batch_id: 7)
|
|
88
|
+
child_bid = nil
|
|
89
|
+
parent.jobs do
|
|
90
|
+
child = Joblin::Batching::Batch.new
|
|
91
|
+
child.jobs { }
|
|
92
|
+
child_bid = child.bid
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
ctx = Joblin::Batching::Batch.new(child_bid).context
|
|
96
|
+
ctx.present?
|
|
97
|
+
|
|
98
|
+
expect(ctx.local_bid).to eq(parent.bid)
|
|
99
|
+
expect { ctx[:report_attempt] = 1 }.not_to raise_error
|
|
100
|
+
expect(ctx[:sync_batch_id]).to eq(7)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'freezes inherited contexts that writes would silently drop' do
|
|
104
|
+
grandparent = editable_batch(level: 'grandparent')
|
|
105
|
+
parent_bid = nil
|
|
106
|
+
child_bid = nil
|
|
107
|
+
grandparent.jobs do
|
|
108
|
+
parent = Joblin::Batching::Batch.new
|
|
109
|
+
parent.allow_context_changes = true
|
|
110
|
+
parent.context = { level: 'parent' }
|
|
111
|
+
parent.jobs do
|
|
112
|
+
child = Joblin::Batching::Batch.new
|
|
113
|
+
child.jobs { }
|
|
114
|
+
child_bid = child.bid
|
|
115
|
+
end
|
|
116
|
+
parent_bid = parent.bid
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
ctx = Joblin::Batching::Batch.new(child_bid).context
|
|
120
|
+
ctx.to_h
|
|
121
|
+
hash_map = ctx.send(:instance_variable_get, :@hash_map)
|
|
122
|
+
|
|
123
|
+
expect(ctx.local_bid).to eq(parent_bid)
|
|
124
|
+
expect(hash_map[parent_bid]).not_to be_frozen
|
|
125
|
+
expect(hash_map[grandparent.bid]).to be_frozen
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
43
129
|
it 'works with a callback batch' do
|
|
44
130
|
ActiveJob::Base.queue_adapter = :sidekiq
|
|
45
131
|
b = Joblin::Batching::Batch.new
|