sidekiq-unique-jobs 7.0.0.beta22 → 7.0.0.beta27

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq-unique-jobs might be problematic. Click here for more details.

Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +88 -15
  3. data/README.md +55 -30
  4. data/lib/sidekiq_unique_jobs.rb +0 -1
  5. data/lib/sidekiq_unique_jobs/batch_delete.rb +1 -1
  6. data/lib/sidekiq_unique_jobs/changelog.rb +1 -1
  7. data/lib/sidekiq_unique_jobs/cli.rb +4 -2
  8. data/lib/sidekiq_unique_jobs/connection.rb +1 -1
  9. data/lib/sidekiq_unique_jobs/constants.rb +4 -1
  10. data/lib/sidekiq_unique_jobs/digests.rb +1 -1
  11. data/lib/sidekiq_unique_jobs/exceptions.rb +9 -9
  12. data/lib/sidekiq_unique_jobs/job.rb +5 -5
  13. data/lib/sidekiq_unique_jobs/json.rb +1 -1
  14. data/lib/sidekiq_unique_jobs/key.rb +1 -1
  15. data/lib/sidekiq_unique_jobs/lock.rb +1 -1
  16. data/lib/sidekiq_unique_jobs/lock/base_lock.rb +1 -1
  17. data/lib/sidekiq_unique_jobs/lock/client_validator.rb +1 -1
  18. data/lib/sidekiq_unique_jobs/lock/server_validator.rb +1 -1
  19. data/lib/sidekiq_unique_jobs/lock/until_and_while_executing.rb +1 -1
  20. data/lib/sidekiq_unique_jobs/lock/until_executed.rb +1 -1
  21. data/lib/sidekiq_unique_jobs/lock/until_executing.rb +1 -1
  22. data/lib/sidekiq_unique_jobs/lock/until_expired.rb +1 -1
  23. data/lib/sidekiq_unique_jobs/lock/validator.rb +3 -2
  24. data/lib/sidekiq_unique_jobs/lock/while_executing.rb +1 -1
  25. data/lib/sidekiq_unique_jobs/lock/while_executing_reject.rb +1 -1
  26. data/lib/sidekiq_unique_jobs/lock_args.rb +4 -4
  27. data/lib/sidekiq_unique_jobs/lock_config.rb +5 -5
  28. data/lib/sidekiq_unique_jobs/lock_digest.rb +2 -2
  29. data/lib/sidekiq_unique_jobs/lock_info.rb +1 -1
  30. data/lib/sidekiq_unique_jobs/lock_timeout.rb +1 -1
  31. data/lib/sidekiq_unique_jobs/lock_ttl.rb +1 -1
  32. data/lib/sidekiq_unique_jobs/locksmith.rb +1 -1
  33. data/lib/sidekiq_unique_jobs/logging.rb +3 -3
  34. data/lib/sidekiq_unique_jobs/logging/middleware_context.rb +2 -2
  35. data/lib/sidekiq_unique_jobs/lua/delete_by_digest.lua +1 -1
  36. data/lib/sidekiq_unique_jobs/lua/shared/_delete_from_queue.lua +3 -0
  37. data/lib/sidekiq_unique_jobs/middleware.rb +16 -4
  38. data/lib/sidekiq_unique_jobs/middleware/client.rb +5 -5
  39. data/lib/sidekiq_unique_jobs/middleware/server.rb +3 -3
  40. data/lib/sidekiq_unique_jobs/normalizer.rb +1 -1
  41. data/lib/sidekiq_unique_jobs/on_conflict.rb +1 -1
  42. data/lib/sidekiq_unique_jobs/on_conflict/log.rb +1 -1
  43. data/lib/sidekiq_unique_jobs/on_conflict/null_strategy.rb +1 -1
  44. data/lib/sidekiq_unique_jobs/on_conflict/raise.rb +1 -1
  45. data/lib/sidekiq_unique_jobs/on_conflict/reject.rb +1 -1
  46. data/lib/sidekiq_unique_jobs/on_conflict/replace.rb +1 -1
  47. data/lib/sidekiq_unique_jobs/on_conflict/reschedule.rb +1 -1
  48. data/lib/sidekiq_unique_jobs/on_conflict/strategy.rb +1 -1
  49. data/lib/sidekiq_unique_jobs/options_with_fallback.rb +1 -1
  50. data/lib/sidekiq_unique_jobs/orphans/lua_reaper.rb +1 -1
  51. data/lib/sidekiq_unique_jobs/orphans/manager.rb +35 -4
  52. data/lib/sidekiq_unique_jobs/orphans/null_reaper.rb +24 -0
  53. data/lib/sidekiq_unique_jobs/orphans/observer.rb +2 -2
  54. data/lib/sidekiq_unique_jobs/orphans/reaper.rb +5 -1
  55. data/lib/sidekiq_unique_jobs/orphans/ruby_reaper.rb +5 -5
  56. data/lib/sidekiq_unique_jobs/profiler.rb +1 -1
  57. data/lib/sidekiq_unique_jobs/redis.rb +1 -1
  58. data/lib/sidekiq_unique_jobs/redis/entity.rb +1 -1
  59. data/lib/sidekiq_unique_jobs/redis/hash.rb +1 -1
  60. data/lib/sidekiq_unique_jobs/redis/list.rb +1 -1
  61. data/lib/sidekiq_unique_jobs/redis/set.rb +1 -1
  62. data/lib/sidekiq_unique_jobs/redis/sorted_set.rb +1 -1
  63. data/lib/sidekiq_unique_jobs/redis/string.rb +1 -1
  64. data/lib/sidekiq_unique_jobs/rspec/matchers.rb +2 -2
  65. data/lib/sidekiq_unique_jobs/rspec/matchers/have_valid_sidekiq_options.rb +2 -2
  66. data/lib/sidekiq_unique_jobs/script.rb +1 -1
  67. data/lib/sidekiq_unique_jobs/script/caller.rb +2 -2
  68. data/lib/sidekiq_unique_jobs/sidekiq_unique_ext.rb +5 -5
  69. data/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb +1 -1
  70. data/lib/sidekiq_unique_jobs/sidekiq_worker_methods.rb +9 -3
  71. data/lib/sidekiq_unique_jobs/testing.rb +2 -1
  72. data/lib/sidekiq_unique_jobs/timing.rb +1 -1
  73. data/lib/sidekiq_unique_jobs/unlockable.rb +1 -1
  74. data/lib/sidekiq_unique_jobs/update_version.rb +1 -1
  75. data/lib/sidekiq_unique_jobs/upgrade_locks.rb +1 -1
  76. data/lib/sidekiq_unique_jobs/version.rb +1 -1
  77. data/lib/sidekiq_unique_jobs/version_check.rb +23 -4
  78. data/lib/sidekiq_unique_jobs/web.rb +1 -1
  79. data/lib/sidekiq_unique_jobs/web/helpers.rb +1 -1
  80. metadata +19 -6
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  #
5
5
  # Provides the sidekiq middleware that makes the gem work
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  #
9
9
  module Middleware
