tiq 0.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18d6c9646c99ec4a20f1836345ae4d40d2cd2c2e4b13b357f354d41e2a1549d0
4
- data.tar.gz: 7e9957b6a21ec8aec869b885b14e84b519a2276e070c2406b190f37338b2d287
3
+ metadata.gz: cbc51f573dbb6b1f9ebb839e651af7939309a34e9b7d7aebbb1aa1bba4821096
4
+ data.tar.gz: 1f46fdb48cb1700f9e4325d42b7fce28ddbeeb95144bd02765fee4ba39bda5d0
5
5
  SHA512:
6
- metadata.gz: 762d1f49e97bd77ffe029b6f7ebd2c5974b62a75462b2412f2cc930e08c83c58ad9284c774779f31635eeafc2f026de6a4facfb9dc0d6f89e5676f53b8a740c0
7
- data.tar.gz: e8b7897d8a18d9d932986edc09ac160d744247e31672a3ffc879f2c742528473ca4e554675369bba3fbc0e5f75bda135ee531c34d66fe0b433fd5c3efd1cb874
6
+ metadata.gz: 47f4390cb60bb482a7325a1cc6c24a52c5e70f1b70e38d9d799cfeedf4bdbc98867dba50a4537251cb27036bb4c390c8b0e16b0067c7b148e66b515e0ebf6c3f
7
+ data.tar.gz: 986a52a560c6ad59557409fafe80d053320c94449d477bf4c848e8f8120eaa4c20d666e2c12b139f22e4f58e953fe2c2f5af1a4efdf70367e326b18e7c508d05
data/LICENSE.md CHANGED
@@ -1,29 +1,375 @@
1
- # License
2
-
3
- Copyright (C) 2022, Ecsypno <https://ecsypno.com/>
4
- All rights reserved.
5
-
6
- Redistribution and use in source and binary forms, with or without modification,
7
- are permitted provided that the following conditions are met:
8
-
9
- * Redistributions of source code must retain the above copyright notice,
10
- this list of conditions and the following disclaimer.
11
-
12
- * Redistributions in binary form must reproduce the above copyright notice,
13
- this list of conditions and the following disclaimer in the documentation
14
- and/or other materials provided with the distribution.
15
-
16
- * Neither the name of the copyright holder nor the names of its contributors
17
- may be used to endorse or promote products derived from this software
18
- without specific prior written permission.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
24
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1
+ ```
2
+ Mozilla Public License Version 2.0
3
+ ==================================
4
+
5
+ 1. Definitions
6
+ --------------
7
+
8
+ 1.1. "Contributor"
9
+ means each individual or legal entity that creates, contributes to
10
+ the creation of, or owns Covered Software.
11
+
12
+ 1.2. "Contributor Version"
13
+ means the combination of the Contributions of others (if any) used
14
+ by a Contributor and that particular Contributor's Contribution.
15
+
16
+ 1.3. "Contribution"
17
+ means Covered Software of a particular Contributor.
18
+
19
+ 1.4. "Covered Software"
20
+ means Source Code Form to which the initial Contributor has attached
21
+ the notice in Exhibit A, the Executable Form of such Source Code
22
+ Form, and Modifications of such Source Code Form, in each case
23
+ including portions thereof.
24
+
25
+ 1.5. "Incompatible With Secondary Licenses"
26
+ means
27
+
28
+ (a) that the initial Contributor has attached the notice described
29
+ in Exhibit B to the Covered Software; or
30
+
31
+ (b) that the Covered Software was made available under the terms of
32
+ version 1.1 or earlier of the License, but not also under the
33
+ terms of a Secondary License.
34
+
35
+ 1.6. "Executable Form"
36
+ means any form of the work other than Source Code Form.
37
+
38
+ 1.7. "Larger Work"
39
+ means a work that combines Covered Software with other material, in
40
+ a separate file or files, that is not Covered Software.
41
+
42
+ 1.8. "License"
43
+ means this document.
44
+
45
+ 1.9. "Licensable"
46
+ means having the right to grant, to the maximum extent possible,
47
+ whether at the time of the initial grant or subsequently, any and
48
+ all of the rights conveyed by this License.
49
+
50
+ 1.10. "Modifications"
51
+ means any of the following:
52
+
53
+ (a) any file in Source Code Form that results from an addition to,
54
+ deletion from, or modification of the contents of Covered
55
+ Software; or
56
+
57
+ (b) any new file in Source Code Form that contains any Covered
58
+ Software.
59
+
60
+ 1.11. "Patent Claims" of a Contributor
61
+ means any patent claim(s), including without limitation, method,
62
+ process, and apparatus claims, in any patent Licensable by such
63
+ Contributor that would be infringed, but for the grant of the
64
+ License, by the making, using, selling, offering for sale, having
65
+ made, import, or transfer of either its Contributions or its
66
+ Contributor Version.
67
+
68
+ 1.12. "Secondary License"
69
+ means either the GNU General Public License, Version 2.0, the GNU
70
+ Lesser General Public License, Version 2.1, the GNU Affero General
71
+ Public License, Version 3.0, or any later versions of those
72
+ licenses.
73
+
74
+ 1.13. "Source Code Form"
75
+ means the form of the work preferred for making modifications.
76
+
77
+ 1.14. "You" (or "Your")
78
+ means an individual or a legal entity exercising rights under this
79
+ License. For legal entities, "You" includes any entity that
80
+ controls, is controlled by, or is under common control with You. For
81
+ purposes of this definition, "control" means (a) the power, direct
82
+ or indirect, to cause the direction or management of such entity,
83
+ whether by contract or otherwise, or (b) ownership of more than
84
+ fifty percent (50%) of the outstanding shares or beneficial
85
+ ownership of such entity.
86
+
87
+ 2. License Grants and Conditions
88
+ --------------------------------
89
+
90
+ 2.1. Grants
91
+
92
+ Each Contributor hereby grants You a world-wide, royalty-free,
93
+ non-exclusive license:
94
+
95
+ (a) under intellectual property rights (other than patent or trademark)
96
+ Licensable by such Contributor to use, reproduce, make available,
97
+ modify, display, perform, distribute, and otherwise exploit its
98
+ Contributions, either on an unmodified basis, with Modifications, or
99
+ as part of a Larger Work; and
100
+
101
+ (b) under Patent Claims of such Contributor to make, use, sell, offer
102
+ for sale, have made, import, and otherwise transfer either its
103
+ Contributions or its Contributor Version.
104
+
105
+ 2.2. Effective Date
106
+
107
+ The licenses granted in Section 2.1 with respect to any Contribution
108
+ become effective for each Contribution on the date the Contributor first
109
+ distributes such Contribution.
110
+
111
+ 2.3. Limitations on Grant Scope
112
+
113
+ The licenses granted in this Section 2 are the only rights granted under
114
+ this License. No additional rights or licenses will be implied from the
115
+ distribution or licensing of Covered Software under this License.
116
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
117
+ Contributor:
118
+
119
+ (a) for any code that a Contributor has removed from Covered Software;
120
+ or
121
+
122
+ (b) for infringements caused by: (i) Your and any other third party's
123
+ modifications of Covered Software, or (ii) the combination of its
124
+ Contributions with other software (except as part of its Contributor
125
+ Version); or
126
+
127
+ (c) under Patent Claims infringed by Covered Software in the absence of
128
+ its Contributions.
129
+
130
+ This License does not grant any rights in the trademarks, service marks,
131
+ or logos of any Contributor (except as may be necessary to comply with
132
+ the notice requirements in Section 3.4).
133
+
134
+ 2.4. Subsequent Licenses
135
+
136
+ No Contributor makes additional grants as a result of Your choice to
137
+ distribute the Covered Software under a subsequent version of this
138
+ License (see Section 10.2) or under the terms of a Secondary License (if
139
+ permitted under the terms of Section 3.3).
140
+
141
+ 2.5. Representation
142
+
143
+ Each Contributor represents that the Contributor believes its
144
+ Contributions are its original creation(s) or it has sufficient rights
145
+ to grant the rights to its Contributions conveyed by this License.
146
+
147
+ 2.6. Fair Use
148
+
149
+ This License is not intended to limit any rights You have under
150
+ applicable copyright doctrines of fair use, fair dealing, or other
151
+ equivalents.
152
+
153
+ 2.7. Conditions
154
+
155
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
156
+ in Section 2.1.
157
+
158
+ 3. Responsibilities
159
+ -------------------
160
+
161
+ 3.1. Distribution of Source Form
162
+
163
+ All distribution of Covered Software in Source Code Form, including any
164
+ Modifications that You create or to which You contribute, must be under
165
+ the terms of this License. You must inform recipients that the Source
166
+ Code Form of the Covered Software is governed by the terms of this
167
+ License, and how they can obtain a copy of this License. You may not
168
+ attempt to alter or restrict the recipients' rights in the Source Code
169
+ Form.
170
+
171
+ 3.2. Distribution of Executable Form
172
+
173
+ If You distribute Covered Software in Executable Form then:
174
+
175
+ (a) such Covered Software must also be made available in Source Code
176
+ Form, as described in Section 3.1, and You must inform recipients of
177
+ the Executable Form how they can obtain a copy of such Source Code
178
+ Form by reasonable means in a timely manner, at a charge no more
179
+ than the cost of distribution to the recipient; and
180
+
181
+ (b) You may distribute such Executable Form under the terms of this
182
+ License, or sublicense it under different terms, provided that the
183
+ license for the Executable Form does not attempt to limit or alter
184
+ the recipients' rights in the Source Code Form under this License.
185
+
186
+ 3.3. Distribution of a Larger Work
187
+
188
+ You may create and distribute a Larger Work under terms of Your choice,
189
+ provided that You also comply with the requirements of this License for
190
+ the Covered Software. If the Larger Work is a combination of Covered
191
+ Software with a work governed by one or more Secondary Licenses, and the
192
+ Covered Software is not Incompatible With Secondary Licenses, this
193
+ License permits You to additionally distribute such Covered Software
194
+ under the terms of such Secondary License(s), so that the recipient of
195
+ the Larger Work may, at their option, further distribute the Covered
196
+ Software under the terms of either this License or such Secondary
197
+ License(s).
198
+
199
+ 3.4. Notices
200
+
201
+ You may not remove or alter the substance of any license notices
202
+ (including copyright notices, patent notices, disclaimers of warranty,
203
+ or limitations of liability) contained within the Source Code Form of
204
+ the Covered Software, except that You may alter any license notices to
205
+ the extent required to remedy known factual inaccuracies.
206
+
207
+ 3.5. Application of Additional Terms
208
+
209
+ You may choose to offer, and to charge a fee for, warranty, support,
210
+ indemnity or liability obligations to one or more recipients of Covered
211
+ Software. However, You may do so only on Your own behalf, and not on
212
+ behalf of any Contributor. You must make it absolutely clear that any
213
+ such warranty, support, indemnity, or liability obligation is offered by
214
+ You alone, and You hereby agree to indemnify every Contributor for any
215
+ liability incurred by such Contributor as a result of warranty, support,
216
+ indemnity or liability terms You offer. You may include additional
217
+ disclaimers of warranty and limitations of liability specific to any
218
+ jurisdiction.
219
+
220
+ 4. Inability to Comply Due to Statute or Regulation
221
+ ---------------------------------------------------
222
+
223
+ If it is impossible for You to comply with any of the terms of this
224
+ License with respect to some or all of the Covered Software due to
225
+ statute, judicial order, or regulation then You must: (a) comply with
226
+ the terms of this License to the maximum extent possible; and (b)
227
+ describe the limitations and the code they affect. Such description must
228
+ be placed in a text file included with all distributions of the Covered
229
+ Software under this License. Except to the extent prohibited by statute
230
+ or regulation, such description must be sufficiently detailed for a
231
+ recipient of ordinary skill to be able to understand it.
232
+
233
+ 5. Termination
234
+ --------------
235
+
236
+ 5.1. The rights granted under this License will terminate automatically
237
+ if You fail to comply with any of its terms. However, if You become
238
+ compliant, then the rights granted under this License from a particular
239
+ Contributor are reinstated (a) provisionally, unless and until such
240
+ Contributor explicitly and finally terminates Your grants, and (b) on an
241
+ ongoing basis, if such Contributor fails to notify You of the
242
+ non-compliance by some reasonable means prior to 60 days after You have
243
+ come back into compliance. Moreover, Your grants from a particular
244
+ Contributor are reinstated on an ongoing basis if such Contributor
245
+ notifies You of the non-compliance by some reasonable means, this is the
246
+ first time You have received notice of non-compliance with this License
247
+ from such Contributor, and You become compliant prior to 30 days after
248
+ Your receipt of the notice.
249
+
250
+ 5.2. If You initiate litigation against any entity by asserting a patent
251
+ infringement claim (excluding declaratory judgment actions,
252
+ counter-claims, and cross-claims) alleging that a Contributor Version
253
+ directly or indirectly infringes any patent, then the rights granted to
254
+ You by any and all Contributors for the Covered Software under Section
255
+ 2.1 of this License shall terminate.
256
+
257
+ 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
258
+ end user license agreements (excluding distributors and resellers) which
259
+ have been validly granted by You or Your distributors under this License
260
+ prior to termination shall survive termination.
261
+
262
+ ************************************************************************
263
+ * *
264
+ * 6. Disclaimer of Warranty *
265
+ * ------------------------- *
266
+ * *
267
+ * Covered Software is provided under this License on an "as is" *
268
+ * basis, without warranty of any kind, either expressed, implied, or *
269
+ * statutory, including, without limitation, warranties that the *
270
+ * Covered Software is free of defects, merchantable, fit for a *
271
+ * particular purpose or non-infringing. The entire risk as to the *
272
+ * quality and performance of the Covered Software is with You. *
273
+ * Should any Covered Software prove defective in any respect, You *
274
+ * (not any Contributor) assume the cost of any necessary servicing, *
275
+ * repair, or correction. This disclaimer of warranty constitutes an *
276
+ * essential part of this License. No use of any Covered Software is *
277
+ * authorized under this License except under this disclaimer. *
278
+ * *
279
+ ************************************************************************
280
+
281
+ ************************************************************************
282
+ * *
283
+ * 7. Limitation of Liability *
284
+ * -------------------------- *
285
+ * *
286
+ * Under no circumstances and under no legal theory, whether tort *
287
+ * (including negligence), contract, or otherwise, shall any *
288
+ * Contributor, or anyone who distributes Covered Software as *
289
+ * permitted above, be liable to You for any direct, indirect, *
290
+ * special, incidental, or consequential damages of any character *
291
+ * including, without limitation, damages for lost profits, loss of *
292
+ * goodwill, work stoppage, computer failure or malfunction, or any *
293
+ * and all other commercial damages or losses, even if such party *
294
+ * shall have been informed of the possibility of such damages. This *
295
+ * limitation of liability shall not apply to liability for death or *
296
+ * personal injury resulting from such party's negligence to the *
297
+ * extent applicable law prohibits such limitation. Some *
298
+ * jurisdictions do not allow the exclusion or limitation of *
299
+ * incidental or consequential damages, so this exclusion and *
300
+ * limitation may not apply to You. *
301
+ * *
302
+ ************************************************************************
303
+
304
+ 8. Litigation
305
+ -------------
306
+
307
+ Any litigation relating to this License may be brought only in the
308
+ courts of a jurisdiction where the defendant maintains its principal
309
+ place of business and such litigation shall be governed by laws of that
310
+ jurisdiction, without reference to its conflict-of-law provisions.
311
+ Nothing in this Section shall prevent a party's ability to bring
312
+ cross-claims or counter-claims.
313
+
314
+ 9. Miscellaneous
315
+ ----------------
316
+
317
+ This License represents the complete agreement concerning the subject
318
+ matter hereof. If any provision of this License is held to be
319
+ unenforceable, such provision shall be reformed only to the extent
320
+ necessary to make it enforceable. Any law or regulation which provides
321
+ that the language of a contract shall be construed against the drafter
322
+ shall not be used to construe this License against a Contributor.
323
+
324
+ 10. Versions of the License
325
+ ---------------------------
326
+
327
+ 10.1. New Versions
328
+
329
+ Mozilla Foundation is the license steward. Except as provided in Section
330
+ 10.3, no one other than the license steward has the right to modify or
331
+ publish new versions of this License. Each version will be given a
332
+ distinguishing version number.
333
+
334
+ 10.2. Effect of New Versions
335
+
336
+ You may distribute the Covered Software under the terms of the version
337
+ of the License under which You originally received the Covered Software,
338
+ or under the terms of any subsequent version published by the license
339
+ steward.
340
+
341
+ 10.3. Modified Versions
342
+
343
+ If you create software not governed by this License, and you want to
344
+ create a new license for such software, you may create and use a
345
+ modified version of this License if you rename the license and remove
346
+ any references to the name of the license steward (except to note that
347
+ such modified license differs from this License).
348
+
349
+ 10.4. Distributing Source Code Form that is Incompatible With Secondary
350
+ Licenses
351
+
352
+ If You choose to distribute Source Code Form that is Incompatible With
353
+ Secondary Licenses under the terms of this version of the License, the
354
+ notice described in Exhibit B of this License must be attached.
355
+
356
+ Exhibit A - Source Code Form License Notice
357
+ -------------------------------------------
358
+
359
+ This Source Code Form is subject to the terms of the Mozilla Public
360
+ License, v. 2.0. If a copy of the MPL was not distributed with this
361
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
362
+
363
+ If it is not possible or desirable to put the notice in a particular
364
+ file, then You may include the notice in a location (such as a LICENSE
365
+ file in a relevant directory) where a recipient would be likely to look
366
+ for such a notice.
367
+
368
+ You may add additional accurate notices of copyright ownership.
369
+
370
+ Exhibit B - "Incompatible With Secondary Licenses" Notice
371
+ ---------------------------------------------------------
372
+
373
+ This Source Code Form is "Incompatible With Secondary Licenses", as
374
+ defined by the Mozilla Public License, v. 2.0.
375
+ ```
data/README.md CHANGED
@@ -19,19 +19,10 @@
19
19
  </tr>
