tupelo 0.21 → 0.22

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +171 -45
  3. data/bin/tup +51 -0
  4. data/example/counters/merge.rb +23 -3
  5. data/example/multi-tier/multi-sinatras.rb +5 -0
  6. data/example/riemann/event-subspace.rb +1 -4
  7. data/example/riemann/expiration-dbg.rb +2 -0
  8. data/example/riemann/producer.rb +4 -3
  9. data/example/riemann/v1/riemann.rb +2 -2
  10. data/example/riemann/v2/event-template.rb +71 -0
  11. data/example/riemann/v2/expirer.rb +1 -1
  12. data/example/riemann/v2/hash-store.rb +1 -0
  13. data/example/riemann/v2/ordered-event-store.rb +4 -1
  14. data/example/riemann/v2/riemann.rb +15 -8
  15. data/example/riemann/v2/sqlite-event-store.rb +117 -72
  16. data/example/sqlite/poi-store.rb +1 -1
  17. data/example/sqlite/poi-template.rb +2 -2
  18. data/example/sqlite/poi-v2.rb +2 -2
  19. data/example/subspaces/ramp.rb +9 -2
  20. data/example/tcp.rb +5 -0
  21. data/example/tiny-tcp-client.rb +15 -0
  22. data/example/tiny-tcp-service.rb +32 -0
  23. data/lib/tupelo/app.rb +4 -4
  24. data/lib/tupelo/app/builder.rb +2 -2
  25. data/lib/tupelo/app/irb-shell.rb +3 -3
  26. data/lib/tupelo/archiver.rb +0 -2
  27. data/lib/tupelo/archiver/tuplestore.rb +1 -1
  28. data/lib/tupelo/archiver/worker.rb +6 -6
  29. data/lib/tupelo/client.rb +2 -2
  30. data/lib/tupelo/client/reader.rb +3 -3
  31. data/lib/tupelo/client/scheduler.rb +1 -1
  32. data/lib/tupelo/client/subspace.rb +2 -2
  33. data/lib/tupelo/client/transaction.rb +28 -28
  34. data/lib/tupelo/client/tuplestore.rb +2 -2
  35. data/lib/tupelo/client/worker.rb +11 -10
  36. data/lib/tupelo/util/bin-circle.rb +8 -8
  37. data/lib/tupelo/util/boolean.rb +1 -1
  38. data/lib/tupelo/version.rb +1 -1
  39. data/test/lib/mock-client.rb +10 -10
  40. data/test/system/test-archiver.rb +2 -2
  41. data/test/unit/test-ops.rb +21 -21
  42. metadata +10 -20
  43. data/example/bingo/bingo-v2.rb +0 -20
  44. data/example/broker-queue.rb +0 -35
  45. data/example/child-of-child.rb +0 -34
  46. data/example/dataflow.rb +0 -21
  47. data/example/pregel/dist-opt.rb +0 -15
  48. data/example/riemann/v2/event-sql.rb +0 -56
  49. data/example/sqlite/tmp/poi-sqlite.rb +0 -35
  50. data/example/subspaces/addr-book-v1.rb +0 -104
  51. data/example/subspaces/addr-book-v2.rb +0 -16
  52. data/example/subspaces/sorted-set-space-OLD.rb +0 -130
  53. data/lib/tupelo/tuplets/persistent-archiver.rb +0 -86
  54. data/lib/tupelo/tuplets/persistent-archiver/tuplespace.rb +0 -91
  55. data/lib/tupelo/tuplets/persistent-archiver/worker.rb +0 -114
@@ -31,7 +31,7 @@ class Tupelo::Client
31
31
  end
32
32
  end
33
33
  end
34
-
34
+
35
35
  # Tuplestore that stores nothing. Very efficient for large stores!
36
36
  # Useful for clients that don't need to take or read the stored tuples.
37
37
  # The write, pulse, and blocking read operations all work correctly.
@@ -45,7 +45,7 @@ class Tupelo::Client
45
45
  def find_distinct_matches_for(*); raise; end
46
46
  def find_match_for(*); raise; end
47
47
  def clear; end
48
-
48
+
49
49
  ## should store space metadata, so outgoing writes can be tagged
50
50
  end
51
51
  end
@@ -17,7 +17,6 @@ class Tupelo::Client
17
17
  attr_reader :msg_reader_thread
18
18
  attr_reader :worker_thread
19
19
  attr_reader :cmd_queue
20
- attr_reader :tuplestore
21
20
  attr_reader :message_class
22
21
  attr_reader :blobber
23
22
  attr_reader :read_waiters
