tupelo 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bd2a467d93d42b9237dc027c9ee33160c7f44a3
4
- data.tar.gz: 16c3d47bc0acd033f1f8be8bc4578310edb3f653
3
+ metadata.gz: 74456cde00385b5340494724ee0affc7cf6e2534
4
+ data.tar.gz: 331f3970d1fd41a702ada650f5701616de24b184
5
5
  SHA512:
6
- metadata.gz: 1f20d07a716db5de35606c9500562863c64a5f3e74129336bfb9d52221b2751385d3d2c8a6ca873bd9841c403edafcc5911df776a143bf83a743d0d257af7ce6
7
- data.tar.gz: 40b77909cf54701fabfaf35d189dd15f9ebc8beb4bbfa8a6a55b2cc6ee1eb512eab682c5c26df375e94a939d1a018a1f463e1400ae9131412819ebd09f4c093c
6
+ metadata.gz: bcfe41b674e798ba15761f6740bc74a11963a793538a725ec393fefd4328eb9053e019d95c0f4701cb2ca680dc52c2d2e8dce48921be7cd68532c639b4c61d90
7
+ data.tar.gz: 82b13b6aa0675069946428033e5d032ca4418409c5901da00cac76cf139d7cc34afa428c4e666e42370b69241c797cabb55b375cfd34e5d8bd5bc83f2e6bf9a9
data/README.md CHANGED
@@ -105,7 +105,8 @@ Getting started
105
105
  ...
106
106
  end
107
107
 
