plezi 0.12.14 → 0.12.15

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
  SHA1:
3
- metadata.gz: d6b0b52b7ab1f233bf4d1e35c75df9579a0f1456
4
- data.tar.gz: 1f927d686228dd20ebec6397b3977dbb68bdcf3f
3
+ metadata.gz: 1e2ced994d1b21af157a084e747c60c2fd113a5c
4
+ data.tar.gz: 6828e742abc6eb612cf70bfbe0c6f2f6da1cac1c
5
5
  SHA512:
6
- metadata.gz: 54a35d6840cbfd4477e52b68552c958458f886b85204360c2e7951d76b62836737622e83c8ad915469cc0f892fa459bb99a31b5650d3d21bfd7528f997b4c273
7
- data.tar.gz: c9e5d79dade6f7fd1416cd5d34fb189fd31dd6fd9b0fdf6f6ef2df823de5b5203c84b51bd95f733e23436667d5c3bc16b623068792e708849b32a1a090c1aa15
6
+ metadata.gz: d7f1d3f579ae87afdf56028e80e093c00ae1f9bd01f155e424c71cb2d846cf418f109c82ee559d21454836345ebe219d614a6af0f11d94e81665fee40856e203
7
+ data.tar.gz: 23a7279397df8ea1326bfe2da342b5c9c3ab5f85bb3970aae34bbc6c265e01b34392e292a2638e5b48596d720af2a1eb58ae588c624d63324b357c56c01b676f
@@ -2,6 +2,16 @@
2
2
 
3
3
  ***
4
4
 
5
+ Change log v.0.12.15
6
+
7
+ **Fix**: fixed the Redis connection, which was failing after DB selection support was added.
8
+
9
+ **Fix**: Iodine update fixes an issue where unicasting might fail when connection is still very new.
10
+
11
+ **Fixe**: fixed an issue with the Identity API where Redis emulation would loose the historic messages due to unicasting failure for the unregistered (super new) connection.
12
+
13
+ ***
14
+
5
15
  Change log v.0.12.14
6
16
 
7
17
  **Update**: `Controller#redirect_to` will now attempt to guess the URL using `url_for`, unless the URL given is a String. It also leverages the new `redirect_to` Iodine::Response method, allowing you to set the FUTURE response's status_code.
@@ -11,11 +11,11 @@ module Plezi
11
11
  @redis_locker.synchronize do
12
12
  return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis # repeat the test once syncing is done.
13
13
  @redis.quit if @redis
14
- @redis = ::Redis.new(ENV['PL_REDIS_URL'])
14
+ @redis = ::Redis.new(url: ENV['PL_REDIS_URL'])
15
15
  raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless @redis
16
16
  @redis_sub_thread = Thread.new do
17
17
  begin
18
- ::Redis.new(ENV['PL_REDIS_URL']).subscribe(Plezi::Settings.redis_channel_name, Plezi::Settings.uuid) do |on|
18
+ ::Redis.new(url: ENV['PL_REDIS_URL']).subscribe(Plezi::Settings.redis_channel_name, Plezi::Settings.uuid) do |on|
19
19
  on.message do |channel, msg|
20
20
  ::Plezi::Base::WSObject.forward_message ::Plezi::Base::WSObject.translate_message(msg)
21
21
  end
@@ -39,6 +39,18 @@ module Plezi
39
39
  @cache[key].count
40
40
  end
41
41
  end
42
+ def lpop key
43
+ sync do
44
+ @cache[key] ||= []
45
+ @cache[key].shift
46
+ end
47
+ end
48
+ def lrem key, count, value
49
+ sync do
50
+ @cache[key] ||= []
51
+ @cache[key].delete(value)
52
+ end
53
+ end
42
54
  def rpush key, value
43
55
  sync do
44
56
  @cache[key] ||= []
@@ -95,8 +107,7 @@ module Plezi
95
107
  # @!visibility public
96
108
  # The following method registers the connections as a unique global identity.
97
109
  #
98
- # Like {Plezi::Base::WSObject::SuperClassMethods#notify}, using this method requires an active Redis connection
99
- # to be set up. See {Plezi#redis} for more information.
110
+ # The Identity API works best when a Redis server is used. See {Plezi#redis} for more information.
100
111
  #
101
112
  # By default, only one connection at a time can respond to identity events. If the same identity
102
113
  # connects more than once, only the last connection will receive the notifications.
@@ -110,9 +121,19 @@ module Plezi
110
121
  # lifetime:: sets how long the identity can survive. defaults to `604_800` seconds (7 days).
111
122
  # max_connections:: sets the amount of concurrent connections an identity can have (akin to open browser tabs receiving notifications). defaults to 1 (a single connection).
112
123
  #