@@ -34,7 +33,7 @@ class Tupelo::Client
34
33
  def initialize writes, pulses, takes, reads
35
34
  @writes, @pulses, @takes, @reads = writes, pulses, takes, reads
36
35
  end
37
-
36
+
38
37
  NOOP = new([].freeze, [].freeze, [].freeze, [].freeze).freeze
39
38
 
40
39
  def to_s
@@ -48,11 +47,11 @@ class Tupelo::Client
48
47
  end
49
48
  alias inspect to_s
50
49
  end
51
-
50
+
52
51
  class Subspace
53
52
  attr_reader :tag, :spec, :pot
54
53
  alias template pot
55
-
54
+
56
55
  def initialize metatuple, worker
57
56
  @metatuple = metatuple
58
57
  @tag = metatuple["tag"] || metatuple[:tag]
@@ -61,7 +60,7 @@ class Tupelo::Client
61
60
  @spec = Marshal.load(Marshal.dump(template)).freeze
62
61
  @pot = worker.pot_for(spec).optimize!.freeze
63
62
  end
64
-
63
+
65
64
  def === tuple
66
65
  @pot === tuple
67
66
  end
@@ -91,16 +90,18 @@ class Tupelo::Client
91
90
  @notify_waiters = []
92
91
  @stopping = false
93
92
  @subspaces = []
93
+
94
+ @worker_thread = nil
94
95
  end
95
96
 
96
97
  def log *args
97
98
  if args.empty?
98
99
  @log
99
100
  else
100
- @log.unknown *args
101
+ @log.unknown(*args)
101
102
  end
102
103
  end
103
-
104
+
104
105
  def tuplestore
105
106
  @tuplestore ||= begin
106
107
  if client.tuplestore.respond_to? :new
@@ -353,7 +354,7 @@ class Tupelo::Client
353
354
  log.debug {"inserting #{op.writes}; deleting #{take_tuples}"}
354
355
  tuplestore.transaction inserts: write_tuples, deletes: take_tuples,
355
356
  tick: @global_tick
356
-
357
+
357
358
  op.writes.each do |tuple|
358
359
  sniff_meta_tuple tuple
359
360
  end
@@ -539,7 +540,7 @@ class Tupelo::Client
539
540
  read_waiters << waiter
540
541
  end
541
542
  else
542
- tuplestore.each {|tuple| waiter.gloms tuple}
543
+ tuplestore.each {|t| waiter.gloms t}
543
544
  read_waiters << waiter
544
545
  end
545
546
  end
@@ -582,7 +583,7 @@ class Tupelo::Client
582
583
  pulses = transaction.pulses
583
584
  takes = transaction.take_tuples_for_remote.compact
584
585
  reads = transaction.read_tuples_for_remote.compact
585
-
586
+
586
587
  unless msg.tags
587
588
  tags = nil
588
589
  [takes, reads].compact.flatten(1).each do |tuple|
@@ -29,31 +29,31 @@ class BinCircle
29
29
  KEY_BITS = 30
30
30
  KEY_MAX = 2**KEY_BITS - 1
31
31
  DEFAULT_REPS = 10
32
-
32
+
33
33
  attr_accessor :default_reps
34
34
 
35
35
  def initialize reps: DEFAULT_REPS
36
36
  @tree = MultiRBTree.new # hashed_bin_id => bin_id
37
37
  @default_reps = reps
38
38
  end
39
-
39
+
40
40
  # +id+ should be an identifier for your bin, typically a number or string.
41
41
  # Uses id.to_s, so +id+ should not contain a hash (which would not determine
42
42
  # a unique string).
43
43
  def add_bin id, reps: default_reps
44
44
  rep_id = "#{id} 0000"
45
- reps.times do |i|
45
+ reps.times do
46
46
  key = key_for_string(rep_id)
47
47
  @tree[key] = id
48
48
  rep_id.succ!
49
49
  end
50
50
  end
51
-
51
+
52
52
  # Returns the set of bin ids now in the circle.
53
53
  def bins
54
54
  Set.new @tree.values
55
55
  end
56
-
56
+
57
57
  def inspect
58
58
  "#<#{self.class} bins=#{bins.to_a}>"
59
59
  end
@@ -64,19 +64,19 @@ class BinCircle
64
64
  def key_for_string str
65
65
  Digest::MD5.hexdigest(str).to_i(16) & KEY_MAX
66
66
  end
67
-
67
+
68
68
  # Delete the bin specified by +id+ (same as argument to #add_bin).
69
69
  def delete_bin id
70
70
  @tree.delete_if {|k,v| v == id}
