plezi 0.12.14 → 0.12.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 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