124
+ # Lifetimes are renewed with each registration and when a connected Identoty receives a notification.
125
+ # Identities should have a reasonable lifetime. For example, a 10 minutes long lifetime (60*10)
126
+ # may prove ineffective. When using such short lifetimes, consider the possibility that `unicast` might provide be a better alternative.
127
+ #
128
+ # A lifetime cannot (by design) be shorter than 10 minutes.
129
+ #
113
130
  # Calling this method will also initiate any events waiting in the identity's queue.
114
131
  # make sure that the method is only called once all other initialization is complete.
115
132
  #
133
+ # i.e.
134
+ #
135
+ # register_as session.id, lifetime: 60*60*24, max_connections: 4
136
+ #
116
137
  # Do NOT call this method asynchronously unless Plezi is set to run as in a single threaded mode - doing so
117
138
  # will execute any pending events outside the scope of the IO's mutex lock, thus introducing race conditions.
118
139
  def register_as identity, options = {}
@@ -120,19 +141,21 @@ module Plezi
120
141
  options[:max_connections] ||= 1
121
142
  options[:max_connections] = 1 if options[:max_connections].to_i < 1
122
143
  options[:lifetime] ||= 604_800
144
+ options[:lifetime] = 600 if options[:lifetime].to_i < 600
123
145
  identity = identity.to_s.freeze
124
- @___identity ||= [].to_set
125
- @___identity << identity
126
- redis.pipelined do
146
+ @___identity ||= {}
147
+ @___identity[identity] = options
148
+ redis.multi do
149
+ redis.lpop(identity)
150
+ redis.lpush(identity, ''.freeze)
151
+ redis.lrem "#{identity}_uuid".freeze, 0, uuid
127
152
  redis.lpush "#{identity}_uuid".freeze, uuid
128
153
  redis.ltrim "#{identity}_uuid".freeze, 0, (options[:max_connections]-1)
129
- end
130
- redis.lpush(identity, ''.freeze) unless redis.llen(identity) > 0
131
- ___review_identity identity
132
- redis.pipelined do
133
154
  redis.expire identity, options[:lifetime]
134
155
  redis.expire "#{identity}_uuid".freeze, options[:lifetime]
135
156
  end
157
+ ___review_identity identity
158
+ identity
136
159
  end
137
160
 
138
161
  # @!visibility public
@@ -153,21 +176,44 @@ module Plezi
153
176
  def ___review_identity identity
154
177
  redis = Plezi.redis || ::Plezi::Base::WSObject::RedisEmultaion
155
178
  identity = identity.to_s.freeze
156
- return Iodine.warn("Identity message reached wrong target (ignored).").clear unless @___identity.include?(identity)
179
+ return Iodine.warn("Identity message reached wrong target (ignored).").clear unless @___identity[identity]
157
180
  messages = redis.multi do
158
181
  redis.lrange identity, 1, -1
159
182
  redis.ltrim identity, 0, 0
183
+ redis.expire identity, @___identity[identity][:lifetime]
184
+ redis.expire "#{identity}_uuid".freeze, @___identity[identity][:lifetime]
160
185
  end[0]
161
186
  targets = redis.lrange "#{identity}_uuid", 0, -1
187
+ targets.delete(uuid)
162
188
  while msg = messages.shift
163
189
  msg = ::Plezi::Base::WSObject.translate_message(msg)
164
190
  next unless msg
165
191
  Iodine.error("Notification recieved but no method can handle it - dump:\r\n #{msg.to_s}") && next unless self.class.has_super_method?(msg[:method])
166
- # targets.each {|target| target == uuid ? self.method(msg[:method]).call(*msg[:data]) : unicast(target, msg[:method], *msg[:data])}
167
- targets.each {|target| unicast(target, msg[:method], *msg[:data])} # this allows for async execution
168
-
192
+ Iodine.run do
193
+ targets.each {|target| unicast(target, msg[:method], *msg[:data]) }
194
+ end
195
+ self.method(msg[:method]).call(*msg[:data])
169
196
  end
197
+ # ___extend_lifetime identity
170
198
  end
199
+
200
+ # # re-registers the Identity, extending it's lifetime
201
+ # # and making sure it's still valid.
202
+ # def ___extend_lifetime identity
203
+ # return unless @___identity
204
+ # redis = Plezi.redis || ::Plezi::Base::WSObject::RedisEmultaion
205
+ # options = @___identity[identity]
206
+ # return unless options
207
+ # redis.multi do
208
+ # # redis.lpop(identity)
209
+ # # redis.lpush(identity, ''.freeze)
210
+ # # redis.lrem "#{identity}_uuid".freeze, 0, uuid
211
+ # # redis.lpush "#{identity}_uuid".freeze, uuid
212
+ # # redis.ltrim "#{identity}_uuid".freeze, 0, (options[:max_connections]-1)
213
+ # redis.expire identity, options[:lifetime]
214
+ # redis.expire "#{identity}_uuid".freeze, options[:lifetime]
215
+ # end
216
+ # end
171
217
  end