71
71
  end
72
-
72
+
73
73
  # +id+ should be an identifier for your object, typically a number or string.
74
74
  # Uses id.to_s, so +id+ should not contain a hash (which would not determine
75
75
  # a unique string). It is not necessary for +id+ to be unique across objects.
76
76
  def find_bin obj
77
77
  find_bin_by_key(key_for_string(obj.to_s))
78
78
  end
79
-
79
+
80
80
  def find_bin_by_key key
81
81
  _, id = @tree.lower_bound(key) || @tree.first
82
82
  id
@@ -10,7 +10,7 @@ class Tupelo::Client
10
10
  templates.any? {|template| template === obj}
11
11
  end
12
12
  end
13
-
13
+
14
14
  def or *templates
15
15
  Or.new(worker, templates)
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module Tupelo
2
- VERSION = "0.21"
2
+ VERSION = "0.22"
3
3
  end
@@ -25,16 +25,16 @@ class MockClient
25
25
  def update
26
26
  worker.update
27
27
  end
28
-
28
+
29
29
  def make_queue
30
30
  MockQueue.new
31
31
  end
32
-
33
- def will &block
34
- (@will_do ||= []) << Fiber.new { instance_eval &block }
32
+
33
+ def will(&block)
34
+ (@will_do ||= []) << Fiber.new { instance_eval(&block) }
35
35
  self
36
36
  end
37
-
37
+
38
38
  def step
39
39
  loop do
40
40
  fiber = @will_do[0] or raise IsDone, "nothing to do"
@@ -49,7 +49,7 @@ class MockClient
49
49
  @will_do.shift
50
50
  end
51
51
  end
52
-
52
+
53
53
  def run limit: 100
54
54
  loop do
55
55
  fiber = @will_do[0] or raise IsDone, "nothing to do"
@@ -77,7 +77,7 @@ class MockClient
77
77
  @will_do.shift
78
78
  end
79
79
  end
80
-
80
+
81
81
  def run_until_blocked limit: 100, &block
82
82
  begin
83
83
  run limit: limit, &block
@@ -86,9 +86,9 @@ class MockClient
86
86
  end
87
87
  raise IsDone, "run_until_blocked never blocked"
88
88
  end
89
-
89
+
90
90
  def now limit: 100, &block
91
- fiber = Fiber.new { instance_eval &block }
91
+ fiber = Fiber.new { instance_eval(&block) }
92
92
  val = nil
93
93
  count = 0
94
94
  update
@@ -106,7 +106,7 @@ class MockClient
106
106
  end
107
107
  val
108
108
  end
109
-
109
+
110
110
  def subscribed_all
111
111
  true
112
112
  end
@@ -4,9 +4,9 @@ Tupelo.application do
4
4
  expected = [[1], [2], [3]]
5
5
 
6
6
  local do
7
- write *expected
7
+ write(*expected)
8
8
  end
9
-
9
+
10
10
  child_pid = child do
11
11
  # Test that tuples written before this client started are readable.
12
12
  a = read_all [Integer]
@@ -40,14 +40,14 @@ class TestOps < Minitest::Test
40
40
  def make_clients n
41
41
  n.times.map {|i| make_client i}
42
42
  end
43
-
43
+
44
44
  def test_one_client
45
45
  client = make_client "one"
46
46
 
47
47
  client.update; writer = client.write_nowait [1]
48
48
  client.update; writer.wait
49
49
  client.update; assert_equal 1, writer.global_tick
50
-
50
+
51
51
  reader = Fiber.new do
52
52
  client.read [nil]
53
53
  end
@@ -55,11 +55,11 @@ class TestOps < Minitest::Test
55
55
  client.update; reader.resume
56
56
  client.update; assert_equal [1], reader.resume
57
57
  end
58
-
58
+
59
59
  def test_read_existing
60
60
  t = ["foo"]
61
61
  cl = make_clients(2)
62
-
62
+
63
63
  w = cl[0].now {write t}
64
64
  assert_equal 1, w.global_tick
65
65
 
@@ -129,7 +129,7 @@ class TestOps < Minitest::Test
129
129
  def test_take_waiting
130
130
  t = ["bar"]
131
131
  taker, writer = make_clients(2)
132
-
132
+
133
133
  taker.will {take [nil]}.run_until_blocked
134
134
 
135
135
  w = writer.now {write t}
@@ -142,14 +142,14 @@ class TestOps < Minitest::Test
142
142
  assert_empty c.run
143
143
  end
144
144
  end
145
-
145
+
146
146
  def test_transaction_existing