20
20
  <tr>
21
21
  <th>License</th>
22
- <td><a href="file.LICENSE.html">3-clause BSD</a></td>
22
+ <td><a href="file.LICENSE.html">MPL v2</a></td>
23
23
  </tr>
24
24
  </table>
25
25
 
26
- ## Quadron Overall
27
-
28
- * [Cuboid](https://github.com/qadron/cuboid) -- Cluster partitioning.
29
- * -> **[Tiq](https://github.com/qadron/tiq)** -- Clustering solution.
30
- * [Toq](https://github.com/qadron/toq) -- RPC handling.
31
- * [Ratkr](https://github.com/qadron/raktr) -- Network connection handling.
32
-
33
- Also be sure to check-out [dSel](https://github.com/qadron/dsel) for spiffy DSL generation.
34
-
35
26
  ## Synopsis
36
27
 
37
28
  Tiq is a simple and lightweight clustering solution.
@@ -53,7 +44,7 @@ and instantiate it with a URL to bind to.
53
44
  cass MyNode < Tiq::Node
54
45
  end
55
46
 
56
- node = MyNode.new( url: "localhost:9999" )
47
+ node = MyNode.new( url: "localhost:9999" ).start
57
48
  ```
58
49
 
59
50
  ### Cluster
@@ -67,7 +58,7 @@ Any existing _Node_ would do.
67
58
  class MySecondNode < Tiq::Node
68
59
  end
69
60
 
70
- node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' )
61
+ node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' ).start
71
62
  ```
72
63
 
73
64
  ### Client
@@ -75,7 +66,7 @@ node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' )
75
66
  `Tiq::Client` offers a _Client_ to enable _Node_/User communications.
76
67
 
77
68
  ```ruby
78
- client = MyClient.new( "localhost:9999" )
69
+ client = MyClient.new( "localhost:9999" ).start
79
70
 
80
71
  # Issue calls on the server side and get us the responses.
81
72
  # Client will return `true`.
@@ -104,18 +95,17 @@ class MyChannelNode < Tiq::Node
104
95
  end
105
96
 
106
97
  # Set up initial Node, the start of the cluster.
107
- node_1 = MyNode.new( url: "localhost:9999" )
108
- node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' )
109
- channel = MyChannelNode.new( url: "localhost:9997", peer: 'localhost:9999' ).data
98
+ node_1 = MyNode.new( url: "localhost:9999" ).start
99
+ node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' ).start
100
+ channel = MyChannelNode.new( url: "localhost:9997", peer: 'localhost:9999' ).start.channel
110
101
  sleep 1
111
102
 
112
103
  channel.on_set :my_signal do |value|
113
104
  p "#{:on_set} - #{value}"
114
105
  end
115
106
 
116
- node_1.data.set :my_signal, 'tada!'
107
+ node_1.channel.set :my_signal, 'tada!'
117
108
  sleep 1
118
-
119
109
  ```
120
110
 
121
111
  ### Add-ons
@@ -129,7 +119,7 @@ class MyNode < Tiq::Node
129
119
  end
130
120
 
131
121
  # Set up initial Node.
132
- node_1 = MyNode.new( url: "localhost:9999" )
122
+ node_1 = MyNode.new( url: "localhost:9999" ).start
133
123
 
134
124
  # Add a service to the node, called :poll.
135
125
  Tiq::Addon::Attach node_1, :poll do |arguments = nil|
@@ -137,12 +127,14 @@ Tiq::Addon::Attach node_1, :poll do |arguments = nil|
137
127
  end
138
128
 
139
129
  # Interact with the service via a Client.
140
- Tiq::Addon "localhost:9999", :poll, 'ping' do
130
+ Tiq::Addon "localhost:9999", :poll, 'ping' do |r|
141
131
  puts "CLIENT: #{r}"
142
132
  end
133
+
134
+ sleep 1
143
135
  ```
144
136
 
145
- ### Data
137
+ ### Channel Shared Data
146
138
 
147
139
  Data can be shared across _Nodes_ by means of broadcasting upon
148
140
  change - optional.
@@ -155,18 +147,34 @@ class MySecondNode < Tiq::Node
155
147
  end
156
148
 
157
149
  # Set up initial Node, the start of the cluster.
158
- node_1 = MyNode.new( url: "localhost:9999" )
159
- node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' )
150
+ node_1 = MyNode.new( url: "localhost:9999" ).start
151
+ node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' ).start
160
152
 
161
153
  sleep 1
162
154
 
163
- node_2.data.on_set :my_signal do |value|
155
+ node_2.channel.on_set :my_signal do |value|
164
156
  p "#{:on_set} - #{value}"
165
157
  end
166
158
 
167
- node_1.data.set :my_signal, 'tada!'
159
+ node_1.channel.set :my_signal, 'tada!'
160
+ sleep 1
161
+ ```
162
+
163
+ #### Custom groups
164
+
165
+ ```ruby
166
+ require 'tiq'
167
+
168
+ n1 = Tiq::Node.new( url: "localhost:9999" ).start
169
+ n2 = Tiq::Node.new( url: "localhost:9998", peer: 'localhost:9999' ).start
170
+
171
+ # Add as many groups/channels/shared-data structures as you want.
172
+ n1.create_channel 'agents'
173
+
174
+ n1.agents.set :a1, 99
168
175
  sleep 1
169
176
 
177
+ p n2.agents.get :a1
170
178
  ```
171
179
 
172
180
  ## Installation
data/lib/tiq/client.rb CHANGED
@@ -5,12 +5,14 @@ module Tiq
5
5
  class Client < Toq::Client
6
6
 
7
7
  def initialize( url, options = {} )
8
+ @handler = (options[:handler] || 'node').to_s
9
+
8
10
  host, port = url.split( ':' )
9
11
  super( options.merge( host: host, port: port.to_i ) )
10
12
  end
11
13
 
12
14
  def method_missing( method, *args, &block )
13
- call( "node.#{method}", *args, &block )
15
+ call( "#{@handler}.#{method}", *args, &block )
14
16
  end
15
17
 
16
18
  end
@@ -23,13 +23,13 @@ class Node
23
23
  class Addon
24
24
 
25
25
  attr_reader :node
26
- attr_reader :data
26
+ attr_reader :channel
27
27
  attr_reader :options
28
28
 
29
29
  def initialize( node, payload, options = {} )
30
30
  @node = node
31
31
  @options = options
32
- @data = @node.data
32
+ @channel = @node.channel
33
33
  @payload = payload
34
34
  end
35
35
 
@@ -1,16 +1,17 @@
1
1
  module Tiq
2
2
  class Node
3
- class Data
3
+ class Channel
4
4
 
5
5
  CONCURRENCY = 20
6
6
 
7
- def initialize( node )
7
+ def initialize( node, options = {} )
8
8
  @hash = {}
9
9
 
10
10
  @on_set_cb = {}
11
11
  @on_delete_cb = {}
12
12
 
13
- @node = node
13
+ @handler = (options[:handler] || 'channel').to_s
14
+ @node = node
14
15
  end
15
16
 
16
17
  def update( data )
@@ -66,7 +67,7 @@ class Data
66
67
  nil
67
68
  end
68
69
 
69
- def on_set( k, &block )
70
+ def on_set( k = nil, &block )
70
71
  # p "#{@node} on_set #{k} 0 #{block}"
71
72
  (@on_set_cb[sanitize_key( k )] ||= []) << block
72
73
  nil
@@ -86,9 +87,14 @@ class Data
86
87
  def call_on_set( k, v )
87
88
  k = sanitize_key( k )
88
89
 
89
- # p "#{@node} call_on_set #{k} 2"
90
- # p @on_set_cb
91
- # p "--- PEERS #{@node.peers}"
90
+ # Catch-all!
91
+ if @on_set_cb['']
92
+ @on_set_cb.each do |_, cbs|
93
+ cbs.each do |cb|
94
+ cb.call k, v
95
+ end
96
+ end
97
+ end
92
98
 
93
99
  if @on_set_cb[k]
94
100
  @on_set_cb[k].each do |cb|
@@ -103,6 +109,15 @@ class Data
103
109
  k = sanitize_key( k )
104
110
  return if !@on_delete_cb[k]
105
111
 
112
+ # Catch-all!
113
+ if @on_delete_cb['']
114
+ @on_delete_cb.each do |k, cbs|
115
+ cbs.each do |cb|
116
+ cb.call k, v
117
+ end
118
+ end
119
+ end
120
+
106
121
  @on_delete_cb[k].each do |cb|
107
122
  cb.call k
108
123
  end
@@ -119,7 +134,7 @@ class Data
119
134
 
120
135
  def connect_to_peer( url, options = {} )
121
136
  @rpc_clients ||= {}
122
- @rpc_clients[url] ||= Tiq::Channel.new( url, options )
137
+ @rpc_clients[url] ||= Tiq::Client.new( url, options.merge( handler: @handler ) )
123
138
  end
124
139
 
125
140
  def sanitize_key( k )
data/lib/tiq/node.rb CHANGED
@@ -1,18 +1,41 @@
1
1
  require 'set'
2
- require_relative 'node/data'
2
+ require 'yaml'
3
+ require_relative 'node/channel'
3
4
  require_relative 'node/addon'
4
- require_relative 'channel'
5
5
  require_relative 'client'
6
6
 
7
7
  module Tiq
8
8
 
9
9
  class Node
10
10
 
11
+ class <<self
12
+
13
+ def when_ready( url, &block )
14
+ client = Client.new( url, client_max_retries: 0, connection_pool_size: 1 )
15
+ r = Raktr.new
16
+ r.run_in_thread
17
+ r.delay( 0.1 ) do |task|
18
+ client.alive? do |r|
19
+ if r.rpc_exception?
20
+ r.delay( 0.1, &task )
21
+ next
22
+ end
23
+
24
+ client.close
25
+
26
+ block.call
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+
11
33
  INTERVAL_PING = 5
12
34
 
13
- attr_reader :data
14
- attr_reader :services
35
+ attr_reader :url
36
+ attr_reader :channel
15
37
  attr_reader :reactor
38
+ attr_reader :server
16
39
 
17
40
  # Initializes the node by:
18
41
  #
@@ -33,7 +56,11 @@ class Node
33
56
  @addons = {}
34
57
  @nodes_info_cache = []
35
58
 
36
- host, port = @url.split( ':' )
59
+ host = port = nil
60
+ if @url
61
+ host, port = @url.split( ':' )
62
+ end
63
+
37
64
  options[:host] ||= host || 'localhost'
38
65
  options[:port] ||= port || 9999
39
66
 
@@ -47,8 +74,10 @@ class Node
47
74
 
48
75
  @reactor.run_in_thread if !@reactor.running?
49
76
 
50
- @data = Data.new( self )
51
- @server.add_handler( 'data', @data )
77
+ @channel = Tiq::Node::Channel.new( self, handler: 'channel' )
78
+ @server.add_handler( 'channel', @channel )
79
+
80
+ @channels = {}
52
81
 
53
82
  @reactor.on_error do |_, e|
54
83
  $stderr.puts "Reactor: #{e}"
@@ -86,7 +115,11 @@ class Node
86
115
 
87
116
  announce @url
88
117
  rescue => e
118
+ p grid_peers
89
119
  p e
120
+ e.backtrace.each do |l|
121
+ p l
122
+ end
90
123
  end
91
124
  end
92
125
  end
@@ -94,20 +127,20 @@ class Node
94
127
  $stdout.puts 'Node ready.'
95
128
 
96
129
  log_updated_peers
97
-
98
- run
99
130
  end
100
131
 
101
132
  def attach_addon( name, service, options = {} )
102
- if @addons[name.to_s]
133
+ name = name.to_s
134
+ if @addons[name]
103
135
  fail "Add-on already registered with name: #{name}"
104
136
  end
105
- @addons[name.to_s] = Node::Addon.new( self, service, options )
137
+ @addons[name] = Node::Addon.new( self, service, options )
106
138
  nil
107
139
  end
108
140
 
109
141
  def call_addon( name, *arguments )
110
- if !@addons[name.to_s]
142
+ name = name.to_s
143
+ if !@addons[name]
111
144
  fail "Add-on not attached with name: #{name}"
112
145
  end
113
146
 
@@ -119,13 +152,52 @@ class Node
119
152
  end
120
153
 
121
154
  def dettach_addon( name )
122
- if !@addons[name.to_s]
155
+ name = name.to_s
156
+ if !@addons[name]
123
157
  fail "Add-on not attached with name: #{name}"
124
158
  end
125
159
 
126
160
  @addons.delete name
127
161
  end
128
162
 
163
+ def create_channel( name, broadcast = true, &block )
164
+ name = name.to_s
165
+ @channels[name] = Tiq::Node::Data.new( self, handler: name )
166
+ @server.add_handler( name, @channels[name] )
167
+
168
+ self.class.define_method name do
169
+ @channels[name]
170
+ end
171
+
172
+ if !broadcast
173
+ block.call
174
+ return
175
+ end
176
+
177
+ each = proc { |peer, iterator|
178
+ begin
179
+ connect_to_peer( peer ).create_channel( name, false ) { |_, i2| iterator.next; i2.next }
180
+ rescue => e
181
+ p e
182
+ end
183
+ }
184
+ @reactor.create_iterator( @peers, 20 ).each( each )
185
+ nil
186
+ rescue => e
187
+ p e
188
+ e.backtrace.each do |l|
189
+ p l
190
+ end
191
+ end
192
+
193
+ def remove_channel( name )
194
+ @channels.delete name.to_s
195
+ end
196
+
197
+ def channels
198
+ @channels.keys
199
+ end
200
+
129
201
  # @return [Boolean]
130
202
  # `true` if grid member, `false` otherwise.
131
203
  def grid_member?
@@ -133,7 +205,7 @@ class Node
133
205
  end
134
206
 
135
207
  def unplug
136
- @server.create_iterator( @peers, 20 ).each do |peer, iterator|
208
+ @reactor.create_iterator( @peers, 20 ).each do |peer, iterator|
137
209
  connect_to_peer( peer ).remove_peer( @url ) { iterator.next }
138
210
  end
139
211
 
@@ -151,14 +223,14 @@ class Node
151
223
  $stdout.puts "Adding peer: #{node_url}"
152
224
  @peers << node_url
153
225
 
154
- connect_to_peer( node_url ){ update_data( @data.to_h ) }
226
+ connect_to_peer( node_url ){ update_channel( @channel.to_h ) }
155
227
 
156
228
  log_updated_peers
157
229
  true
158
230
  end
159
231
 
160
- def update_data( data )
161
- @data.update( data )
232
+ def update_channel( channel )
233
+ @channel.update( channel )
162
234
  nil
163
235
  end
164
236
 
@@ -225,9 +297,16 @@ class Node
225
297
  true
226
298
  end
227
299
 
228
- def run
300
+ def start
301
+ # @server.reactor.ensure_reactor_running
229
302
  $stdout.puts 'Running'
230
303
  @server.start
304
+
305
+ q = Queue.new
306
+ self.class.when_ready( @url) { q << Client.new( @url ) }
307
+ q.pop
308
+
309
+ self
231
310
  rescue => e
232
311
  $stderr.puts e
233
312
  $stderr.puts "Could not start server"
@@ -0,0 +1,3 @@
1
+ module Tiq
2
+ VERSION = '0.2.1'
3
+ end
data/lib/tiq.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require 'msgpack'
2
2
  require_relative 'tiq/node'
3
3
  require_relative 'tiq/client'
4
- require_relative 'tiq/channel'
4
+ require_relative 'tiq/node/channel'
5
5
 
6
6
  module Tiq
7
- VERSION = '0.2'
8
7
  end
@@ -5,8 +5,9 @@ describe 'Tiq::Node::Addon' do
5
5
  let( :peer ) { @peer ||= Tiq::Node.new( url: 'localhost:9998', peer: 'localhost:9999' ) }
6
6
 
7
7
  before( :each ) do
8
- node
9
- peer
8
+ node.start
9
+ sleep 1
10
+ peer.start
10
11
  sleep 0.1
11
12
  end
12
13
 
@@ -15,7 +16,7 @@ describe 'Tiq::Node::Addon' do
15
16
  @peer = nil
16
17
  @node.shutdown
17
18
  @node = nil
18
- sleep 1
19
+ sleep 2
19
20
  end
20
21
 
21
22
  it 'attaches and calls an addon' do
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Tiq::Node::Data do
3
+ describe Tiq::Node::Channel do
4
4
  let( :node ) { @node ||= Tiq::Node.new( url: 'localhost:9999' ) }
5
5
  let( :peer ) { @peer ||= Tiq::Node.new( url: 'localhost:9998', peer: 'localhost:9999' ) }
6
6
 
@@ -19,44 +19,44 @@ describe Tiq::Node::Data do
19
19
  end
20
20
 
21
21
  it 'sets and gets data locally' do
22
- node.data.set( 'key1', 'value1' )
23
- expect( node.data.get( 'key1' ) ).to eq 'value1'
22
+ node.channel.set( 'key1', 'value1' )
23
+ expect( node.channel.get( 'key1' ) ).to eq 'value1'
24
24
  end
25
25
 
26
26
  it 'propagates data to peers' do
27
- node.data.set( 'key2', 'value2' )
27
+ node.channel.set( 'key2', 'value2' )
28
28
  sleep 1
29
- expect( peer.data.get( 'key2' ) ).to eq 'value2'
29
+ expect( peer.channel.get( 'key2' ) ).to eq 'value2'
30
30
  end
31
31
 
32
32
  it 'does not propagate data when broadcast is false' do
33
- node.data.set( 'key3', 'value3', false )
33
+ node.channel.set( 'key3', 'value3', false )
34
34
  sleep 0.1
35
- expect( peer.data.get( 'key3' ) ).to be_nil
35
+ expect( peer.channel.get( 'key3' ) ).to be_nil
36
36
  end
37
37
 
38
38
  it 'calls on_set callbacks' do
39
39
  called = false
40
- peer.data.on_set( 'key4' ) { |k, v| called = (k == 'key4' && v == 'value4') }
41
- node.data.set( 'key4', 'value4' )
40
+ peer.channel.on_set( 'key4' ) { |k, v| called = (k == 'key4' && v == 'value4') }
41
+ node.channel.set( 'key4', 'value4' )
42
42
  sleep 1
43
43
  expect( called ).to be true
44
44
  end
45
45
 
46
46
  it 'calls on_delete callbacks' do
47
47
  called = false
48
- peer.data.set( 'key5', 'value5' )
48
+ peer.channel.set( 'key5', 'value5' )
49
49
  sleep 1
50
- peer.data.on_delete( 'key5' ) { |k| called = (k == 'key5') }
51
- node.data.delete( 'key5' )
50
+ peer.channel.on_delete( 'key5' ) { |k| called = (k == 'key5') }
51
+ node.channel.delete( 'key5' )
52
52
  sleep 1
53
53
  expect( called ).to be true
54
54
  end
55
55
 
56
56
  it 'does not call on_set callback when value is unchanged' do
57
57
  count = 0
58
- peer.data.on_set( 'key6' ) { count += 1 }
59
- node.data.set( 'key6', 'value6' )
60
- node.data
58
+ peer.channel.on_set( 'key6' ) { count += 1 }
59
+ node.channel.set( 'key6', 'value6' )
60
+ node.channel
61
61
  end
62
62
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiq
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tasos Laskos
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-10-11 00:00:00.000000000 Z
10
+ date: 2025-12-24 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: msgpack
@@ -43,30 +42,28 @@ email: tasos.laskos@gmail.com
43
42
  executables: []
44
43
  extensions: []
45
44
  extra_rdoc_files:
46
- - README.md
47
- - LICENSE.md
48
45
  - CHANGELOG.md
46
+ - LICENSE.md
47
+ - README.md
49
48
  files:
50
49
  - CHANGELOG.md
51
50
  - LICENSE.md
52
51
  - README.md
53
52
  - lib/tiq.rb
54
- - lib/tiq/channel.rb
55
53
  - lib/tiq/client.rb
56
54
  - lib/tiq/node.rb
57
55
  - lib/tiq/node/addon.rb
58
- - lib/tiq/node/data.rb
56
+ - lib/tiq/node/channel.rb
57
+ - lib/tiq/version.rb
59
58
  - spec/spec_helper.rb
60
- - spec/tiq/channel_spec.rb
61
59
  - spec/tiq/client_spec.rb
62
60
  - spec/tiq/node/addon_spec.rb
63
- - spec/tiq/node/data_spec.rb
61
+ - spec/tiq/node/channel_spec.rb
64
62
  - spec/tiq/node_spec.rb
65
63
  homepage: https://github.com/qadron/tiq
66
64
  licenses:
67
- - BSD 3-Clause
65
+ - MPL v2
68
66
  metadata: {}
69
- post_install_message:
70
67
  rdoc_options:
71
68
  - "--charset=UTF-8"
72
69
  require_paths:
@@ -82,14 +79,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
79
  - !ruby/object:Gem::Version
83
80
  version: '0'
84
81
  requirements: []
85
- rubygems_version: 3.4.22
86
- signing_key:
82
+ rubygems_version: 3.6.9
87
83
  specification_version: 4
88
84
  summary: Simple RPC protocol.
89
85
  test_files:
86
+ - spec/spec_helper.rb
90
87
  - spec/tiq/client_spec.rb
91
- - spec/tiq/node_spec.rb
92
- - spec/tiq/channel_spec.rb
93
- - spec/tiq/node/data_spec.rb
94
88
  - spec/tiq/node/addon_spec.rb
95
- - spec/spec_helper.rb
89
+ - spec/tiq/node/channel_spec.rb
90
+ - spec/tiq/node_spec.rb
data/lib/tiq/channel.rb DELETED
@@ -1,17 +0,0 @@
1
- require 'msgpack'
2
- require 'toq'
3
-
4
- module Tiq
5
- class Channel < Toq::Client
6
-
7
- def initialize( url, options = {} )
8
- host, port = url.split( ':' )
9
- super( options.merge( host: host, port: port.to_i ) )
10
- end
11
-
12
- def method_missing( method, *args, &block )
13
- call( "data.#{method}", *args, &block )
14
- end
15
-
16
- end
17
- end
@@ -1,5 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Tiq::Channel do
4
-
5
- end