tiq 0.1 → 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: 8e436fceef44012df5924defa9947216cac33a6703f222a738a0abc56f48c21b
4
- data.tar.gz: b802bf48b8133fce415abc875069ee33eb2e3d362cc8e5043288c534d8caf856
3
+ metadata.gz: cbc51f573dbb6b1f9ebb839e651af7939309a34e9b7d7aebbb1aa1bba4821096
4
+ data.tar.gz: 1f46fdb48cb1700f9e4325d42b7fce28ddbeeb95144bd02765fee4ba39bda5d0
5
5
  SHA512:
6
- metadata.gz: 6bf88679ecc201e7a814724d8efa5888d8944515325c8d3ec087d4da95d23d8eae66745b941731ea7a195ac94a010f7785687773749de13ba2691baac6757f91
7
- data.tar.gz: 80d673141cf5ea1d7cb213dc6ae0a4fa2c843f10fe4ec373ffa8ccf8c1e897c6d209520ee2ce23b7ad2f2ffad20edfcd8e20ab2455f88de434f4e316bb5eb38d
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
@@ -1,10 +1,6 @@
1
1
  # Tiq
2
2
 
3
3
  <table>
4
- <tr>
5
- <th>Version</th>
6
- <td>0.0.1</td>
7
- </tr>
8
4
  <tr>
9
5
  <th>Github page</th>
10
6
  <td><a href="http://github.com/qadron/tiq">http://github.com/qadron/tiq</a></td>
@@ -19,27 +15,27 @@
19
15
  </tr>
20
16
  <tr>
21
17
  <th>Copyright</th>
22
- <td>2025 <a href="https://ecsypno.com">Ecsypno</a></td>
18
+ <td><a href="mailto:tasos.laskos@gmail.com">Tasos Laskos</a></td>
23
19
  </tr>
24
20
  <tr>
25
21
  <th>License</th>
26
- <td><a href="file.LICENSE.html">3-clause BSD</a></td>
22
+ <td><a href="file.LICENSE.html">MPL v2</a></td>
27
23
  </tr>
28
24
  </table>
29
25
 
30
26
  ## Synopsis
31
27
 
32
- Tiq is a simple and lightweight clustering solution protocol.
28
+ Tiq is a simple and lightweight clustering solution.
33
29
 