147
147
  r = [0]; w = [1]; t = [2]
148
148
  writer, transactor = make_clients(2)
149
149
 
150
150
  w_op = writer.now {write r, t}
151
151
  assert_equal 1, w_op.global_tick
152
-
152
+
153
153
  transactor.will do
154
154
  transaction do
155
155
  write w
@@ -164,7 +164,7 @@ class TestOps < Minitest::Test
164
164
  assert_equal [r, w], c.run
165
165
  end
166
166
  end
167
-
167
+
168
168
  def test_transaction_waiting
169
169
  r = [0]; w = [1]; t = [2]
170
170
  writer, transactor = make_clients(2)
@@ -179,7 +179,7 @@ class TestOps < Minitest::Test
179
179
 
180
180
  w_op = writer.now {write r, t}
181
181
  assert_equal 1, w_op.global_tick
182
-
182
+
183
183
  assert_equal [r, t], transactor.run
184
184
 
185
185
  [writer, transactor].each do |c|
@@ -187,12 +187,12 @@ class TestOps < Minitest::Test
187
187
  assert_equal [r, w], c.run
188
188
  end
189
189
  end
190
-
190
+
191
191
  def test_transaction_take_two
192
192
  x = [0]; y = [1]
193
193
  c = make_client(1)
194
194
 
195
- w_op = c.now {write x, y}
195
+ c.now {write x, y}
196
196
 
197
197
  c.will do
198
198
  transaction do
@@ -202,12 +202,12 @@ class TestOps < Minitest::Test
202
202
 
203
203
  assert_equal [x, y].sort, c.run.sort
204
204
  end
205
-
205
+
206
206
  def test_transaction_take_read
207
207
  x = [0]
208
208
  c = make_client(1)
209
209
 
210
- w_op = c.now {write x}
210
+ c.now {write x}
211
211
 
212
212
  c.will do
213
213
  transaction do
@@ -217,7 +217,7 @@ class TestOps < Minitest::Test
217
217
 
218
218
  assert_equal [x, nil], c.run
219
219
  end
220
-
220
+
221
221
  def test_transaction_write_read
222
222
  x = [0]
223
223
  c = make_client(1)
@@ -255,7 +255,7 @@ class TestOps < Minitest::Test
255
255
  assert_equal nil, transactor.run
256
256
  assert_equal 0, transactor.worker.global_tick
257
257
  end
258
-
258
+
259
259
  def test_transaction_cancel
260
260
  w = [1]; t = [2]
261
261
  writer, transactor = make_clients(2)
@@ -283,11 +283,11 @@ class TestOps < Minitest::Test
283
283
  assert_equal [t], c.run
284
284
  end
285
285
  end
286
-
286
+
287
287
  def test_transaction_fail_retry
288
288
  winner, loser = make_clients(2)
289
289
  winner.now {write ["token", 1]}
290
-
290
+
291
291
  run_count = 0
292
292
  result = nil
293
293
  loser.will do
@@ -304,7 +304,7 @@ class TestOps < Minitest::Test
304
304
  end
305
305
  loser.run_until_blocked
306
306
  assert_equal 1, run_count
307
-
307
+
308
308
  winner.will do
309
309
  take ["token", 1]
310
310
  end
@@ -316,14 +316,14 @@ class TestOps < Minitest::Test
316
316
 
317
317
  winner.now {write ["token", 2]}
318
318
  assert_raises(MockClient::IsBlocked) {loser.run}
319
-
319
+
320
320
  winner.now {write ["token", 1]}
321
321
  assert_equal [["token", 1], ["token", 2]], loser.run
322
-
322
+
323
323
  result = winner.now {read_all [nil, nil]}
324
324
  assert_equal [["test", 1], ["test", 2], ["test", 3]], result
325
325
  end
326
-
326
+
327
327
  def test_pulse
328
328
  t = ["c0"]
329
329
  reader, pulser = make_clients(2)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tupelo
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.21'
4
+ version: '0.22'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel VanderWerf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-19 00:00:00.000000000 Z
11
+ date: 2014-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: atdo
@@ -95,17 +95,14 @@ files:
95
95
  - example/balance-xfer.rb
96
96
  - example/barrier.rb
97
97
  - example/bingo/bingo-v1.rb
98
- - example/bingo/bingo-v2.rb
99
98
  - example/boolean-match.rb
100
99
  - example/bounded-retry.rb
101
100
  - example/broker-locking.rb
102
101
  - example/broker-optimistic-v2.rb
103
102
  - example/broker-optimistic.rb
104
- - example/broker-queue.rb
105
103
  - example/cancel.rb
106
104
  - example/chat/chat-nohistory.rb
107
105
  - example/chat/chat.rb
108
- - example/child-of-child.rb
109
106
  - example/concurrent-transactions.rb
110
107
  - example/consistent-hash.rb
111
108
  - example/counters/lock.rb
@@ -113,7 +110,6 @@ files:
113
110
  - example/counters/optimistic.rb
114
111
  - example/custom-class.rb
115
112
  - example/custom-search.rb
116
- - example/dataflow.rb
117
113
  - example/deadlock.rb
118
114
  - example/dedup.rb
119
115
  - example/dphil-optimistic-v2.rb
@@ -144,7 +140,6 @@ files:
144
140
  - example/observer.rb
145
141
  - example/optimist.rb
146
142
  - example/parallel.rb
147
- - example/pregel/dist-opt.rb
148
143
  - example/pregel/distributed.rb
149
144
  - example/pregel/pagerank.rb
150
145
  - example/pregel/pregel.rb
@@ -159,7 +154,7 @@ files:
159
154
  - example/riemann/producer.rb
160
155
  - example/riemann/v1/expirer.rb
161
156
  - example/riemann/v1/riemann.rb
162
- - example/riemann/v2/event-sql.rb
157
+ - example/riemann/v2/event-template.rb
163
158
  - example/riemann/v2/expirer.rb
164
159
  - example/riemann/v2/hash-store.rb
165
160
  - example/riemann/v2/http-mode.rb
@@ -174,16 +169,12 @@ files:
174
169
  - example/sqlite/poi-template.rb
175
170
  - example/sqlite/poi-v2.rb
176
171
  - example/sqlite/poi.rb
177
- - example/sqlite/tmp/poi-sqlite.rb
178
- - example/subspaces/addr-book-v1.rb
179
- - example/subspaces/addr-book-v2.rb
180
172
  - example/subspaces/addr-book.rb
181
173
  - example/subspaces/pubsub.rb
182
174
  - example/subspaces/ramp.rb
183
175
  - example/subspaces/shop/shop-v1.rb
184
176
  - example/subspaces/shop/shop-v2.rb
185
177
  - example/subspaces/simple.rb
186
- - example/subspaces/sorted-set-space-OLD.rb
187
178
  - example/subspaces/sorted-set-store.rb
188
179
  - example/take-many.rb
189
180
  - example/take-nowait-caution.rb
@@ -193,6 +184,8 @@ files:
193
184
  - example/timeout.rb
194
185
  - example/tiny-client.rb
195
186
  - example/tiny-service.rb
187
+ - example/tiny-tcp-client.rb
188
+ - example/tiny-tcp-service.rb
196
189
  - example/transaction-logic.rb
197
190
  - example/uniq-id.rb
198
191
  - example/wait-interrupt.rb
@@ -220,9 +213,6 @@ files:
220
213
  - lib/tupelo/client/transaction.rb
221
214
  - lib/tupelo/client/tuplestore.rb
222
215
  - lib/tupelo/client/worker.rb
223
- - lib/tupelo/tuplets/persistent-archiver.rb
224
- - lib/tupelo/tuplets/persistent-archiver/tuplespace.rb
225
- - lib/tupelo/tuplets/persistent-archiver/worker.rb
226
216
  - lib/tupelo/util/bin-circle.rb
227
217
  - lib/tupelo/util/boolean.rb
228
218
  - lib/tupelo/version.rb
@@ -256,9 +246,9 @@ require_paths:
256
246
  - lib
257
247
  required_ruby_version: !ruby/object:Gem::Requirement
258
248
  requirements:
259
- - - ">="
249
+ - - "~>"
260
250
  - !ruby/object:Gem::Version
261
- version: '0'
251
+ version: '2.0'
262
252
  required_rubygems_version: !ruby/object:Gem::Requirement
263
253
  requirements:
264
254
  - - ">="
@@ -266,13 +256,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
256
  version: '0'
267
257
  requirements: []
268
258
  rubyforge_project:
269
- rubygems_version: 2.2.2
259
+ rubygems_version: 2.4.1
270
260
  signing_key:
271
261
  specification_version: 4
272
262
  summary: Distributed tuplespace
273
263
  test_files:
274
- - test/unit/test-ops.rb
275
- - test/unit/test-mock-client.rb
276
264
  - test/unit/test-mock-seq.rb
277
265
  - test/unit/test-mock-queue.rb
266
+ - test/unit/test-ops.rb
267
+ - test/unit/test-mock-client.rb
278
268
  has_rdoc: