rmessage 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 027c26a46e85945a595e17f63f468b7db4bbc5445e62337e72aba85136ebd089
4
+ data.tar.gz: 5059e66328f264c26c20d42ab152dc4d1486b02f7990a87dec54560f94455def
5
+ SHA512:
6
+ metadata.gz: a7a1371e9e285c7f8313478f8ee7ecdce68d90b411922ed321d634781122a375534278439bfa02c175bfd1448212f08008339ada3b73e23306d27554e56cde21
7
+ data.tar.gz: ffdc5a57b6e9d5a99f9f22536478c45287076cc03a1fa2ac6ce25778f90b8b9e3f3ea316632a7d771c995f6c97e912ab479f4181010c2ee696513b3d415718b7
@@ -0,0 +1,81 @@
1
+ module RMessage
2
+ # A Message encapsulates a JSON payload that is sent to or received from Redis.
3
+ class Message
4
+
5
+ # @!attribute [r] label
6
+ # @return [Symbol, String] the label.
7
+ attr :label
8
+
9
+ # @!attribute [r] signature
10
+ # @return [Integer, String] the signature.
11
+ attr :signature
12
+
13
+ # @!attribute [r] payload
14
+ # @return [Hash] the payload.
15
+ attr :payload
16
+
17
+ # Constructs a new Message
18
+ # @param opts [Hash] message options
19
+ # * label [Symbol, String] the Message label
20
+ # * signature [Integer, String] the Message signature
21
+ # * payload [Hash, String] the Message data
22
+ # @param data [Hash, String] message data
23
+ def initialize(opts = {}, data = nil)
24
+ @label = opts[:label] || :UNTITLED
25
+ @signature = opts[:signature] || Druuid.gen
26
+ @payload = data || opts[:payload]
27
+ end
28
+
29
+ # Read and parse data. Defaults to the Message#payload.
30
+ # @param data [Hash, String] the data.
31
+ def read(data = @payload)
32
+ case data
33
+ when Hash
34
+ @label ||= data[:label]
35
+ @signature ||= data[:signature]
36
+ @payload ||= data[:payload]
37
+ when String
38
+ parsed = Oj.load(data)
39
+ @label ||= parsed['label']
40
+ @signature ||= parsed['signature']
41
+ @payload ||= parsed['payload']
42
+ else raise TypeError, 'Invalid type for Message#payload'
43
+ end
44
+ end
45
+
46
+ # Build a JSON string using data in this message
47
+ # @param data [Hash, String] the payload.
48
+ def build(data = @payload)
49
+ Oj.dump({ 'label' => @label, 'signature' => @signature, 'payload' => data })
50
+ end
51
+ end
52
+ end
53
+
54
+ # Copyright (c) 2022, Patrick W.
55
+ # All rights reserved.
56
+ #
57
+ # Redistribution and use in source and binary forms, with or without
58
+ # modification, are permitted provided that the following conditions are met:
59
+ #
60
+ # * Redistributions of source code must retain the above copyright notice, this
61
+ # list of conditions and the following disclaimer.
62
+ #
63
+ # * Redistributions in binary form must reproduce the above copyright notice,
64
+ # this list of conditions and the following disclaimer in the documentation
65
+ # and/or other materials provided with the distribution.
66
+ #
67
+ # * Neither the name of the copyright holder nor the names of its
68
+ # contributors may be used to endorse or promote products derived from
69
+ # this software without specific prior written permission.
70
+ #
71
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
72
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
74
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
75
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
76
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
77
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
78
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
79
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
81
+
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A module to provide publishing functions to an Object.
4
+ module RMessage::Publisher
5
+ # @!attribute [r] channel
6
+ # @return [String, Integer, Symbol] the channel to publish to
7
+ attr :channel
8
+
9
+ # Publishes a message to the specified redis channel.
10
+ # @param message [RMessage::Message] the message
11
+ # @param channel [String, Integer, Symbol] the channel
12
+ # @param connection_index [Integer] the index of the connection to Redis within the {RMessage::CONNECTION_POOL}
13
+ def publish(message, channel: @channel, connection_index: 0)
14
+ RMessage::CONNECTION_POOL[connection_index].publish(channel, message.build)
15
+ end
16
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Utility functions to allow setting up and parsing messages received from Redis publishers.
4
+ module RMessage::Subscriber
5
+ # @!attribute [r] channel
6
+ # @return [String, Symbol, Integer] the channel to subscribe to
7
+ attr :channel
8
+
9
+ # @!attribute [r] events
10
+ # @return [Hash] a map of event labels to classes
11
+ attr :events
12
+
13
+ # Setup a subscription to a specific Redis channel
14
+ # @param channel [Symbol, String, Integer] the channel
15
+ # @param auto_parse [Boolean] should messages be parsed automatically?
16
+ # @param connection_index [Integer] the index of the redis connection in {RMessage::CONNECTION_POOL}
17
+ def setup_subscription(channel: @channel, auto_parse: false, connection_index: 0, &_)
18
+ RMessage::CONNECTION_POOL[connection_index].subscribe(channel) do |event|
19
+ event.subscribe do
20
+ puts "Subscribed to #{channel}"
21
+ end
22
+
23
+ if auto_parse
24
+ event.message { |_, message| parse_message(message) }
25
+ else
26
+ event.message { |_, message| yield(message) }
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def parse_message(message_data)
34
+ msg = RMessage::Message.new(message_data)
35
+ msg.read
36
+ @events[msg.label].new(msg)
37
+ end
38
+ end
39
+
40
+ # Copyright (c) 2022, Patrick W.
41
+ # All rights reserved.
42
+ #
43
+ # Redistribution and use in source and binary forms, with or without
44
+ # modification, are permitted provided that the following conditions are met:
45
+ #
46
+ # * Redistributions of source code must retain the above copyright notice, this
47
+ # list of conditions and the following disclaimer.
48
+ #
49
+ # * Redistributions in binary form must reproduce the above copyright notice,
50
+ # this list of conditions and the following disclaimer in the documentation
51
+ # and/or other materials provided with the distribution.
52
+ #
53
+ # * Neither the name of the copyright holder nor the names of its
54
+ # contributors may be used to endorse or promote products derived from
55
+ # this software without specific prior written permission.
56
+ #
57
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
58
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
60
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
61
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
63
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
64
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
66
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/rmessage.rb ADDED
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.dirname(__FILE__)].each { |file| $LOAD_PATH.unshift(file) if File.directory? file }
4
+
5
+ require 'druuid'
6
+ require 'dotenv'
7
+ require 'redis'
8
+ require 'oj'
9
+
10
+ # Utility modules to make it easier to build Pub/Sub systems in Ruby using Redis.
11
+ module RMessage
12
+ # @!attribute [r] CONNECTION_POOL
13
+ # @return [Array] a pool of connections
14
+ CONNECTION_POOL = []
15
+
16
+ autoload :Broker, 'rmessage/broker'
17
+ autoload :Publisher, 'rmessage/publisher'
18
+ autoload :Subscriber, 'rmessage/subscriber'
19
+ autoload :Message, 'rmessage/message'
20
+
21
+ def self.add_connection(opts = {})
22
+ CONNECTION_POOL << Redis.new(host: opts[:host], port: opts[:port])
23
+ end
24
+
25
+ def self.load_defaults
26
+ # Load ENV vars.
27
+ Dotenv.load('.env') if File.exist?('.env')
28
+ Oj.default_options = { mode: :object, cache_keys: true, cache_strings: true, symbol_keys: false }
29
+ RMessage.add_connection(host: ENV['RMESSAGE_REDIS_HOST'], port: ENV['RMESSAGE_REDIS_PORT'])
30
+ end
31
+ end
32
+
33
+ # Copyright (c) 2022, Patrick W.
34
+ # All rights reserved.
35
+ #
36
+ # Redistribution and use in source and binary forms, with or without
37
+ # modification, are permitted provided that the following conditions are met:
38
+ #
39
+ # * Redistributions of source code must retain the above copyright notice, this
40
+ # list of conditions and the following disclaimer.
41
+ #
42
+ # * Redistributions in binary form must reproduce the above copyright notice,
43
+ # this list of conditions and the following disclaimer in the documentation
44
+ # and/or other materials provided with the distribution.
45
+ #
46
+ # * Neither the name of the copyright holder nor the names of its
47
+ # contributors may be used to endorse or promote products derived from
48
+ # this software without specific prior written permission.
49
+ #
50
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
51
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
54
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
56
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
57
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
58
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmessage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Patrick W.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dotenv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.7.6
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.7'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.7.6
33
+ - !ruby/object:Gem::Dependency
34
+ name: druuid
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.0.2
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.0.2
53
+ - !ruby/object:Gem::Dependency
54
+ name: oj
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.13'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.13.11
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.13'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.13.11
73
+ - !ruby/object:Gem::Dependency
74
+ name: redis
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '4.6'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 4.6.0
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '4.6'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 4.6.0
93
+ description:
94
+ email: Sickday@pm.me
95
+ executables: []
96
+ extensions: []
97
+ extra_rdoc_files: []
98
+ files:
99
+ - lib/rmessage.rb
100
+ - lib/rmessage/message.rb
101
+ - lib/rmessage/publisher.rb
102
+ - lib/rmessage/subscriber.rb
103
+ homepage: https://git.repos.pw/Sickday/rmessage
104
+ licenses:
105
+ - BSD-3-Clause
106
+ metadata:
107
+ source_code_uri: https://git.repos.pw/Sickday/rmessage
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.3.3
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Utility modules to make it easier to build Pub/Sub systems in Ruby using
127
+ Redis.
128
+ test_files: []