108
- Note that a local match is still not a guarantee of `x_final == x_optimistic`. Another process may take `x_optimistic` first, and the take will be re-executed.
108
+ Note that a local match is still not a guarantee of `x_final == x_optimistic`. Another process may take `x_optimistic` first, and the take will be re-executed. (Think of #take_nowait as a way of saying "take a match, but don't bother trying if there is no match known at this time.")
109
+
109
110
  Perform a general transaction:
110
111
 
111
112
  result =
@@ -133,7 +134,7 @@ Getting started
133
134
 
134
135
  Note that all bin and example programs accept blob type (e.g., --msgpack, --json) on command line (it only needs to be specified for server -- the clients discover it). Also, all these programs accept log level on command line. The default is --warn. The --info level is a good way to get an idea of what is happening, without the verbosity of --debug.
135
136
 
136
- 6. Debugging: in addition to the --info switch on all bin and example programs, bin/tspy is also really useful. There is also the similar --trace switch that is available to all bin and example programs, for example:
137
+ 6. Debugging: in addition to the --info switch on all bin and example programs, bin/tspy is also really useful. There is also the similar --trace switch that is available to all bin and example programs. This switch diagnostic output for each transaction. For example:
137
138
 
138
139
  ```
139
140
  tick cid status operation
@@ -142,7 +143,7 @@ Getting started
142
143
  3 3 atomic take ["x", 1], ["y", 2]
143
144
  ```
144
145
 
145
- The `Tupelo.application` command, provided by `tupelo/app`, is the source of all these options and is available to your programs.
146
+ The `Tupelo.application` command, provided by `tupelo/app`, is the source of all these options and is available to your programs. It's a kind of lightweight process deployment and control framework; however it is not necessary to use tupelo.
146
147
 
147
148
 
148
149
  What is a tuplespace?
@@ -180,7 +181,7 @@ In other words, a tuple is a fairly general object, though this depends on the s
180
181
 
181
182
  * hashes
182
183
 
183
- It's kind of like a "JSON object", except that in the json blob case, the hash keys can only be strings. In the msgpack case, keys have no special limitations. In the case of the marshal and yaml modes, tuples can contain many other kinds of objects.
184
+ It's kind of like a "JSON object", except that, when using the json serializer, the hash keys can only be strings. In the msgpack case, keys have no special limitations. In the case of the marshal and yaml modes, tuples can contain many other kinds of objects.
184
185
 
185
186
  What is a template?
186
187
  -------------------
@@ -244,7 +245,7 @@ Transactions and optimistic concurrency
244
245
 
245
246
  Transactions combine operations into a group that take effect at the same instant in (logical) time, isolated from other transactions.
246
247
 
247
- However, it may take some time to prepare the transaction. This is true in terms of both real time (clock and process) and logical tiem (global sequence of operations). Preparing a transaction means finding tuples that match the criteria of the read and take operations. Finding tuples may require searching (locally) for tuples, or waiting for new tuples to be written by others. Also, the transaction may fail even after matching tuples are found (when another process takes tuples of interest). Then the transaction needs to be prepared again. Once prepared, transaction is sent to all clients, where it may either succeed (in all clients) or fail (for the same reason as before--someone else grabbed one of our tuples). If it fails, then the preparation can begin again. A transaction guarantees that, when it completes, all the operations were performed on the tuples at the same logical time. It does not guarantee that the world stands still while one process is inside the `transaction {...}` block.
248
+ However, it may take some time to prepare the transaction. This is true in terms of both real time (clock and process) and logical time (global sequence of operations). Preparing a transaction means finding tuples that match the criteria of the read and take operations. Finding tuples may require searching (locally) for tuples, or waiting for new tuples to be written by others. Also, the transaction may fail even after matching tuples are found (when another process takes tuples of interest). Then the transaction needs to be prepared again. Once prepared, transaction is sent to all clients, where it may either succeed (in all clients) or fail (for the same reason as before--someone else grabbed one of our tuples). If it fails, then the preparation begins again. A transaction guarantees that, when it completes, all the operations were performed on the tuples at the same logical time. It does not guarantee that the world stands still while one process is inside the `transaction {...}` block.
248
249
 
249
250
  Transactions are not just about batching up operations into a more efficient package (though you can do that with the #batch api). A transaction makes the combined operations execute atomically: the transaction finishes only when all of its operations can be successfully performed. Writes and pulses can always succeed, but takes and reads only succeed if the tuples exist.
250
251
 
@@ -378,6 +379,8 @@ To compare
378
379
 
379
380
  * pubsubs: kafka
380
381
 
382
+ * spark, storm
383
+
381
384
  Architecture
382
385
  ============
383
386
 
@@ -410,9 +413,9 @@ Protocol
410
413
 
411
414
  Nothing in the protocol specifies local searching or storage, or matching, or notification, or templating. That's all up to each client. The protocol only contains tuples and operations on them (take, write, pulse, read), combined into transactions.
412
415
 
413
- The protocol has two layers. The outer (message) layer is 6 fields, managed by the funl gem, using msgpack for serialization. All socket reads are non-blocking, so a slow sender will not block other activity in the system.
416
+ The protocol has two layers. The outer (message) layer is 6 fields, managed by the funl gem, using msgpack for serialization. All socket reads are non-blocking (using msgpack's stream mode), so a slow sender will not block other activity in the system.
414
417
 
415
- The inner (blob) layer manages one of those 6 field using msgpack (by default), marshal, json, or yaml. This layer contains the transaction operations. The blob is not unpacked by the server, only by clients.
418
+ One of those 6 fields is a data blob, containing the actual transaction and tuple information. The inner (blob) layer manages that field using msgpack (by default), marshal, json, or yaml. This layer contains the transaction operations. The blob is not unpacked by the server, only by clients.
416
419
 
417
420
  Each inner serialization method ("blobber") has its own advantages and drawbacks:
418
421
 
@@ -422,8 +425,6 @@ Each inner serialization method ("blobber") has its own advantages and drawbacks
422
425
 
423
426
  * msgpack and json (yajl) are both relatively efficient (in terms of packet size, as well as parse/emit time)
424
427
 
425
- * msgpack and json both support non-blocking (buffered) reads, which can avoid bottlenecks due to slow senders or bad networks.
426
-
427
428
  * msgpack and json support the least diversity of objects (just "JSON objects"), but msgpack also supports hash keys that are objects rather than just strings.
428
429
 
429
430
  For most purposes, msgpack is a good choice, so it is the default.
@@ -0,0 +1,27 @@
1
+ require 'tupelo/app/remote'
2
+
3
+ hosts = ARGV.shift or abort "usage: #$0 <ssh-hostname>,<ssh-hostname>,..."
4
+ hosts = hosts.split(",")
5
+
6
+ Tupelo.tcp_application do
7
+ hosts.each do |host|
8
+ remote host: host, passive: true, eval: %{
9
+ loop do
10
+ len = take([String])[0].size
11
+ write [len]
12
+ end
13
+ }
14
+ end
15
+
16
+ local do
17
+ input = [ ["We are going to"], ["calcula"], ["te the len"],
18
+ ["gth of this "], ["sentence."] ]
19
+ write *input
20
+ sum = 0
21
+ input.size.times do
22
+ sum += take([Numeric])[0]
23
+ end
24
+ log "sum = #{sum}, correct sum = #{input.flatten.join.size}"
25
+ sleep 2
26
+ end
27
+ end
data/example/remote.rb CHANGED
@@ -13,15 +13,20 @@ Tupelo.tcp_application do
13
13
  # only for examples and tests, not production.
14
14
  end
15
15
 
16
- remote host: host, eval: %{
16
+ remote host: host, log: true, eval: %{
17
17
  write host: `hostname`.chomp, mode: "eval", client: client_id
18
18
  }
19
19
  # rather than embed large chunks of code in the string, it's better to
20
20
  # load or require a file and pass self (which is a Client instance) to
21
21
  # a method in that file.
22
22
 
23
+ remote host: host, log: true, passive: true, eval: %{
24
+ write host: `hostname`.chomp, mode: "eval", client: client_id
25
+ sleep # since passive, app can stop this process
26
+ }
27
+
23
28
  local do
24
- 2.times do
29
+ 3.times do
25
30
  log take host: nil, mode: nil, client: nil
26
31
  end
27
32
  end
data/example/small.rb CHANGED
@@ -58,7 +58,7 @@ EasyServe.start(servers_file: "small-servers.yaml") do |ez|
58
58
  client.stop if client # gracefully exit the tuplespace management thread
59
59
  end
60
60
 
61
- ez.client :seqd, :cseqd, :arcd do |seqd, cseqd, arcd|
61
+ ez.child :seqd, :cseqd, :arcd do |seqd, cseqd, arcd|
62
62
  run_client seq: seqd, cseq: cseqd, arc: arcd, log: log do |client|
63
63
  client.write [2, 3, "frogs"]
64
64
  _, s = client.take ["animals", nil]
@@ -66,7 +66,7 @@ EasyServe.start(servers_file: "small-servers.yaml") do |ez|
66
66
  end
67
67
  end
68
68
 
69
- ez.client :seqd, :cseqd, :arcd do |seqd, cseqd, arcd|
69
+ ez.child :seqd, :cseqd, :arcd do |seqd, cseqd, arcd|
70
70
  run_client seq: seqd, cseq: cseqd, arc: arcd, log: log do |client|
71
71
  x, y, s = client.take [Numeric, Numeric, String]
72
72
  s2 = ([s] * (x + y)).join(" ")
@@ -23,14 +23,13 @@ module Tupelo
23
23
  def remote client_class = Client,
24
24
  client_lib: 'tupelo/client', host: nil, **opts
25
25
  require 'easy-serve/remote'
26
- raise if opts[:passive] ## not supported yet
27
26
  ## detach option so that remote process doesn't keep ssh connection
28
27
  snames = :seqd, :cseqd, :arcd
29
28
 
30
29
  if opts[:eval]
31
30
  ez.remote *snames, host: host, **opts, eval: %{
32
31
  require #{client_lib.inspect}
33
-
32
+
34
33
  seqd, cseqd, arcd = *conns
35
34
  client_class = Object.const_get(#{client_class.name.inspect})
36
35
 
data/lib/tupelo/app.rb CHANGED
@@ -46,7 +46,7 @@ module Tupelo
46
46
  # way. Then you do not have to manually interrupt the whole application when
47
47
  # the active processes are done. See examples.
48
48
  def child client_class = Client, passive: false, &block
49
- ez.client :seqd, :cseqd, :arcd, passive: passive do |seqd, cseqd, arcd|
49
+ ez.child :seqd, :cseqd, :arcd, passive: passive do |seqd, cseqd, arcd|
50
50
  run_client client_class,
51
51
  seq: seqd, cseq: cseqd, arc: arcd, log: log do |client|
52
52
  if block
@@ -1,3 +1,3 @@
1
1
  module Tupelo
2
- VERSION = "0.6"
2
+ VERSION = "0.7"
3
3
  end
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.6'
4
+ version: '0.7'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel VanderWerf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-27 00:00:00.000000000 Z
11
+ date: 2013-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: atdo
@@ -118,6 +118,7 @@ files:
118
118
  - example/hash-tuples.rb
119
119
  - example/pulse.rb
120
120
  - example/transaction-logic.rb
121
+ - example/remote-map-reduce.rb
121
122
  - example/map-reduce.rb
122
123
  - example/balance-xfer.rb
123
124
  - example/add-dsl.rb