10
10
  include SidekiqUniqueJobs::Logging::Middleware
@@ -25,11 +25,19 @@ module SidekiqUniqueJobs
25
25
  def self.configure_server # rubocop:disable Metrics/MethodLength
26
26
  Sidekiq.configure_server do |config|
27
27
  config.client_middleware do |chain|
28
- chain.add SidekiqUniqueJobs::Middleware::Client
28
+ if defined?(Apartment::Sidekiq::Middleware::Client)
29
+ chain.insert_after Apartment::Sidekiq::Middleware::Client, SidekiqUniqueJobs::Middleware::Client
30
+ else
31
+ chain.add SidekiqUniqueJobs::Middleware::Client
32
+ end
29
33
  end
30
34
 
31
35
  config.server_middleware do |chain|
32
- chain.add SidekiqUniqueJobs::Middleware::Server
36
+ if defined?(Apartment::Sidekiq::Middleware::Server)
37
+ chain.insert_after Apartment::Sidekiq::Middleware::Server, SidekiqUniqueJobs::Middleware::Server
38
+ else
39
+ chain.add SidekiqUniqueJobs::Middleware::Server
40
+ end
33
41
  end
34
42
 
35
43
  config.on(:startup) do
@@ -51,7 +59,11 @@ module SidekiqUniqueJobs
51
59
  def self.configure_client
52
60
  Sidekiq.configure_client do |config|
53
61
  config.client_middleware do |chain|
