redmineup 1.1.11 → 1.1.13

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: ecb516fc8ae25a65558bec625b9603e7aacd7188d473e80b23eb27223050d2ac
4
- data.tar.gz: 66e4cecc1aa21ab23211e51774fbd262840f5df3efdbb9bb355d20870d142909
3
+ metadata.gz: a4d2181d902dbfa9a13995df17ff80c6a9eaea15fd54c6a918a6695ced32ed40
4
+ data.tar.gz: 88ee188a9626a4483f6ebc108a5f2ae174de4bde94e5d04128f60b0f3d6d8799
5
5
  SHA512:
6
- metadata.gz: 43bddd0b96c58e00fc4645476801b1792022bce7c13588dc99f00486f77f47031e0fce58a4b5fe41d11b3dfca899527d003f294e1030957662141042e96e6a71
7
- data.tar.gz: 4164a606ad2a264bb4501d3ec773215b5396b7da7dcdbc58bb09adadae630875d14dc9bdf4d669749b391ce19ff620df38c204d6474f2785f465d1e7b461a0b7
6
+ metadata.gz: bbd631a43429432a3c3f2e208527b601dd3d1dca57d260d314f2808d485b96d8f8ef29baf31a6836c026c30cf5d453075082d6d65cf548efba7fe5393a862b75
7
+ data.tar.gz: 49ccf2ace3f1af01aa00a748a94c93f6deb994fd5bc0e0a23db7f4e98c7ed371aeff27b8561a0c8cce1aeee19d9e8e5333ae4c7ee77c699bb9c8bb1c092daff3
@@ -1,5 +1,7 @@
1
1
  const connections = new Map();
2
2
  const MAX_PENDING_ACK = 3;
3
+ const RETRY_BASE_DELAY = 5000;
4
+ const RETRY_MAX_DELAY = 320000;
3
5
 
4
6
  self.onconnect = function (event) {
5
7
  const clientPort = event.ports[0];
@@ -114,26 +116,41 @@ function sendSubscribe(socket, identifier) {
114
116
  }
115
117
 
116
118
  function initSocketStruct() {
117
- return { socket: null, clients: new Map() };
119
+ return { socket: null, clients: new Map(), retryDelay: RETRY_BASE_DELAY };
118
120
  }
119
121
 
120
122
  function initWebSocket(url) {
121
123
  const conn = connections.get(url);
122
124
  if (!conn) return;
123
125
 
124
- conn.socket = new WebSocket(url);
126
+ if (conn.socket) {
127
+ try {
128
+ conn.socket.onopen =
129
+ conn.socket.onmessage =
130
+ conn.socket.onclose =
131
+ conn.socket.onerror =
132
+ null;
133
+ conn.socket.close();
134
+ } catch (e) {}
135
+ }
136
+
137
+ const socket = new WebSocket(url);
138
+ conn.socket = socket;
125
139
 
126
140
  conn.socket.onopen = function () {
141
+ if (conn.socket !== socket) return;
142
+ conn.retryDelay = RETRY_BASE_DELAY;
127
143
  const seen = new Set();
128
144
  for (const { channelIdentifier } of conn.clients.values()) {
129
145
  if (!seen.has(channelIdentifier)) {
130
146
  seen.add(channelIdentifier);
131
- sendSubscribe(conn.socket, channelIdentifier);
147
+ sendSubscribe(socket, channelIdentifier);
132
148
  }
133
149
  }
134
150
  };
135
151
 
136
152
  conn.socket.onmessage = function (event) {
153
+ if (conn.socket !== socket) return;
137
154
  const messageData = (event.data && JSON.parse(event.data)) || {};
138
155
 
139
156
  if (messageData.type === "confirm_subscription") {
@@ -154,15 +171,18 @@ function initWebSocket(url) {
154
171
  });
155
172
  };
156
173
 
157
- conn.socket.onclose = function () {
174
+ socket.onclose = function () {
175
+ if (conn.socket !== socket) return;
158
176
  broadcastTo(conn, { type: "disconnected" });
177
+ const delay = conn.retryDelay;
178
+ conn.retryDelay = Math.min(conn.retryDelay * 2, RETRY_MAX_DELAY);
159
179
  setTimeout(function () {
160
- if (connections.has(url)) initWebSocket(url);
161
- }, 5000);
180
+ if (connections.has(url) && conn.socket === socket) initWebSocket(url);
181
+ }, delay);
162
182
  };
163
183
 
164
- conn.socket.onerror = function (error) {
165
- conn.socket.close();
184
+ socket.onerror = function (error) {
185
+ socket.close();
166
186
  };
167
187
  }
168
188
 
data/doc/CHANGELOG CHANGED
@@ -4,6 +4,15 @@ Redmine UP gem - general functions for plugins (tags, vote, viewing, currency)
4
4
  Copyright (C) 2011-2026 Kirill Bezrukov (RedmineUP)
5
5
  https://www.redmineup.com/
6
6
 
7
+ == 2026-08-25 v1.1.13
8
+
9
+ * Updated patches from include to prepend
10
+
11
+ == 2026-07-23 v1.1.12
12
+
13
+ * Fixed race condition and added exponential backoff to shared worker websocket reconnect logic
14
+ * Added `Redmineup::TestHelper#load_plugin_fixtures` for loading plugin test fixtures
15
+
7
16
  == 2026-06-26 v1.1.11
8
17
 
9
18
  * Added shared workers for websocket connection
@@ -0,0 +1,12 @@
1
+ module Redmineup
2
+ module TestHelper
3
+ module ClassMethods
4
+ def load_plugin_fixtures(plugin_name, *names)
5
+ fixtures_dir = File.join(Redmine::Plugin.find(plugin_name).directory, 'test', 'fixtures')
6
+ ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, names)
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ ActiveSupport::TestCase.extend Redmineup::TestHelper::ClassMethods
@@ -1,9 +1,9 @@
1
1
  module Redmineup