34
- This implementation is based on [Toq](https://github.com/qadron/toq) for Remote Procedure Call needs.
30
+ This implementation is based on [Toq](https://github.com/qadron/toq) to cover Remote Procedure Call needs.
35
31
 
36
32
  ## Concepts
37
33
 
38
- There are a few key concepts in `Tik`:
34
+ There are a few key concepts in `Tiq`:
39
35
 
40
36
  ### Node
41
37
 
42
- `Tik::Node` offers _Node_ representations, _server-side_ presences if you must.
38
+ `Tiq::Node` offers _Node_ representations, _server-side_ presences if you must.
43
39
 
44
40
  To start a _Node_, you need to create a class that inherits from `Tiq::Node`
45
41
  and instantiate it with a URL to bind to.
@@ -48,7 +44,7 @@ and instantiate it with a URL to bind to.
48
44
  cass MyNode < Tiq::Node
49
45
  end
50
46
 
51
- node = MyNode.new( url: "localhost:9999" )
47
+ node = MyNode.new( url: "localhost:9999" ).start
52
48
  ```
53
49
 
54
50
  ### Cluster
@@ -62,15 +58,15 @@ Any existing _Node_ would do.
62
58
  class MySecondNode < Tiq::Node
63
59
  end
64
60
 
65
- node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' )
61
+ node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' ).start
66
62
  ```
67
63
 
68
64
  ### Client
69
65
 
70
- `Tik::Client` offers a _Client_ to enable _Node_/User communications.
66
+ `Tiq::Client` offers a _Client_ to enable _Node_/User communications.
71
67
 
72
68
  ```ruby
73
- client = MyClient.new( "localhost:9999" )
69
+ client = MyClient.new( "localhost:9999" ).start
74
70
 
75
71
  # Issue calls on the server side and get us the responses.
76
72
  # Client will return `true`.
@@ -99,18 +95,17 @@ class MyChannelNode < Tiq::Node
99
95
  end
100
96
 
101
97
  # Set up initial Node, the start of the cluster.
102
- node_1 = MyNode.new( url: "localhost:9999" )
103
- node_2 = MySecondNode.new( url: "localhost:9998", peer: 'localhost:9999' )
104
- 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
105
101
  sleep 1
106
102
 
107
103
  channel.on_set :my_signal do |value|
108
104
  p "#{:on_set} - #{value}"
109
105
  end
110
106
 
111
- node_1.data.set :my_signal, 'tada!'
107
+ node_1.channel.set :my_signal, 'tada!'
112
108
  sleep 1
113
-
114
109
  ```
115
110
 
116
111
  ### Add-ons
@@ -123,11 +118,8 @@ every _Node_.
123
118
  class MyNode < Tiq::Node
124
119
  end
125
120
 
126
- class MyClient < Tiq::Client
127
- end
128
-
129
121
  # Set up initial Node.
130
- node_1 = MyNode.new( url: "localhost:9999" )
122
+ node_1 = MyNode.new( url: "localhost:9999" ).start
131
123
 
132
124
  # Add a service to the node, called :poll.
133
125
  Tiq::Addon::Attach node_1, :poll do |arguments = nil|
@@ -135,13 +127,14 @@ Tiq::Addon::Attach node_1, :poll do |arguments = nil|
135
127
  end
136
128
 
137
129
  # Interact with the service via a Client.
138
- client_1 = MyClient.new( "localhost:9999" )
139
- Tiq::Addon client_1, :poll, 'ping' do
130
+ Tiq::Addon "localhost:9999", :poll, 'ping' do |r|
140
131
  puts "CLIENT: #{r}"
141
132
  end
133
+
134
+ sleep 1
142
135
  ```
143
136
 
144
- ### Data
137
+ ### Channel Shared Data
145
138
 
146
139
  Data can be shared across _Nodes_ by means of broadcasting upon
147
140
  change - optional.
@@ -154,18 +147,34 @@ class MySecondNode < Tiq::Node
154
147
  end
155
148
 
156
149
  # Set up initial Node, the start of the cluster.
157
- node_1 = MyNode.new( url: "localhost:9999" )
158
- 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
159
152
 
160
153
  sleep 1
161
154
 
162
- node_2.data.on_set :my_signal do |value|
155
+ node_2.channel.on_set :my_signal do |value|
163
156
  p "#{:on_set} - #{value}"
164
157
  end
165
158
 
166
- 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
167
175
  sleep 1
168
176
 
177
+ p n2.agents.get :a1
169
178
  ```
170
179
 
171
180
  ## Installation
data/lib/tiq/client.rb CHANGED
@@ -1,15 +1,18 @@
1
1
  require 'msgpack'
2
+ require 'toq'
2
3
 
3
4
  module Tiq
4
5
  class Client < Toq::Client
5
6
 
6
7
  def initialize( url, options = {} )
8
+ @handler = (options[:handler] || 'node').to_s
9
+
7
10
  host, port = url.split( ':' )
8
11
  super( options.merge( host: host, port: port.to_i ) )
9
12
  end
10
13
 
11
14
  def method_missing( method, *args, &block )
12
- call( "node.#{method}", *args, &block )
15
+ call( "#{@handler}.#{method}", *args, &block )
13
16
  end
14
17
 
15
18
  end
@@ -1,7 +1,8 @@
1
1
  module Tiq
2
2
 
3
- def self.Addon( node, shortname, *args, &block )
4
- node.call_addon( shortname, *args, &block )
3
+ def self.Addon( client_or_url, shortname, *args, &block )
4
+ client = client_or_url.is_a?( Tiq::Client ) ? client_or_url : Tiq::Client.new( client_or_url )
5
+ client.call_addon( shortname, *args, &block )
5
6
  end
6
7
 
7
8
  module Addon
@@ -22,18 +23,18 @@ class Node
22
23
  class Addon
23
24
 
24
25
  attr_reader :node
25
- attr_reader :data
26
+ attr_reader :channel
26
27
  attr_reader :options
27
28
 
28
29
  def initialize( node, payload, options = {} )
29
30
  @node = node
30
31
  @options = options
31
- @data = @node.data
32
+ @channel = @node.channel
32
33
  @payload = payload
33
34
  end
34
35
 
35
- def call( *aguments, &block )
36
- @payload.call( *aguments, &block )
36
+ def call( *arguments, &block )
37
+ instance_eval { @payload.call *arguments, &block }
37
38
  end
38
39
 
39
40
  # @return [Server::node::Node]
@@ -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,17 +1,41 @@
1
1
  require 'set'
2
- require_relative 'node/data'
3
- require_relative 'channel'
2
+ require 'yaml'
3
+ require_relative 'node/channel'
4
+ require_relative 'node/addon'
4
5
  require_relative 'client'
5
6
 
6
7
  module Tiq
7
8
 
8
9
  class Node
9
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
+
10
33
  INTERVAL_PING = 5
11
34
 
12
- attr_reader :data
13
- attr_reader :services
35
+ attr_reader :url
36
+ attr_reader :channel
14
37
  attr_reader :reactor
38
+ attr_reader :server
15
39
 
16
40
  # Initializes the node by:
17
41
  #
@@ -32,11 +56,15 @@ class Node
32
56
  @addons = {}
33
57
  @nodes_info_cache = []
34
58
 
35
- host, port = @url.split( ':' )
59
+ host = port = nil
60
+ if @url
61
+ host, port = @url.split( ':' )
62
+ end
63
+
36
64
  options[:host] ||= host || 'localhost'
37
65
  options[:port] ||= port || 9999
38
66
 
39
- @server = Toq::Server.new( host: options[:host], port: options[:port] )
67
+ @server = Toq::Server.new( options.merge( host: options[:host], port: options[:port] ) )
40
68
  @reactor = @server.reactor
41
69
  @server.add_async_check do |method|
42
70
  # methods that expect a block are async
@@ -46,8 +74,10 @@ class Node
46
74
 
47
75
  @reactor.run_in_thread if !@reactor.running?
48
76
 
49
- @data = Data.new( self )
50
- @server.add_handler( 'data', @data )
77
+ @channel = Tiq::Node::Channel.new( self, handler: 'channel' )
78
+ @server.add_handler( 'channel', @channel )
79
+
80
+ @channels = {}
51
81
 
52
82
  @reactor.on_error do |_, e|
53
83
  $stderr.puts "Reactor: #{e}"
@@ -85,7 +115,11 @@ class Node
85
115
 
86
116
  announce @url
87
117
  rescue => e
118
+ p grid_peers
88
119
  p e
120
+ e.backtrace.each do |l|
121
+ p l
122
+ end
89
123
  end
90
124
  end
91
125
  end
@@ -93,16 +127,23 @@ class Node
93
127
  $stdout.puts 'Node ready.'
94
128
 
95
129
  log_updated_peers
96
-
97
- run
98
130
  end
99
131
 
100
132
  def attach_addon( name, service, options = {} )
101
- @addons[name.to_s] = Addon.new( self, service, options )
133
+ name = name.to_s
134
+ if @addons[name]
135
+ fail "Add-on already registered with name: #{name}"
136
+ end
137
+ @addons[name] = Node::Addon.new( self, service, options )
102
138
  nil
103
139
  end
104
140
 
105
141
  def call_addon( name, *arguments )
142
+ name = name.to_s
143
+ if !@addons[name]
144
+ fail "Add-on not attached with name: #{name}"
145
+ end
146
+
106
147
  @addons[name.to_s].call( *arguments )
107
148
  end
108
149
 
@@ -111,9 +152,52 @@ class Node
111
152
  end
112
153
 
113
154
  def dettach_addon( name )
155
+ name = name.to_s
156
+ if !@addons[name]
157
+ fail "Add-on not attached with name: #{name}"
158
+ end
159
+
114
160
  @addons.delete name
115
161
  end
116
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
+
117
201
  # @return [Boolean]
118
202
  # `true` if grid member, `false` otherwise.
119
203
  def grid_member?
@@ -121,7 +205,7 @@ class Node
121
205
  end
122
206
 
123
207
  def unplug
124
- @server.create_iterator( @peers, 20 ).each do |peer, iterator|
208
+ @reactor.create_iterator( @peers, 20 ).each do |peer, iterator|
125
209
  connect_to_peer( peer ).remove_peer( @url ) { iterator.next }
126
210
  end
127
211
 
@@ -139,14 +223,14 @@ class Node
139
223
  $stdout.puts "Adding peer: #{node_url}"
140
224
  @peers << node_url
141
225
 
142
- connect_to_peer( node_url ){ update_data( @data.to_h ) }
226
+ connect_to_peer( node_url ){ update_channel( @channel.to_h ) }
143
227
 
144
228
  log_updated_peers
145
229
  true
146
230
  end
147
231
 
148
- def update_data( data )
149
- @data.update( data )
232
+ def update_channel( channel )
233
+ @channel.update( channel )
150
234
  nil
151
235
  end
152
236
 
@@ -213,9 +297,16 @@ class Node
213
297
  true
214
298
  end
215
299
 
216
- def run
300
+ def start
301
+ # @server.reactor.ensure_reactor_running
217
302
  $stdout.puts 'Running'
218
303
  @server.start
304
+
305
+ q = Queue.new
306
+ self.class.when_ready( @url) { q << Client.new( @url ) }
307
+ q.pop
308
+
309
+ self
219
310
  rescue => e
220
311
  $stderr.puts e
221
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.1'
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,17 +16,64 @@ 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
22
- node.attach_addon( 'echo', 'Tiq::Service::Echo' )
23
+ node.attach_addon 'echo', proc { |arguments|
24
+ arguments
25
+ }
23
26
  result = node.call_addon( 'echo', 'hello' )
24
27
  expect( result ).to eq 'hello'
25
28
  end
26
29
 
27
30
  it 'lists addons' do
28
- node.attach_addon( 'echo', 'Tiq::Service::Echo' )
31
+ node.attach_addon 'echo', proc { |arguments|
32
+ arguments
33
+ }
29
34
  expect( node.addons ).to include 'echo'
30
35
  end
36
+
37
+ describe 'Tiq.Addon' do
38
+ it 'calls an Addon to handle the request' do
39
+ Tiq::Addon.Attach( node, 'echo' ) { |arguments|
40
+ arguments
41
+ }
42
+ result = Tiq::Addon( 'localhost:9999', 'echo', 'test' )
43
+ expect( result ).to eq 'test'
44
+ end
45
+ end
46
+
47
+ describe Tiq::Addon do
48
+ describe '.Attach' do
49
+ it 'attaches an Addon' do
50
+ Tiq::Addon.Attach( node, 'echo' ) { |arguments|
51
+ arguments
52
+ }
53
+ result = Tiq::Addon( 'localhost:9999', 'echo', 'test' )
54
+ expect( result ).to eq 'test'
55
+ end
56
+ end
57
+
58
+ describe '.Dettach' do
59
+ it 'dettaches an Addon' do
60
+ Tiq::Addon::Attach( node, 'echo' ) { |arguments|
61
+ arguments
62
+ }
63
+ result = Tiq::Addon( 'localhost:9999', 'echo', 'test' )
64
+ expect( result ).to eq 'test'
65
+
66
+ Tiq::Addon.Dettach( node, 'echo' )
67
+
68
+ result = nil
69
+ begin
70
+ Tiq::Addon( 'localhost:9999', 'echo', 'test' )
71
+ rescue => e
72
+ result = e
73
+ end
74
+
75
+ expect(result.class).to be Toq::Exceptions::RemoteException
76
+ end
77
+ end
78
+ end
31
79
  end
@@ -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.1'
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-10 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,18 +0,0 @@
1
- require 'msgpack'
2
- require 'toq'
3
-
4
- module Tiq
5
- class Channel
6
-
7
- def initialize( url, options = {} )
8
- host, port = url.split( ':' )
9
- @client = Toq::Client.new( options.merge( host: host, port: port.to_i ) )
10
- end
11
-
12
- def method_missing( method, *args, &block )
13
- @client.call( "data.#{method}", *args, &block )
14
- end
15
-
16
- end
17
-
18
- end
@@ -1 +0,0 @@
1
- require 'spec_helper'