54
- chain.add SidekiqUniqueJobs::Middleware::Client
62
+ if defined?(Apartment::Sidekiq::Middleware::Client)
63
+ chain.insert_after Apartment::Sidekiq::Middleware::Client, SidekiqUniqueJobs::Middleware::Client
64
+ else
65
+ chain.add SidekiqUniqueJobs::Middleware::Client
66
+ end
55
67
  end
56
68
  end
57
69
  end
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module Middleware
5
5
  # The unique sidekiq middleware for the client push
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Client
9
9
  prepend SidekiqUniqueJobs::Middleware
10
10
 
@@ -18,15 +18,15 @@ module SidekiqUniqueJobs
18
18
  #
19
19
  # @yield when uniqueness is disable
20
20
  # @yield when the lock is successful
21
- def call(*)
22
- lock { yield }
21
+ def call(*, &block)
22
+ lock(&block)
23
23
  end
24
24
 
25
25
  private
26
26
 
27
27
  def lock
28
- if (token = lock_instance.lock)
29
- yield token
28
+ if (_token = lock_instance.lock)
29
+ yield
30
30
  else
31
31
  warn_about_duplicate
32
32
  end
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module Middleware
5
5
  # The unique sidekiq middleware for the server processor
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Server
9
9
  prepend SidekiqUniqueJobs::Middleware
10
10
 
@@ -19,8 +19,8 @@ module SidekiqUniqueJobs
19
19
  #
20
20
  # @yield when uniqueness is disabled
21
21
  # @yield when owning the lock
22
- def call(*)
23
- lock_instance.execute { yield }
22
+ def call(*, &block)
23
+ lock_instance.execute(&block)
24
24
  end
25
25
  end
26
26
  end
@@ -3,7 +3,7 @@
3
3
  module SidekiqUniqueJobs
4
4
  # Normalizes hashes by dumping them to json and loading them from json
5
5
  #
6
- # @author Mikael Henriksson <mikael@zoolutions.se>
6
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
7
7
  module Normalizer
8
8
  extend SidekiqUniqueJobs::JSON
9
9
 
@@ -12,7 +12,7 @@ module SidekiqUniqueJobs
12
12
  #
13
13
  # Provides lock conflict resolutions
14
14
  #
15
- # @author Mikael Henriksson <mikael@zoolutions.se>
15
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
16
16
  #
17
17
  module OnConflict
18
18
  # A convenience method for using the configured strategies
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module OnConflict
5
5
  # Strategy to log information about conflict
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Log < OnConflict::Strategy
9
9
  include SidekiqUniqueJobs::Logging
10
10
 
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module OnConflict
5
5
  # Default conflict strategy class that does nothing
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class NullStrategy < OnConflict::Strategy
9
9
  # Do nothing on conflict
10
10
  # @return [nil]
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module OnConflict
5
5
  # Strategy to raise an error on conflict
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Raise < OnConflict::Strategy
9
9
  # Raise an error on conflict.
10
10
  # This will cause Sidekiq to retry the job
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module OnConflict
5
5
  # Strategy to send jobs to dead queue
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Reject < OnConflict::Strategy
9
9
  include SidekiqUniqueJobs::Timing
10
10
 
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module OnConflict
5
5
  # Strategy to replace the job on conflict
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Replace < OnConflict::Strategy
9
9
  #
10
10
  # @!attribute [r] queue
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  module OnConflict
5
5
  # Strategy to reschedule job on conflict
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  class Reschedule < OnConflict::Strategy
9
9
  include SidekiqUniqueJobs::SidekiqWorkerMethods
10
10
  include SidekiqUniqueJobs::Logging
@@ -5,7 +5,7 @@ module SidekiqUniqueJobs
5
5
  # Abstract conflict strategy class
6
6
  #
7
7
  # @abstract
8
- # @author Mikael Henriksson <mikael@zoolutions.se>
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
9
  class Strategy
10
10
  include SidekiqUniqueJobs::JSON
11
11
  include SidekiqUniqueJobs::Logging
@@ -7,7 +7,7 @@ module SidekiqUniqueJobs
7
7
  # 1. item (required)
8
8
  # 2. options (can be nil)
9
9
  # 3. worker_class (required, can be anything)
10
- # @author Mikael Henriksson <mikael@zoolutions.se>
10
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
11
11
  module OptionsWithFallback
12
12
  def self.included(base)
13
13
  base.send(:include, SidekiqUniqueJobs::SidekiqWorkerMethods)
@@ -7,7 +7,7 @@ module SidekiqUniqueJobs
7
7
  #
8
8
  # @note this is a much slower version of the lua script but does not crash redis
9
9
  #
10
- # @author Mikael Henriksson <mikael@zoolutions.se>
10
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
11
11
  #
12
12
  class LuaReaper < Reaper
13
13
  #
@@ -5,12 +5,13 @@ module SidekiqUniqueJobs
5
5
  #
6
6
  # Manages the orphan reaper
7
7
  #
8
- # @author Mikael Henriksson <mikael@zoolutions.se>
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
9
  #
10
10
  module Manager
11
11
  module_function
12
12
 
13
13
  DRIFT_FACTOR = 0.02
14
+ REAPERS = [:ruby, :lua].freeze
14
15
 
15
16
  include SidekiqUniqueJobs::Connection
16
17
  include SidekiqUniqueJobs::Logging
@@ -22,8 +23,8 @@ module SidekiqUniqueJobs
22
23
  # @return [Concurrent::TimerTask] the task that was started
23
24
  #
24
25
  def start # rubocop:disable
25
- return if registered?
26
26
  return if disabled?
27
+ return if registered?
27
28
 
28
29
  with_logging_context do
29
30
  register_reaper_process
@@ -41,6 +42,9 @@ module SidekiqUniqueJobs
41
42
  # @return [Boolean]
42
43
  #
43
44
  def stop
45
+ return if disabled?
46
+ return if unregistered?
47
+
44
48
  with_logging_context do
45
49
  log_info("Stopping Reaper")
46
50
  unregister_reaper_process
@@ -114,7 +118,7 @@ module SidekiqUniqueJobs
114
118
  end
115
119
 
116
120
  #
117
- # Checks if a reaper is already registered
121
+ # Checks if a reaper is registered
118
122
  #
119
123
  #
120
124
  # @return [true, false]
@@ -125,8 +129,35 @@ module SidekiqUniqueJobs
125
129
  end
126
130
  end
127
131
 
132
+ #
133
+ # Checks if that reapers are not registerd
134
+ #
135
+ # @see registered?
136
+ #
137
+ # @return [true, false]
138
+ #
139
+ def unregistered?
140
+ !registered?
141
+ end
142
+
143
+ #
144
+ # Checks if reaping is disabled
145
+ #
146
+ # @see enabled?
147
+ #
148
+ # @return [true, false]
149
+ #
128
150
  def disabled?
129
- reaper == :none
151
+ !enabled?
152
+ end
153
+
154
+ #
155
+ # Checks if reaping is enabled
156
+ #
157
+ # @return [true, false]
158
+ #
159
+ def enabled?
160
+ REAPERS.include?(reaper)
130
161
  end
131
162
 
132
163
  #
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SidekiqUniqueJobs
4
+ module Orphans
5
+ #
6
+ # Class DeleteOrphans provides deletion of orphaned digests
7
+ #
8
+ # @note this is a much slower version of the lua script but does not crash redis
9
+ #
10
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
11
+ #
12
+ class NullReaper < Reaper
13
+ #
14
+ # Delete orphaned digests
15
+ #
16
+ #
17
+ # @return [Integer] the number of reaped locks
18
+ #
19
+ def call
20
+ # NO OP
21
+ end
22
+ end
23
+ end
24
+ end
@@ -6,13 +6,13 @@ module SidekiqUniqueJobs
6
6
  #
7
7
  # @note this is a much slower version of the lua script but does not crash redis
8
8
  #
9
- # @author Mikael Henriksson <mikael@zoolutions.se>
9
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
10
10
  #
11
11
  module Orphans
12
12
  #
13
13
  # Observes the Orphan::Manager and provides information about each execution
14
14
  #
15
- # @author Mikael Henriksson <mikael@zoolutions.se>
15
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
16
16
  #
17
17
  class Observer
18
18
  include SidekiqUniqueJobs::Logging
@@ -7,7 +7,7 @@ module SidekiqUniqueJobs
7
7
  #
8
8
  # @note this is a much slower version of the lua script but does not crash redis
9
9
  #
10
- # @author Mikael Henriksson <mikael@zoolutions.se>
10
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
11
11
  #
12
12
  class Reaper
13
13
  include SidekiqUniqueJobs::Connection
@@ -17,12 +17,16 @@ module SidekiqUniqueJobs
17
17
 
18
18
  require_relative "lua_reaper"
19
19
  require_relative "ruby_reaper"
20
+ require_relative "null_reaper"
20
21
 
21
22
  #
22
23
  # @return [Hash<Symbol, SidekiqUniqueJobs::Orphans::Reaper] the current implementation of reapers
23
24
  REAPERS = {
24
25
  lua: SidekiqUniqueJobs::Orphans::LuaReaper,
25
26
  ruby: SidekiqUniqueJobs::Orphans::RubyReaper,
27
+ none: SidekiqUniqueJobs::Orphans::NullReaper,
28
+ nil => SidekiqUniqueJobs::Orphans::NullReaper,
29
+ false => SidekiqUniqueJobs::Orphans::NullReaper,
26
30
  }.freeze
27
31
 
28
32
  #
@@ -7,7 +7,7 @@ module SidekiqUniqueJobs
7
7
  #
8
8
  # @note this is a much slower version of the lua script but does not crash redis
9
9
  #
10
- # @author Mikael Henriksson <mikael@zoolutions.se>
10
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
11
11
  #
12
12
  class RubyReaper < Reaper
13
13
  #
@@ -135,6 +135,8 @@ module SidekiqUniqueJobs
135
135
  return true if load_json(job)[LOCK_DIGEST] == digest
136
136
  end
137
137
  end
138
+
139
+ false
138
140
  end
139
141
  end
140
142
 
@@ -151,7 +153,7 @@ module SidekiqUniqueJobs
151
153
  conn.sscan_each("queues", &block)
152
154
  end
153
155
 
154
- def entries(conn, queue) # rubocop:disable Metrics/MethodLength
156
+ def entries(conn, queue, &block) # rubocop:disable Metrics/MethodLength
155
157
  queue_key = "queue:#{queue}"
156
158
  initial_size = conn.llen(queue_key)
157
159
  deleted_size = 0
@@ -166,9 +168,7 @@ module SidekiqUniqueJobs
166
168
 
167
169
  break if entries.empty?
168
170
 
169
- entries.each do |entry|
170
- yield entry
171
- end
171
+ entries.each(&block)
172
172
 
173
173
  deleted_size = initial_size - conn.llen(queue_key)
174
174
  end
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  #
5
5
  # Class MethodProfiler provides method level profiling
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  #
9
9
  class Profiler
10
10
  def self.patch(klass, methods, name) # rubocop:disable Metrics/MethodLength
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  #
5
5
  # Augments and enhances redis with object oriented methods
6
6
  #
7
- # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
8
8
  #
9
9
  module Redis
10
10
  end
@@ -5,7 +5,7 @@ module SidekiqUniqueJobs
5
5
  #
6
6
  # Class Entity functions as a base class for redis types
7
7
  #
8
- # @author Mikael Henriksson <mikael@zoolutions.se>
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
9
  #
10
10
  class Entity
11
11
  # includes "SidekiqUniqueJobs::Logging"
@@ -5,7 +5,7 @@ module SidekiqUniqueJobs
5
5
  #
6
6
  # Class Hash provides convenient access to redis hashes
7
7
  #
8
- # @author Mikael Henriksson <mikael@zoolutions.se>
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
9
  #
10
10
  class Hash < Entity
11
11
  #
@@ -5,7 +5,7 @@ module SidekiqUniqueJobs
5
5
  #
6
6
  # Class List provides convenient access to redis hashes
7
7
  #
8
- # @author Mikael Henriksson <mikael@zoolutions.se>
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
9
  #
10
10
  class List < Entity
11
11
  #
@@ -5,7 +5,7 @@ module SidekiqUniqueJobs
5
5
  #
6
6
  # Class Set provides convenient access to redis sets
7
7
  #
8
- # @author Mikael Henriksson <mikael@zoolutions.se>
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
9
  #
10
10
  class Set < Entity
11
11
  #
@@ -5,7 +5,7 @@ module SidekiqUniqueJobs
5
5
  #
6
6
  # Class SortedSet provides convenient access to redis sorted sets
7
7
  #
8
- # @author Mikael Henriksson <mikael@zoolutions.se>
8
+ # @author Mikael Henriksson <mikael@mhenrixon.com>
9
9
  #
10
10
  class SortedSet < Entity
11
11
  #