2
2
  module Patches
3
3
  module ActionCableBasePatch
4
- def self.included(base)
5
- base.send(:extend, ClassMethods)
6
- delegate :rup_broadcast_to, to: :class
4
+ def self.prepended(base)
5
+ base.extend(ClassMethods)
6
+ base.delegate :rup_broadcast_to, to: :class
7
7
  end
8
8
 
9
9
  module ClassMethods
@@ -22,6 +22,4 @@ module Redmineup
22
22
  end
23
23
  end
24
24
 
25
- unless ActionCable::Channel::Base.included_modules.include?(Redmineup::Patches::ActionCableBasePatch)
26
- ActionCable::Channel::Base.send(:include, Redmineup::Patches::ActionCableBasePatch)
27
- end
25
+ ActionCable::Channel::Base.prepend(Redmineup::Patches::ActionCableBasePatch)
@@ -1,7 +1,7 @@
1
1
  module Redmineup
2
2
  module Patches
3
3
  module ActionCablePatch
4
- def self.included(base)
4
+ def self.prepended(base)
5
5
  base.class_eval do
6
6
  module_function def rup_server(klass = 'ActionCable::Connection::RupConnection')
7
7
  @rup_servers ||= {}
@@ -16,6 +16,4 @@ module Redmineup
16
16
  end
17
17
  end
18
18
 
19
- unless ActionCable.included_modules.include?(Redmineup::Patches::ActionCablePatch)
20
- ActionCable.include Redmineup::Patches::ActionCablePatch
21
- end
19
+ ActionCable.prepend(Redmineup::Patches::ActionCablePatch)
@@ -14,6 +14,4 @@ module Redmineup
14
14
  end
15
15
  end
16
16
 
17
- unless AutoCompletesController.included_modules.include?(Redmineup::Patches::AutoCompletesControllerPatch)
18
- AutoCompletesController.include(Redmineup::Patches::AutoCompletesControllerPatch)
19
- end
17
+ AutoCompletesController.prepend(Redmineup::Patches::AutoCompletesControllerPatch)
@@ -2,28 +2,15 @@ module Redmineup
2
2
  module Patches