172
218
 
173
219
  module SuperClassMethods
@@ -180,6 +226,7 @@ module Plezi
180
226
  return false unless redis.llen(identity).to_i > 0
181
227
  redis.rpush identity, ({method: event_name, data: args}).to_yaml
182
228
  redis.lrange("#{identity}_uuid".freeze, 0, -1).each {|target| unicast target, :___review_identity, identity }
229
+ # puts "pushed notification #{event_name}"
183
230
  true
184
231
  end
185
232
 
@@ -97,16 +97,19 @@ module Plezi
97
97
 
98
98
  protected
99
99
 
100
+ # @!visibility public
100
101
  # allows writing of data to the websocket (if opened). Otherwise appends the message to the Http response.
101
102
  def write data
102
103
  (@ws_io || @response) << data
103
104
  end
104
105
 
106
+ # @!visibility public
105
107
  # Performs a websocket unicast to the specified target.
106
108
  def unicast target_uuid, method_name, *args
107
109
  self.class.unicast target_uuid, method_name, *args
108
110
  end
109
111
 
112
+ # @!visibility public
110
113
  # Use this to brodcast an event to all 'sibling' objects (websockets that have been created using the same Controller class).
111
114
  #
112
115
  # Accepts:
@@ -119,6 +122,8 @@ module Plezi
119
122
  return false unless self.class.has_method? method_name
120
123
  self.class._inner_broadcast({ method: method_name, data: args, type: self.class}, __get_io )
121
124
  end
125
+
126
+ # @!visibility public
122
127
  # Use this to multicast an event to ALL websocket connections on EVERY controller, including Placebo controllers.
123
128
  #
124
129
  # Accepts:
@@ -238,7 +243,7 @@ module Plezi
238
243
  # sends the broadcast
239
244
  def _inner_broadcast data, ignore_io = nil
240
245
  if data[:target]
241
- if data[:target] && (data[:to_server] == Plezi::Settings.uuid )
246
+ if data[:to_server] == Plezi::Settings.uuid
242
247
  return ( ::Iodine::Http::Websockets.unicast( data[:target], data ) || ___faild_unicast( data ) )
243
248
  end
244
249
  return ( data[:to_server].nil? && ::Iodine::Http::Websockets.unicast(data[:target], data) ) || ( Plezi::Base::AutoRedis.away?(data[:to_server]) && ___faild_unicast( data ) ) || __inner_redis_broadcast(data)
@@ -1,9 +1,14 @@
1
1
  module Plezi
2
2
  module Base
3
3
 
4
+
4
5
  # Sends common basic HTTP responses.
5
6
  module HTTPSender
6
- class ErrorCtrl
7
+ # makes sure to methods are injected to class Class
8
+ class Container
9
+ end
10
+ # the Error Controller, for rendering error templates.
11
+ class ErrorCtrl < Container
7
12
  include ::Plezi::Base::ControllerCore
8
13
  include ::Plezi::ControllerMagic
9
14
 
@@ -1,7 +1,7 @@
1
1
  module Plezi
2
2
  # This module holds the mime dictionary.
3
3
  module MimeTypeHelper
4
- # thank you Apache group (and many more), for compiling mime-type list for me to search through.
4
+ # thank you Apache group (and many more), for compiling mime-type lists for me to search through.
5
5
  MIME_DICTIONARY = { ".123"=>"application/vnd.lotus-1-2-3".freeze,
6
6
  ".3dml"=>"text/vnd.in3d.3dml".freeze,
7
7
  ".3ds"=>"image/x-3ds".freeze,
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.12.14"
2
+ VERSION = "0.12.15"
3
3
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "iodine", "~> 0.1.14"
21
+ spec.add_dependency "iodine", "~> 0.1.15"
22
22
  spec.add_development_dependency "bundler", "~> 1.7"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
 
@@ -29,7 +29,7 @@ if defined? Redis
29
29
  # ## the following is only sample code for you to change:
30
30
  # RADIS_CHANNEL = 'appsecret'
31
31
  # RADIS_URI = ENV['REDIS_URL'] || ENV['REDISCLOUD_URL'] || "redis://:password@my.host:6389/0"
32
- # RADIS_CONNECTION = Redis.new(RADIS_URI)
32
+ # RADIS_CONNECTION = Redis.new(url: RADIS_URI)
33
33
  # RADIS_THREAD = Thread.new do
34
34
  # Redis.new(RADIS_URI).subscribe(RADIS_CHANNEL) do |on|
35
35
  # on.message do |channel, msg|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plezi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.14
4
+ version: 0.12.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.14
19
+ version: 0.1.15
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.14
26
+ version: 0.1.15
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement