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.
- checksums.yaml +4 -4
- data/README.md +171 -45
- data/bin/tup +51 -0
- data/example/counters/merge.rb +23 -3
- data/example/multi-tier/multi-sinatras.rb +5 -0
- data/example/riemann/event-subspace.rb +1 -4
- data/example/riemann/expiration-dbg.rb +2 -0
- data/example/riemann/producer.rb +4 -3
- data/example/riemann/v1/riemann.rb +2 -2
- data/example/riemann/v2/event-template.rb +71 -0
- data/example/riemann/v2/expirer.rb +1 -1
- data/example/riemann/v2/hash-store.rb +1 -0
- data/example/riemann/v2/ordered-event-store.rb +4 -1
- data/example/riemann/v2/riemann.rb +15 -8
- data/example/riemann/v2/sqlite-event-store.rb +117 -72
- data/example/sqlite/poi-store.rb +1 -1
- data/example/sqlite/poi-template.rb +2 -2
- data/example/sqlite/poi-v2.rb +2 -2
- data/example/subspaces/ramp.rb +9 -2
- data/example/tcp.rb +5 -0
- data/example/tiny-tcp-client.rb +15 -0
- data/example/tiny-tcp-service.rb +32 -0
- data/lib/tupelo/app.rb +4 -4
- data/lib/tupelo/app/builder.rb +2 -2
- data/lib/tupelo/app/irb-shell.rb +3 -3
- data/lib/tupelo/archiver.rb +0 -2
- data/lib/tupelo/archiver/tuplestore.rb +1 -1
- data/lib/tupelo/archiver/worker.rb +6 -6
- data/lib/tupelo/client.rb +2 -2
- data/lib/tupelo/client/reader.rb +3 -3
- data/lib/tupelo/client/scheduler.rb +1 -1
- data/lib/tupelo/client/subspace.rb +2 -2
- data/lib/tupelo/client/transaction.rb +28 -28
- data/lib/tupelo/client/tuplestore.rb +2 -2
- data/lib/tupelo/client/worker.rb +11 -10
- data/lib/tupelo/util/bin-circle.rb +8 -8
- data/lib/tupelo/util/boolean.rb +1 -1
- data/lib/tupelo/version.rb +1 -1
- data/test/lib/mock-client.rb +10 -10
- data/test/system/test-archiver.rb +2 -2
- data/test/unit/test-ops.rb +21 -21
- metadata +10 -20
- data/example/bingo/bingo-v2.rb +0 -20
- data/example/broker-queue.rb +0 -35
- data/example/child-of-child.rb +0 -34
- data/example/dataflow.rb +0 -21
- data/example/pregel/dist-opt.rb +0 -15
- data/example/riemann/v2/event-sql.rb +0 -56
- data/example/sqlite/tmp/poi-sqlite.rb +0 -35
- data/example/subspaces/addr-book-v1.rb +0 -104
- data/example/subspaces/addr-book-v2.rb +0 -16
- data/example/subspaces/sorted-set-space-OLD.rb +0 -130
- data/lib/tupelo/tuplets/persistent-archiver.rb +0 -86
- data/lib/tupelo/tuplets/persistent-archiver/tuplespace.rb +0 -91
- data/lib/tupelo/tuplets/persistent-archiver/worker.rb +0 -114
data/example/sqlite/poi-v2.rb
CHANGED
@@ -23,14 +23,14 @@ Tupelo.application do
|
|
23
23
|
when "find box"
|
24
24
|
arg = req[:arg] ## should validate args
|
25
25
|
lat = arg[:lat]; lng = arg[:lng]
|
26
|
-
template = PoiTemplate.new(
|
26
|
+
template = PoiTemplate.new(poispace,
|
27
27
|
lat: lat[0]..lat[1], lng: lng[0]..lng[1])
|
28
28
|
write id: req[:id], result: read_all(template)
|
29
29
|
|
30
30
|
when "delete box"
|
31
31
|
arg = req[:arg]
|
32
32
|
lat = arg[:lat]; lng = arg[:lng]
|
33
|
-
template = PoiTemplate.new(
|
33
|
+
template = PoiTemplate.new(poispace,
|
34
34
|
lat: lat[0]..lat[1], lng: lng[0]..lng[1])
|
35
35
|
|
36
36
|
deleted = []
|
data/example/subspaces/ramp.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Read-atomic multipartition transactions, as per:
|
2
2
|
# http://www.youtube.com/watch?v=_rAdJkAbGls (around minutes 28-30)
|
3
3
|
# http://www.bailis.org/blog/non-blocking-transactional-atomicity
|
4
|
+
# http://www.bailis.org/blog/scalable-atomic-visibility-with-ramp-transactions
|
4
5
|
#
|
5
6
|
# Example of transacting separately on two subspaces (i.e. shardable subsets of
|
6
7
|
# the tuplespace), but hiding intermediate tuples so that the results show up
|
@@ -9,7 +10,7 @@
|
|
9
10
|
# tupelo transactions.)
|
10
11
|
#
|
11
12
|
# In tupelo, we could use the classic tuplespace technique of taking a lock
|
12
|
-
# tuple to protect the sequence
|
13
|
+
# tuple to protect the sequence of two transactions on the two subspaces, but
|
13
14
|
# that would reduce concurrency and require a lease mechanism in case the lock
|
14
15
|
# holder dies. That's possible, but not scalable. So we use transactions with a
|
15
16
|
# trick...
|
@@ -33,7 +34,7 @@ X_REPLICATIONS = 1 # number of copies of the shard of X data
|
|
33
34
|
Y_REPLICATIONS = 1 # number of copies of the shard of Y data
|
34
35
|
|
35
36
|
def next_local_id
|
36
|
-
@counter
|
37
|
+
@counter ||= 0
|
37
38
|
@counter += 1
|
38
39
|
# Protect this with a mutex or queue if other threads need it, or
|
39
40
|
# use the atomic gem. It's ok in a multiprocess app without mutex,
|
@@ -128,6 +129,12 @@ Tupelo.application do
|
|
128
129
|
# This doesn't test that RAMP is working -- it will always see a consistent
|
129
130
|
# view because of tupelo, even without the pending/ack trick. It is more
|
130
131
|
# informative to look at the log output from the x and y clients.
|
132
|
+
#
|
133
|
+
# The key point of this example is that we could write a reader process that
|
134
|
+
# doesn't use tupelo at all, but accesses the data stores directly (assuming
|
135
|
+
# we're using a client-server store like postgres or a concurrent key-value
|
136
|
+
# store like leveldb or lmdb). This non-tupelo process would only need to be
|
137
|
+
# aware of the RAMP semantics of pending and id fields.
|
131
138
|
child subscribe: ["x", "y"], passive: true do
|
132
139
|
log.progname = "reader"
|
133
140
|
read do |t|
|
data/example/tcp.rb
CHANGED
@@ -18,6 +18,11 @@
|
|
18
18
|
# Then run a client like this:
|
19
19
|
#
|
20
20
|
# bin/tup remote-copy-of-tcp.yaml
|
21
|
+
#
|
22
|
+
# If you have ssh set up, you don't even need to copy the file. Just reference
|
23
|
+
# it in the same way you would with scp:
|
24
|
+
#
|
25
|
+
# bin/tup host:tcp.yaml
|
21
26
|
|
22
27
|
require 'tupelo/app'
|
23
28
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# See tiny-tcp-service.rb
|
2
|
+
|
3
|
+
require 'tupelo/app'
|
4
|
+
|
5
|
+
Tupelo.application do
|
6
|
+
if owns_services
|
7
|
+
abort "service not running"
|
8
|
+
end
|
9
|
+
|
10
|
+
local do
|
11
|
+
x = rand(0..100); y = rand(0..100)
|
12
|
+
write [x, y]
|
13
|
+
log "%p + %p = %p" % take([x, y, Numeric])
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Run this with a specified filename:
|
2
|
+
#
|
3
|
+
# ruby tiny-tcp-service.rb srv.yaml
|
4
|
+
#
|
5
|
+
# Then you can run the client locally:
|
6
|
+
#
|
7
|
+
# ruby tiny-tcp-client.rb srv.yaml
|
8
|
+
#
|
9
|
+
# or from a remote host that can ssh back to the server
|
10
|
+
#
|
11
|
+
# ruby tiny-tcp-client.rb serverhost:path/to/srv.yaml
|
12
|
+
#
|
13
|
+
# (Use the --tunnel switch to send the data over ssh, as well.)
|
14
|
+
#
|
15
|
+
# You can also access the service using tup:
|
16
|
+
#
|
17
|
+
# tup srv.yaml
|
18
|
+
# >> w [12, 34]
|
19
|
+
# >> r [12, 34, nil]
|
20
|
+
# => [12, 34, 46]
|
21
|
+
|
22
|
+
require 'tupelo/app'
|
23
|
+
|
24
|
+
Tupelo.tcp_application do
|
25
|
+
puts "service started"
|
26
|
+
local do
|
27
|
+
loop do
|
28
|
+
x, y = take [Numeric, Numeric]
|
29
|
+
write [x, y, x+y]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/tupelo/app.rb
CHANGED
@@ -34,7 +34,7 @@ module Tupelo
|
|
34
34
|
|
35
35
|
opts[:trace] = argv.delete("--trace")
|
36
36
|
opts[:tunnel] = argv.delete("--tunnel")
|
37
|
-
|
37
|
+
|
38
38
|
[argv, opts]
|
39
39
|
end
|
40
40
|
|
@@ -54,7 +54,7 @@ module Tupelo
|
|
54
54
|
def self.application argv: nil,
|
55
55
|
services_file: nil, blob_type: nil,
|
56
56
|
seqd_addr: {}, cseqd_addr: {}, arcd_addr: {}, **opts, &block
|
57
|
-
|
57
|
+
|
58
58
|
unless argv
|
59
59
|
argv, h = parse_args(ARGV)
|
60
60
|
opts.merge! h
|
@@ -121,7 +121,7 @@ module Tupelo
|
|
121
121
|
|
122
122
|
app = AppBuilder.new(ez, argv: argv.dup,
|
123
123
|
owns_services: owns_services, tunnel_default: tunnel_default)
|
124
|
-
|
124
|
+
|
125
125
|
if enable_trace
|
126
126
|
require 'tupelo/app/trace'
|
127
127
|
app.start_trace
|
@@ -137,7 +137,7 @@ module Tupelo
|
|
137
137
|
|
138
138
|
if block
|
139
139
|
if block.arity == 0
|
140
|
-
app.instance_eval
|
140
|
+
app.instance_eval(&block)
|
141
141
|
else
|
142
142
|
yield app
|
143
143
|
end
|
data/lib/tupelo/app/builder.rb
CHANGED
@@ -53,7 +53,7 @@ module Tupelo
|
|
53
53
|
run_client client_class, **opts do |client|
|
54
54
|
if block
|
55
55
|
if block.arity == 0
|
56
|
-
client.instance_eval
|
56
|
+
client.instance_eval(&block)
|
57
57
|
else
|
58
58
|
yield client
|
59
59
|
end
|
@@ -76,7 +76,7 @@ module Tupelo
|
|
76
76
|
run_client client_class, **opts do |client|
|
77
77
|
if block
|
78
78
|
if block.arity == 0
|
79
|
-
client.instance_eval
|
79
|
+
client.instance_eval(&block)
|
80
80
|
else
|
81
81
|
yield client
|
82
82
|
end
|
data/lib/tupelo/app/irb-shell.rb
CHANGED
@@ -7,7 +7,7 @@ module IRB
|
|
7
7
|
def IRB.parse_opts
|
8
8
|
# Don't touch ARGV, which belongs to the app which called this module.
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def IRB.start_session(*args)
|
12
12
|
unless $irb
|
13
13
|
IRB.setup nil
|
@@ -34,7 +34,7 @@ module IRB
|
|
34
34
|
trap 'INT' do
|
35
35
|
$irb.signal_handle
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
custom_configuration if defined?(IRB.custom_configuration)
|
39
39
|
|
40
40
|
begin
|
@@ -44,7 +44,7 @@ module IRB
|
|
44
44
|
ensure
|
45
45
|
IRB.irb_at_exit
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
## might want to reset your app's interrupt handler here
|
49
49
|
end
|
50
50
|
end
|
data/lib/tupelo/archiver.rb
CHANGED
@@ -6,8 +6,6 @@ require 'funl/history-client'
|
|
6
6
|
## should manipulate tuples as strings (at least in msgpack/json cases) instead
|
7
7
|
## of objects -- use msgpack extension for #hash and #== on packed objects
|
8
8
|
|
9
|
-
class Tupelo::Archiver < Tupelo::Client; end
|
10
|
-
|
11
9
|
require 'tupelo/archiver/worker'
|
12
10
|
require 'tupelo/archiver/tuplestore' ## unless persistent?
|
13
11
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'funl/history-worker'
|
2
2
|
|
3
|
-
class Tupelo::Archiver
|
3
|
+
class Tupelo::Archiver < Tupelo::Client
|
4
4
|
class Worker < Tupelo::Client::Worker
|
5
5
|
include Funl::HistoryWorker
|
6
|
-
|
6
|
+
|
7
7
|
def initialize *args, **opts
|
8
|
-
super
|
8
|
+
super(*args)
|
9
9
|
@scheduled_actions = Hash.new {|h,k| h[k] = []}
|
10
10
|
@opts = opts
|
11
11
|
end
|
@@ -13,7 +13,7 @@ class Tupelo::Archiver
|
|
13
13
|
def tuplestore
|
14
14
|
@tuplestore ||= begin
|
15
15
|
if client.tuplestore.respond_to? :new
|
16
|
-
client.tuplestore.new
|
16
|
+
client.tuplestore.new(**@opts)
|
17
17
|
else
|
18
18
|
client.tuplestore
|
19
19
|
end
|
@@ -81,7 +81,7 @@ class Tupelo::Archiver
|
|
81
81
|
ensure
|
82
82
|
req.io.close
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
def at_tick tick, &action
|
86
86
|
@scheduled_actions[tick] << action
|
87
87
|
end
|
@@ -99,7 +99,7 @@ class Tupelo::Archiver
|
|
99
99
|
"send_tuplestore to #{stream.peer_name} " +
|
100
100
|
"at tick #{global_tick.inspect} " +
|
101
101
|
(sub_delta ? " with sub_delta #{sub_delta.inspect}" : "")}
|
102
|
-
|
102
|
+
|
103
103
|
stream << [global_tick]
|
104
104
|
|
105
105
|
## better: make use of sub_delta["subscribed_*"] to reduce what
|
data/lib/tupelo/client.rb
CHANGED
@@ -13,7 +13,7 @@ module Tupelo
|
|
13
13
|
attr_reader :tuplestore
|
14
14
|
|
15
15
|
def initialize(tuplestore: SimpleTupleStore, subscribe: :all, **opts)
|
16
|
-
super
|
16
|
+
super(**opts)
|
17
17
|
@tuplestore = tuplestore
|
18
18
|
@worker = make_worker
|
19
19
|
@initial_subscriptions = subscribe || []
|
@@ -57,7 +57,7 @@ module Tupelo
|
|
57
57
|
if args.empty?
|
58
58
|
super()
|
59
59
|
else
|
60
|
-
super().unknown
|
60
|
+
super().unknown(*args)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
data/lib/tupelo/client/reader.rb
CHANGED
@@ -85,7 +85,7 @@ class Tupelo::Client
|
|
85
85
|
false
|
86
86
|
end
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
def peek tuple
|
90
90
|
queue << tuple
|
91
91
|
once
|
@@ -102,10 +102,10 @@ class Tupelo::Client
|
|
102
102
|
"<#{self.class}: #{template.inspect}>"
|
103
103
|
end
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
class Waiter < WaiterBase
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
class Matcher < WaiterBase
|
110
110
|
attr_reader :all # this is only cosmetic -- see #inspect
|
111
111
|
|
@@ -34,10 +34,10 @@ class Tupelo::Client
|
|
34
34
|
})
|
35
35
|
end
|
36
36
|
|
37
|
-
def subspace tag
|
37
|
+
def subspace tag, wait: false
|
38
38
|
tag = tag.to_s
|
39
39
|
find_subspace_by_tag(tag) or begin
|
40
|
-
if subscribed_tags.include? tag
|
40
|
+
if wait or subscribed_tags.include? tag
|
41
41
|
read tupelo_meta_key => "subspace",
|
42
42
|
tag: tag,
|
43
43
|
template: nil,
|
@@ -23,7 +23,7 @@ class Tupelo::Client
|
|
23
23
|
|
24
24
|
val =
|
25
25
|
if block.arity == 0
|
26
|
-
t.instance_eval
|
26
|
+
t.instance_eval(&block)
|
27
27
|
else
|
28
28
|
yield t
|
29
29
|
end
|
@@ -39,7 +39,7 @@ class Tupelo::Client
|
|
39
39
|
ensure
|
40
40
|
t.cancel if t and t.open? and block_given?
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def abort
|
44
44
|
raise TransactionAbort
|
45
45
|
end
|
@@ -47,7 +47,7 @@ class Tupelo::Client
|
|
47
47
|
# returns an object whose #wait method waits for write to be ack-ed
|
48
48
|
def write_nowait *tuples
|
49
49
|
t = transaction
|
50
|
-
t.write
|
50
|
+
t.write(*tuples)
|
51
51
|
t.commit
|
52
52
|
end
|
53
53
|
alias write write_nowait
|
@@ -59,7 +59,7 @@ class Tupelo::Client
|
|
59
59
|
|
60
60
|
def pulse_nowait *tuples
|
61
61
|
t = transaction
|
62
|
-
t.pulse
|
62
|
+
t.pulse(*tuples)
|
63
63
|
t.commit
|
64
64
|
end
|
65
65
|
alias pulse pulse_nowait
|
@@ -88,7 +88,7 @@ class Tupelo::Client
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
class Transaction
|
93
93
|
attr_reader :client
|
94
94
|
attr_reader :worker
|
@@ -109,7 +109,7 @@ class Tupelo::Client
|
|
109
109
|
attr_reader :missing
|
110
110
|
attr_reader :tags
|
111
111
|
attr_reader :read_only
|
112
|
-
|
112
|
+
|
113
113
|
STATES = [
|
114
114
|
OPEN = :open, # initial state
|
115
115
|
CLOSED = :closed, # client thread changes open -> closed
|
@@ -118,7 +118,7 @@ class Tupelo::Client
|
|
118
118
|
DONE = :done, # worker thread changes pending -> done (terminal)
|
119
119
|
FAILED = :failed # worker thread changes pending -> failed (terminal)
|
120
120
|
]
|
121
|
-
|
121
|
+
|
122
122
|
STATES.each do |s|
|
123
123
|
class_eval %{
|
124
124
|
def #{s}?; @status == #{s.inspect}; end
|
@@ -151,7 +151,7 @@ class Tupelo::Client
|
|
151
151
|
@_take_nowait = nil
|
152
152
|
@_read_nowait = nil
|
153
153
|
@read_only = false
|
154
|
-
|
154
|
+
|
155
155
|
open!
|
156
156
|
|
157
157
|
if deadline
|
@@ -160,11 +160,11 @@ class Tupelo::Client
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
def client_id
|
165
165
|
client.client_id
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
def subspace tag
|
169
169
|
client.subspace tag
|
170
170
|
end
|
@@ -173,7 +173,7 @@ class Tupelo::Client
|
|
173
173
|
if args.empty?
|
174
174
|
@log
|
175
175
|
else
|
176
|
-
@log.unknown
|
176
|
+
@log.unknown(*args)
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
@@ -185,9 +185,9 @@ class Tupelo::Client
|
|
185
185
|
when done?
|
186
186
|
"at global_tick: #{global_tick}"
|
187
187
|
end
|
188
|
-
|
188
|
+
|
189
189
|
stat = [status, stat_extra].compact.join(" ")
|
190
|
-
|
190
|
+
|
191
191
|
ops = [ ["write", writes], ["pulse", pulses],
|
192
192
|
["take", take_templates], ["read", read_templates] ]
|
193
193
|
## exclude templates that were satisfied locally by writes
|
@@ -200,10 +200,10 @@ class Tupelo::Client
|
|
200
200
|
## show take/read tuples too?
|
201
201
|
## show current tick, if open or closed
|
202
202
|
## show nowait
|
203
|
-
|
203
|
+
|
204
204
|
"<#{self.class} #{stat} #{ops.join('; ')}>"
|
205
205
|
end
|
206
|
-
|
206
|
+
|
207
207
|
# :section: Client methods
|
208
208
|
|
209
209
|
def check_tuples tuples
|
@@ -233,7 +233,7 @@ class Tupelo::Client
|
|
233
233
|
# to convert symbols to strings (in case of msgpack or json)
|
234
234
|
nil
|
235
235
|
end
|
236
|
-
|
236
|
+
|
237
237
|
def pulse *tuples
|
238
238
|
check_open
|
239
239
|
check_tuples tuples
|
@@ -241,7 +241,7 @@ class Tupelo::Client
|
|
241
241
|
@pulses.concat tuples.map {|t| blobber.load(blobber.dump(t))}
|
242
242
|
nil
|
243
243
|
end
|
244
|
-
|
244
|
+
|
245
245
|
# raises TransactionFailure
|
246
246
|
def take template_spec
|
247
247
|
check_open
|
@@ -252,7 +252,7 @@ class Tupelo::Client
|
|
252
252
|
wait
|
253
253
|
return take_tuples_for_local.last
|
254
254
|
end
|
255
|
-
|
255
|
+
|
256
256
|
def take_nowait template_spec
|
257
257
|
check_open
|
258
258
|
template = worker.make_template(template_spec)
|
@@ -265,7 +265,7 @@ class Tupelo::Client
|
|
265
265
|
wait
|
266
266
|
return take_tuples_for_local[i]
|
267
267
|
end
|
268
|
-
|
268
|
+
|
269
269
|
# transaction applies only if template has a match
|
270
270
|
def read template_spec
|
271
271
|
if block_given?
|
@@ -328,7 +328,7 @@ class Tupelo::Client
|
|
328
328
|
def wait
|
329
329
|
return self if done?
|
330
330
|
raise exception if failed?
|
331
|
-
|
331
|
+
|
332
332
|
log.debug {"waiting for #{inspect}"}
|
333
333
|
@queue.pop
|
334
334
|
log.debug {"finished waiting for #{inspect}"}
|
@@ -348,7 +348,7 @@ class Tupelo::Client
|
|
348
348
|
wait
|
349
349
|
granted_tuples
|
350
350
|
end
|
351
|
-
|
351
|
+
|
352
352
|
class TransactionThread < Thread
|
353
353
|
def initialize t, *args
|
354
354
|
super(*args)
|
@@ -365,7 +365,7 @@ class Tupelo::Client
|
|
365
365
|
begin
|
366
366
|
val =
|
367
367
|
if block.arity == 0
|
368
|
-
instance_eval
|
368
|
+
instance_eval(&block)
|
369
369
|
else
|
370
370
|
yield self
|
371
371
|
end
|
@@ -381,7 +381,7 @@ class Tupelo::Client
|
|
381
381
|
end
|
382
382
|
|
383
383
|
# :section: Worker methods
|
384
|
-
|
384
|
+
|
385
385
|
def in_worker_thread?
|
386
386
|
worker.in_thread?
|
387
387
|
end
|
@@ -523,7 +523,7 @@ class Tupelo::Client
|
|
523
523
|
## redo the conversions etc
|
524
524
|
return true
|
525
525
|
end
|
526
|
-
|
526
|
+
|
527
527
|
def submit
|
528
528
|
raise TransactionStateError, "must be closed" unless closed?
|
529
529
|
raise unless in_worker_thread?
|
@@ -531,7 +531,7 @@ class Tupelo::Client
|
|
531
531
|
@local_tick = worker.send_transaction self
|
532
532
|
pending!
|
533
533
|
end
|
534
|
-
|
534
|
+
|
535
535
|
def done global_tick, granted_tuples
|
536
536
|
unless pending? or (closed? and read_only)
|
537
537
|
raise TransactionStateError, "must be pending or closed+read_only"
|
@@ -549,17 +549,17 @@ class Tupelo::Client
|
|
549
549
|
def fail missing
|
550
550
|
raise unless in_worker_thread?
|
551
551
|
raise if @global_tick or @exception
|
552
|
-
|
552
|
+
|
553
553
|
@missing = missing
|
554
554
|
@exception = TransactionFailure
|
555
555
|
failed!
|
556
556
|
@queue << false
|
557
557
|
end
|
558
|
-
|
558
|
+
|
559
559
|
def error ex
|
560
560
|
raise unless in_worker_thread?
|
561
561
|
raise if @global_tick or @exception
|
562
|
-
|
562
|
+
|
563
563
|
@exception = ex
|
564
564
|
failed!
|
565
565
|
@queue << false
|