3
3
  module Compatibility
4
4
  module RoutingMapperPatch
5
- def self.included(base)
6
- base.send(:include, InstanceMethods)
5
+ def constraints(options = {}, &block)
6
+ return super(options, &block) unless options.is_a?(Hash)
7
7
 
8
- base.class_eval do
9
- alias_method :constraints_without_redmineup, :constraints
10
- alias_method :constraints, :constraints_with_redmineup
11
- end
12
- end
13
-
14
- module InstanceMethods
15
- def constraints_with_redmineup(options = {}, &block)
16
- return constraints_without_redmineup(options, &block) unless options.is_a?(Hash)
17
-
18
- options[:object_type] = /.+/ if options[:object_type] && options[:object_type].is_a?(Regexp)
19
- constraints_without_redmineup(options, &block)
20
- end
8
+ options[:object_type] = /.+/ if options[:object_type] && options[:object_type].is_a?(Regexp)
9
+ super(options, &block)
21
10
  end
22
11
  end
23
12
  end
24
13
  end
25
14
  end
26
15
 
27
- unless ActionDispatch::Routing::Mapper.included_modules.include?(Redmineup::Patches::Compatibility::RoutingMapperPatch)
28
- ActionDispatch::Routing::Mapper.send(:include, Redmineup::Patches::Compatibility::RoutingMapperPatch)
29
- end
16
+ ActionDispatch::Routing::Mapper.prepend(Redmineup::Patches::Compatibility::RoutingMapperPatch)
@@ -2,18 +2,12 @@ module Redmineup
2
2
  module Patches
3
3
  module Compatibility
4
4
  module SpritePatch
5
- def self.included(base)
6
- base.class_eval do
7
- def sprite_icon(icon_name, label = '', icon_only: false, size: '18', css_class: nil, sprite: "icons", plugin: nil, rtl: false)
8
- label
9
- end
10
- end
5
+ def sprite_icon(icon_name, label = '', icon_only: false, size: '18', css_class: nil, sprite: "icons", plugin: nil, rtl: false)
6
+ label
11
7
  end
12
8
  end
13
9
  end
14
10
  end
15
11
  end
16
12
 
17
- unless ApplicationHelper.included_modules.include?(Redmineup::Patches::Compatibility::SpritePatch)
18
- ApplicationHelper.send(:include, Redmineup::Patches::Compatibility::SpritePatch)
19
- end
13
+ ApplicationHelper.prepend(Redmineup::Patches::Compatibility::SpritePatch)
@@ -1,9 +1,3 @@
1
- if Redmine::VERSION.to_s < "4"
2
- require 'redmineup/patches/compatibility/application_controller_patch'
3
- end
4
- if Redmine::VERSION.to_s < "5"
5
- require 'redmineup/patches/compatibility/user_patch'
6
- end
7
1
  if Redmine::VERSION.to_s < "6"
8
2
  require 'redmineup/patches/compatibility/sprite_patch'
9
3
  end
@@ -2,32 +2,23 @@ module Redmineup
2
2
  module Patches
3
3
  module LiquidPatch
4
4
  module StandardFilters
5
+ private
5
6
 
6
- def self.included(base)
7
- base.class_eval do
8
-
9
- private
10
-
11
- def to_number(obj)
12
- case obj
13
- when Float
14
- BigDecimal(obj.to_s)
15
- when Numeric
16
- obj
17
- when String
18
- (obj.strip =~ /^\d+\.\d+$/) ? BigDecimal(obj) : obj.to_i
19
- else
20
- 0
21
- end
22
- end
7
+ def to_number(obj)
8
+ case obj
9
+ when Float
10
+ BigDecimal(obj.to_s)
11
+ when Numeric
12
+ obj
13
+ when String
14
+ (obj.strip =~ /^\d+\.\d+$/) ? BigDecimal(obj) : obj.to_i
15
+ else
16
+ 0
23
17
  end
24
18
  end
25
-
26
19
  end
27
20
  end
28
21
  end
29
22
  end
30
-
31
- unless Liquid::StandardFilters.included_modules.include?(Redmineup::Patches::LiquidPatch::StandardFilters)
32
- Liquid::StandardFilters.send(:include, Redmineup::Patches::LiquidPatch::StandardFilters)
33
- end
23
+
24
+ Liquid::StandardFilters.prepend(Redmineup::Patches::LiquidPatch::StandardFilters)
@@ -1,3 +1,3 @@
1
1
  module Redmineup
2
- VERSION = '1.1.11'
2
+ VERSION = '1.1.13'
3
3
  end
data/lib/redmineup.rb CHANGED
@@ -45,6 +45,7 @@ require 'redmineup/helpers/external_assets_helper'
45
45
  require 'redmineup/helpers/form_tag_helper'
46
46
  require 'redmineup/helpers/calendars_helper'
47
47
  require 'redmineup/helpers/datetime_helper'
48
+ require 'redmineup/helpers/test_helper'
48
49
  require 'redmineup/assets_manager'
49
50
 
50
51
  require 'redmineup/patches/liquid_patch'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redmineup
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.11
4
+ version: 1.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - RedmineUP
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-29 00:00:00.000000000 Z
11
+ date: 2026-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -174,6 +174,7 @@ files:
174
174
  - lib/redmineup/helpers/external_assets_helper.rb
175
175
  - lib/redmineup/helpers/form_tag_helper.rb
176
176
  - lib/redmineup/helpers/tags_helper.rb
177
+ - lib/redmineup/helpers/test_helper.rb
177
178
  - lib/redmineup/helpers/vote_helper.rb
178
179
  - lib/redmineup/hooks/views_layouts_hook.rb
179
180
  - lib/redmineup/liquid/drops/attachment_drop.rb
@@ -193,10 +194,8 @@ files:
193
194
  - lib/redmineup/patches/action_cable_base_patch.rb
194
195
  - lib/redmineup/patches/action_cable_patch.rb
195
196
  - lib/redmineup/patches/auto_completes_controller_patch.rb
196
- - lib/redmineup/patches/compatibility/application_controller_patch.rb
197
197
  - lib/redmineup/patches/compatibility/routing_mapper_patch.rb
198
198
  - lib/redmineup/patches/compatibility/sprite_patch.rb
199
- - lib/redmineup/patches/compatibility/user_patch.rb
200
199
  - lib/redmineup/patches/compatibility_patch.rb
201
200
  - lib/redmineup/patches/liquid_patch.rb
202
201
  - lib/redmineup/settings.rb
@@ -1,32 +0,0 @@
1
- module Redmineup
2
- module Patches
3
- module Compatibility
4
- module ApplicationControllerPatch
5
- def self.included(base) # :nodoc:
6
- base.extend(ClassMethods)
7
- base.class_eval do
8
- unloadable # Send unloadable so it will not be unloaded in development
9
- end
10
- end
11
-
12
- module ClassMethods
13
- def before_action(*filters, &block)
14
- before_filter(*filters, &block)
15
- end
16
-
17
- def after_action(*filters, &block)
18
- after_filter(*filters, &block)
19
- end
20
-
21
- def skip_before_action(*filters, &block)
22
- skip_before_filter(*filters, &block)
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
29
-
30
- unless ActionController::Base.methods.include?(:before_action)
31
- ActionController::Base.send(:include,Redmineup::Patches::Compatibility::ApplicationControllerPatch)
32
- end
@@ -1,21 +0,0 @@
1
- module Redmineup
2
- module Patches
3
- module Compatibility
4
- module UserPatch
5
- def self.included(base)
6
- base.send(:include, InstanceMethods)
7
- end
8
-
9
- module InstanceMethods
10
- def atom_key
11
- rss_key
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
18
-
19
- unless User.included_modules.include?(Redmineup::Patches::Compatibility::UserPatch)
20
- User.send(:include, Redmineup::Patches::Compatibility::UserPatch)
21
- end