skylight-core 4.0.0.alpha4 → 4.0.0.beta
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 +4 -4
- data/lib/skylight/core/normalizers/active_job/perform.rb +22 -6
- data/lib/skylight/core/probes/action_view.rb +12 -4
- data/lib/skylight/core/version.rb +1 -1
- metadata +2 -7
- data/lib/skylight/core/vendor/active_support/notifications.rb +0 -207
- data/lib/skylight/core/vendor/active_support/per_thread_registry.rb +0 -52
- data/lib/skylight/core/vendor/thread_safe/non_concurrent_cache_backend.rb +0 -133
- data/lib/skylight/core/vendor/thread_safe/synchronized_cache_backend.rb +0 -76
- data/lib/skylight/core/vendor/thread_safe.rb +0 -126
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab9eed2e498ca4b55dfed12501b36fdea71433e0505a2c34733a0d025b03bbdd
|
4
|
+
data.tar.gz: c5a4eed17eb02f2beb8e0b54e90196429467676a9b79dbff10ecd24d0cd9c31d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 823f266c1a844a4e8424569b34f35afb9b5998c2688b66e299bbc4ad16c335aceffa17d24ed0c38243d89f7b8b16b202f65fdb8d416dc13a830e3505848b86a2
|
7
|
+
data.tar.gz: 6c134666859922615c8083298fd42d7d7b04bbb6d2845ab08071daadb65fcc19aa471361cc197b84ddecb708694b3bebb3d8e35f9f825985348c5eacf4809afe
|
@@ -11,13 +11,14 @@ module Skylight::Core
|
|
11
11
|
adapter_name = normalize_adapter_name(payload[:adapter])
|
12
12
|
desc = "{ adapter: '#{adapter_name}', queue: '#{payload[:job].queue_name}' }"
|
13
13
|
|
14
|
-
maybe_set_endpoint(trace,
|
14
|
+
maybe_set_endpoint(trace, payload)
|
15
15
|
|
16
16
|
[CAT, title, desc]
|
17
17
|
end
|
18
18
|
|
19
19
|
def normalize_after(trace, _span, _name, payload)
|
20
|
-
return unless config.enable_segments?
|
20
|
+
return unless config.enable_segments? && assign_endpoint?(trace, payload)
|
21
|
+
|
21
22
|
trace.segment = payload[:job].queue_name
|
22
23
|
end
|
23
24
|
|
@@ -30,14 +31,29 @@ module Skylight::Core
|
|
30
31
|
"active_job"
|
31
32
|
end
|
32
33
|
|
33
|
-
def maybe_set_endpoint(trace,
|
34
|
-
trace
|
34
|
+
def maybe_set_endpoint(trace, payload)
|
35
|
+
if assign_endpoint?(trace, payload)
|
36
|
+
trace.endpoint = normalize_title(payload[:job])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def assign_endpoint?(trace, payload)
|
41
|
+
# Always assign the endpoint if it has not yet been assigned by the ActiveJob probe.
|
42
|
+
return true unless trace.endpoint
|
43
|
+
return unless defined?(Skylight::Core::Probes::ActiveJob::Probe::TITLE)
|
35
44
|
|
36
45
|
# If a job is called using #perform_now inside a controller action
|
37
46
|
# or within another job's #perform method, we do not want this to
|
38
47
|
# overwrite the existing endpoint name (unless it is the default from ActiveJob).
|
39
|
-
|
40
|
-
|
48
|
+
#
|
49
|
+
# If the current endpoint name matches this payload, return true to allow the
|
50
|
+
# segment to be assigned by normalize_after.
|
51
|
+
trace.endpoint == Skylight::Core::Probes::ActiveJob::Probe::TITLE ||
|
52
|
+
trace.endpoint == normalize_title(payload[:job])
|
53
|
+
end
|
54
|
+
|
55
|
+
def normalize_title(job_instance)
|
56
|
+
job_instance.class.to_s
|
41
57
|
end
|
42
58
|
end
|
43
59
|
end
|
@@ -6,12 +6,20 @@ module Skylight::Core
|
|
6
6
|
::ActionView::TemplateRenderer.class_eval do
|
7
7
|
alias_method :render_with_layout_without_sk, :render_with_layout
|
8
8
|
|
9
|
-
def render_with_layout(
|
9
|
+
def render_with_layout(*args, &block) #:nodoc:
|
10
|
+
path, locals = case args.length
|
11
|
+
when 2
|
12
|
+
args
|
13
|
+
when 3
|
14
|
+
# Rails > 6.0.0.beta1 prepends an additional `view` argument
|
15
|
+
args.last(2)
|
16
|
+
end
|
17
|
+
|
10
18
|
layout = nil
|
11
19
|
|
12
20
|
if path
|
13
21
|
layout =
|
14
|
-
if ::ActionView
|
22
|
+
if ::ActionView::VERSION::MAJOR >= 5
|
15
23
|
find_layout(path, locals.keys, [formats.first])
|
16
24
|
else
|
17
25
|
find_layout(path, locals.keys)
|
@@ -20,10 +28,10 @@ module Skylight::Core
|
|
20
28
|
|
21
29
|
if layout
|
22
30
|
instrument(:template, identifier: layout.identifier) do
|
23
|
-
render_with_layout_without_sk(
|
31
|
+
render_with_layout_without_sk(*args, &block)
|
24
32
|
end
|
25
33
|
else
|
26
|
-
render_with_layout_without_sk(
|
34
|
+
render_with_layout_without_sk(*args, &block)
|
27
35
|
end
|
28
36
|
end
|
29
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skylight-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0.
|
4
|
+
version: 4.0.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tilde, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -244,11 +244,6 @@ files:
|
|
244
244
|
- lib/skylight/core/util/logging.rb
|
245
245
|
- lib/skylight/core/util/platform.rb
|
246
246
|
- lib/skylight/core/util/proxy.rb
|
247
|
-
- lib/skylight/core/vendor/active_support/notifications.rb
|
248
|
-
- lib/skylight/core/vendor/active_support/per_thread_registry.rb
|
249
|
-
- lib/skylight/core/vendor/thread_safe.rb
|
250
|
-
- lib/skylight/core/vendor/thread_safe/non_concurrent_cache_backend.rb
|
251
|
-
- lib/skylight/core/vendor/thread_safe/synchronized_cache_backend.rb
|
252
247
|
- lib/skylight/core/version.rb
|
253
248
|
- lib/skylight/core/vm/gc.rb
|
254
249
|
homepage: https://www.skylight.io
|
@@ -1,207 +0,0 @@
|
|
1
|
-
require 'skylight/core/vendor/active_support/notifications/instrumenter'
|
2
|
-
require 'skylight/core/vendor/active_support/notifications/fanout'
|
3
|
-
require 'skylight/core/vendor/active_support/per_thread_registry'
|
4
|
-
|
5
|
-
module ActiveSupport
|
6
|
-
# = Notifications
|
7
|
-
#
|
8
|
-
# <tt>ActiveSupport::Notifications</tt> provides an instrumentation API for
|
9
|
-
# Ruby.
|
10
|
-
#
|
11
|
-
# == Instrumenters
|
12
|
-
#
|
13
|
-
# To instrument an event you just need to do:
|
14
|
-
#
|
15
|
-
# ActiveSupport::Notifications.instrument('render', extra: :information) do
|
16
|
-
# render text: 'Foo'
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# That executes the block first and notifies all subscribers once done.
|
20
|
-
#
|
21
|
-
# In the example above +render+ is the name of the event, and the rest is called
|
22
|
-
# the _payload_. The payload is a mechanism that allows instrumenters to pass
|
23
|
-
# extra information to subscribers. Payloads consist of a hash whose contents
|
24
|
-
# are arbitrary and generally depend on the event.
|
25
|
-
#
|
26
|
-
# == Subscribers
|
27
|
-
#
|
28
|
-
# You can consume those events and the information they provide by registering
|
29
|
-
# a subscriber.
|
30
|
-
#
|
31
|
-
# ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
|
32
|
-
# name # => String, name of the event (such as 'render' from above)
|
33
|
-
# start # => Time, when the instrumented block started execution
|
34
|
-
# finish # => Time, when the instrumented block ended execution
|
35
|
-
# id # => String, unique ID for this notification
|
36
|
-
# payload # => Hash, the payload
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# For instance, let's store all "render" events in an array:
|
40
|
-
#
|
41
|
-
# events = []
|
42
|
-
#
|
43
|
-
# ActiveSupport::Notifications.subscribe('render') do |*args|
|
44
|
-
# events << ActiveSupport::Notifications::Event.new(*args)
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# That code returns right away, you are just subscribing to "render" events.
|
48
|
-
# The block is saved and will be called whenever someone instruments "render":
|
49
|
-
#
|
50
|
-
# ActiveSupport::Notifications.instrument('render', extra: :information) do
|
51
|
-
# render text: 'Foo'
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# event = events.first
|
55
|
-
# event.name # => "render"
|
56
|
-
# event.duration # => 10 (in milliseconds)
|
57
|
-
# event.payload # => { extra: :information }
|
58
|
-
#
|
59
|
-
# The block in the <tt>subscribe</tt> call gets the name of the event, start
|
60
|
-
# timestamp, end timestamp, a string with a unique identifier for that event
|
61
|
-
# (something like "535801666f04d0298cd6"), and a hash with the payload, in
|
62
|
-
# that order.
|
63
|
-
#
|
64
|
-
# If an exception happens during that particular instrumentation the payload will
|
65
|
-
# have a key <tt>:exception</tt> with an array of two elements as value: a string with
|
66
|
-
# the name of the exception class, and the exception message.
|
67
|
-
#
|
68
|
-
# As the previous example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
|
69
|
-
# is able to take the arguments as they come and provide an object-oriented
|
70
|
-
# interface to that data.
|
71
|
-
#
|
72
|
-
# It is also possible to pass an object as the second parameter passed to the
|
73
|
-
# <tt>subscribe</tt> method instead of a block:
|
74
|
-
#
|
75
|
-
# module ActionController
|
76
|
-
# class PageRequest
|
77
|
-
# def call(name, started, finished, unique_id, payload)
|
78
|
-
# Rails.logger.debug ['notification:', name, started, finished, unique_id, payload].join(' ')
|
79
|
-
# end
|
80
|
-
# end
|
81
|
-
# end
|
82
|
-
#
|
83
|
-
# ActiveSupport::Notifications.subscribe('process_action.action_controller', ActionController::PageRequest.new)
|
84
|
-
#
|
85
|
-
# resulting in the following output within the logs including a hash with the payload:
|
86
|
-
#
|
87
|
-
# notification: process_action.action_controller 2012-04-13 01:08:35 +0300 2012-04-13 01:08:35 +0300 af358ed7fab884532ec7 {
|
88
|
-
# controller: "Devise::SessionsController",
|
89
|
-
# action: "new",
|
90
|
-
# params: {"action"=>"new", "controller"=>"devise/sessions"},
|
91
|
-
# format: :html,
|
92
|
-
# method: "GET",
|
93
|
-
# path: "/login/sign_in",
|
94
|
-
# status: 200,
|
95
|
-
# view_runtime: 279.3080806732178,
|
96
|
-
# db_runtime: 40.053
|
97
|
-
# }
|
98
|
-
#
|
99
|
-
# You can also subscribe to all events whose name matches a certain regexp:
|
100
|
-
#
|
101
|
-
# ActiveSupport::Notifications.subscribe(/render/) do |*args|
|
102
|
-
# ...
|
103
|
-
# end
|
104
|
-
#
|
105
|
-
# and even pass no argument to <tt>subscribe</tt>, in which case you are subscribing
|
106
|
-
# to all events.
|
107
|
-
#
|
108
|
-
# == Temporary Subscriptions
|
109
|
-
#
|
110
|
-
# Sometimes you do not want to subscribe to an event for the entire life of
|
111
|
-
# the application. There are two ways to unsubscribe.
|
112
|
-
#
|
113
|
-
# WARNING: The instrumentation framework is designed for long-running subscribers,
|
114
|
-
# use this feature sparingly because it wipes some internal caches and that has
|
115
|
-
# a negative impact on performance.
|
116
|
-
#
|
117
|
-
# === Subscribe While a Block Runs
|
118
|
-
#
|
119
|
-
# You can subscribe to some event temporarily while some block runs. For
|
120
|
-
# example, in
|
121
|
-
#
|
122
|
-
# callback = lambda {|*args| ... }
|
123
|
-
# ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
|
124
|
-
# ...
|
125
|
-
# end
|
126
|
-
#
|
127
|
-
# the callback will be called for all "sql.active_record" events instrumented
|
128
|
-
# during the execution of the block. The callback is unsubscribed automatically
|
129
|
-
# after that.
|
130
|
-
#
|
131
|
-
# === Manual Unsubscription
|
132
|
-
#
|
133
|
-
# The +subscribe+ method returns a subscriber object:
|
134
|
-
#
|
135
|
-
# subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
|
136
|
-
# ...
|
137
|
-
# end
|
138
|
-
#
|
139
|
-
# To prevent that block from being called anymore, just unsubscribe passing
|
140
|
-
# that reference:
|
141
|
-
#
|
142
|
-
# ActiveSupport::Notifications.unsubscribe(subscriber)
|
143
|
-
#
|
144
|
-
# == Default Queue
|
145
|
-
#
|
146
|
-
# Notifications ships with a queue implementation that consumes and publish events
|
147
|
-
# to log subscribers in a thread. You can use any queue implementation you want.
|
148
|
-
#
|
149
|
-
module Notifications
|
150
|
-
class << self
|
151
|
-
attr_accessor :notifier
|
152
|
-
|
153
|
-
def publish(name, *args)
|
154
|
-
notifier.publish(name, *args)
|
155
|
-
end
|
156
|
-
|
157
|
-
def instrument(name, payload = {})
|
158
|
-
if notifier.listening?(name)
|
159
|
-
instrumenter.instrument(name, payload) { yield payload if block_given? }
|
160
|
-
else
|
161
|
-
yield payload if block_given?
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def subscribe(*args, &block)
|
166
|
-
notifier.subscribe(*args, &block)
|
167
|
-
end
|
168
|
-
|
169
|
-
def subscribed(callback, *args, &block)
|
170
|
-
subscriber = subscribe(*args, &callback)
|
171
|
-
yield
|
172
|
-
ensure
|
173
|
-
unsubscribe(subscriber)
|
174
|
-
end
|
175
|
-
|
176
|
-
def unsubscribe(args)
|
177
|
-
notifier.unsubscribe(args)
|
178
|
-
end
|
179
|
-
|
180
|
-
def instrumenter
|
181
|
-
InstrumentationRegistry.instrumenter_for(notifier)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# This class is a registry which holds all of the +Instrumenter+ objects
|
186
|
-
# in a particular thread local. To access the +Instrumenter+ object for a
|
187
|
-
# particular +notifier+, you can call the following method:
|
188
|
-
#
|
189
|
-
# InstrumentationRegistry.instrumenter_for(notifier)
|
190
|
-
#
|
191
|
-
# The instrumenters for multiple notifiers are held in a single instance of
|
192
|
-
# this class.
|
193
|
-
class InstrumentationRegistry # :nodoc:
|
194
|
-
extend ActiveSupport::PerThreadRegistry
|
195
|
-
|
196
|
-
def initialize
|
197
|
-
@registry = {}
|
198
|
-
end
|
199
|
-
|
200
|
-
def instrumenter_for(notifier)
|
201
|
-
@registry[notifier] ||= Instrumenter.new(notifier)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
self.notifier = Fanout.new
|
206
|
-
end
|
207
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module ActiveSupport
|
2
|
-
# This module is used to encapsulate access to thread local variables.
|
3
|
-
#
|
4
|
-
# Instead of polluting the thread locals namespace:
|
5
|
-
#
|
6
|
-
# Thread.current[:connection_handler]
|
7
|
-
#
|
8
|
-
# you define a class that extends this module:
|
9
|
-
#
|
10
|
-
# module ActiveRecord
|
11
|
-
# class RuntimeRegistry
|
12
|
-
# extend ActiveSupport::PerThreadRegistry
|
13
|
-
#
|
14
|
-
# attr_accessor :connection_handler
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# and invoke the declared instance accessors as class methods. So
|
19
|
-
#
|
20
|
-
# ActiveRecord::RuntimeRegistry.connection_handler = connection_handler
|
21
|
-
#
|
22
|
-
# sets a connection handler local to the current thread, and
|
23
|
-
#
|
24
|
-
# ActiveRecord::RuntimeRegistry.connection_handler
|
25
|
-
#
|
26
|
-
# returns a connection handler local to the current thread.
|
27
|
-
#
|
28
|
-
# This feature is accomplished by instantiating the class and storing the
|
29
|
-
# instance as a thread local keyed by the class name. In the example above
|
30
|
-
# a key "ActiveRecord::RuntimeRegistry" is stored in <tt>Thread.current</tt>.
|
31
|
-
# The class methods proxy to said thread local instance.
|
32
|
-
#
|
33
|
-
# If the class has an initializer, it must accept no arguments.
|
34
|
-
module PerThreadRegistry
|
35
|
-
protected
|
36
|
-
|
37
|
-
def method_missing(name, *args, &block) # :nodoc:
|
38
|
-
# Caches the method definition as a singleton method of the receiver.
|
39
|
-
define_singleton_method(name) do |*a, &b|
|
40
|
-
per_thread_registry_instance.public_send(name, *a, &b)
|
41
|
-
end
|
42
|
-
|
43
|
-
send(name, *args, &block)
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def per_thread_registry_instance
|
49
|
-
Thread.current[name] ||= new
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,133 +0,0 @@
|
|
1
|
-
module ThreadSafe
|
2
|
-
class NonConcurrentCacheBackend
|
3
|
-
# WARNING: all public methods of the class must operate on the @backend directly without calling each other. This is important
|
4
|
-
# because of the SynchronizedCacheBackend which uses a non-reentrant mutex for perfomance reasons.
|
5
|
-
def initialize(options = nil)
|
6
|
-
@backend = {}
|
7
|
-
end
|
8
|
-
|
9
|
-
def [](key)
|
10
|
-
@backend[key]
|
11
|
-
end
|
12
|
-
|
13
|
-
def []=(key, value)
|
14
|
-
@backend[key] = value
|
15
|
-
end
|
16
|
-
|
17
|
-
def compute_if_absent(key)
|
18
|
-
if NULL != (stored_value = @backend.fetch(key, NULL))
|
19
|
-
stored_value
|
20
|
-
else
|
21
|
-
@backend[key] = yield
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def replace_pair(key, old_value, new_value)
|
26
|
-
if pair?(key, old_value)
|
27
|
-
@backend[key] = new_value
|
28
|
-
true
|
29
|
-
else
|
30
|
-
false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def replace_if_exists(key, new_value)
|
35
|
-
if NULL != (stored_value = @backend.fetch(key, NULL))
|
36
|
-
@backend[key] = new_value
|
37
|
-
stored_value
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def compute_if_present(key)
|
42
|
-
if NULL != (stored_value = @backend.fetch(key, NULL))
|
43
|
-
store_computed_value(key, yield(stored_value))
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def compute(key)
|
48
|
-
store_computed_value(key, yield(@backend[key]))
|
49
|
-
end
|
50
|
-
|
51
|
-
def merge_pair(key, value)
|
52
|
-
if NULL == (stored_value = @backend.fetch(key, NULL))
|
53
|
-
@backend[key] = value
|
54
|
-
else
|
55
|
-
store_computed_value(key, yield(stored_value))
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def get_and_set(key, value)
|
60
|
-
stored_value = @backend[key]
|
61
|
-
@backend[key] = value
|
62
|
-
stored_value
|
63
|
-
end
|
64
|
-
|
65
|
-
def key?(key)
|
66
|
-
@backend.key?(key)
|
67
|
-
end
|
68
|
-
|
69
|
-
def value?(value)
|
70
|
-
@backend.value?(value)
|
71
|
-
end
|
72
|
-
|
73
|
-
def delete(key)
|
74
|
-
@backend.delete(key)
|
75
|
-
end
|
76
|
-
|
77
|
-
def delete_pair(key, value)
|
78
|
-
if pair?(key, value)
|
79
|
-
@backend.delete(key)
|
80
|
-
true
|
81
|
-
else
|
82
|
-
false
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def clear
|
87
|
-
@backend.clear
|
88
|
-
self
|
89
|
-
end
|
90
|
-
|
91
|
-
def each_pair
|
92
|
-
dupped_backend.each_pair do |k, v|
|
93
|
-
yield k, v
|
94
|
-
end
|
95
|
-
self
|
96
|
-
end
|
97
|
-
|
98
|
-
def size
|
99
|
-
@backend.size
|
100
|
-
end
|
101
|
-
|
102
|
-
def get_or_default(key, default_value)
|
103
|
-
@backend.fetch(key, default_value)
|
104
|
-
end
|
105
|
-
|
106
|
-
alias_method :_get, :[]
|
107
|
-
alias_method :_set, :[]=
|
108
|
-
private :_get, :_set
|
109
|
-
private
|
110
|
-
def initialize_copy(other)
|
111
|
-
super
|
112
|
-
@backend = {}
|
113
|
-
self
|
114
|
-
end
|
115
|
-
|
116
|
-
def dupped_backend
|
117
|
-
@backend.dup
|
118
|
-
end
|
119
|
-
|
120
|
-
def pair?(key, expected_value)
|
121
|
-
NULL != (stored_value = @backend.fetch(key, NULL)) && expected_value.equal?(stored_value)
|
122
|
-
end
|
123
|
-
|
124
|
-
def store_computed_value(key, new_value)
|
125
|
-
if new_value.nil?
|
126
|
-
@backend.delete(key)
|
127
|
-
nil
|
128
|
-
else
|
129
|
-
@backend[key] = new_value
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
module ThreadSafe
|
2
|
-
class SynchronizedCacheBackend < NonConcurrentCacheBackend
|
3
|
-
require 'mutex_m'
|
4
|
-
include Mutex_m
|
5
|
-
# WARNING: Mutex_m is a non-reentrant lock, so the synchronized methods are not allowed to call each other.
|
6
|
-
|
7
|
-
def [](key)
|
8
|
-
synchronize { super }
|
9
|
-
end
|
10
|
-
|
11
|
-
def []=(key, value)
|
12
|
-
synchronize { super }
|
13
|
-
end
|
14
|
-
|
15
|
-
def compute_if_absent(key)
|
16
|
-
synchronize { super }
|
17
|
-
end
|
18
|
-
|
19
|
-
def compute_if_present(key)
|
20
|
-
synchronize { super }
|
21
|
-
end
|
22
|
-
|
23
|
-
def compute(key)
|
24
|
-
synchronize { super }
|
25
|
-
end
|
26
|
-
|
27
|
-
def merge_pair(key, value)
|
28
|
-
synchronize { super }
|
29
|
-
end
|
30
|
-
|
31
|
-
def replace_pair(key, old_value, new_value)
|
32
|
-
synchronize { super }
|
33
|
-
end
|
34
|
-
|
35
|
-
def replace_if_exists(key, new_value)
|
36
|
-
synchronize { super }
|
37
|
-
end
|
38
|
-
|
39
|
-
def get_and_set(key, value)
|
40
|
-
synchronize { super }
|
41
|
-
end
|
42
|
-
|
43
|
-
def key?(key)
|
44
|
-
synchronize { super }
|
45
|
-
end
|
46
|
-
|
47
|
-
def value?(value)
|
48
|
-
synchronize { super }
|
49
|
-
end
|
50
|
-
|
51
|
-
def delete(key)
|
52
|
-
synchronize { super }
|
53
|
-
end
|
54
|
-
|
55
|
-
def delete_pair(key, value)
|
56
|
-
synchronize { super }
|
57
|
-
end
|
58
|
-
|
59
|
-
def clear
|
60
|
-
synchronize { super }
|
61
|
-
end
|
62
|
-
|
63
|
-
def size
|
64
|
-
synchronize { super }
|
65
|
-
end
|
66
|
-
|
67
|
-
def get_or_default(key, default_value)
|
68
|
-
synchronize { super }
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
def dupped_backend
|
73
|
-
synchronize { super }
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
module ThreadSafe
|
4
|
-
autoload :NonConcurrentCacheBackend, 'skylight/core/vendor/thread_safe/non_concurrent_cache_backend'
|
5
|
-
autoload :SynchronizedCacheBackend, 'skylight/core/vendor/thread_safe/synchronized_cache_backend'
|
6
|
-
|
7
|
-
ConcurrentCacheBackend = SynchronizedCacheBackend
|
8
|
-
|
9
|
-
class Cache < ConcurrentCacheBackend
|
10
|
-
KEY_ERROR = defined?(KeyError) ? KeyError : IndexError # there is no KeyError in 1.8 mode
|
11
|
-
|
12
|
-
def initialize(options = nil, &block)
|
13
|
-
if options.kind_of?(::Hash)
|
14
|
-
validate_options_hash!(options)
|
15
|
-
else
|
16
|
-
options = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
super(options)
|
20
|
-
@default_proc = block
|
21
|
-
end
|
22
|
-
|
23
|
-
def [](key)
|
24
|
-
if value = super
|
25
|
-
value
|
26
|
-
elsif @default_proc && !key?(key)
|
27
|
-
@default_proc.call(self, key)
|
28
|
-
else
|
29
|
-
value
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def fetch(key, default_value = NULL)
|
34
|
-
if NULL != (value = get_or_default(key, NULL))
|
35
|
-
value
|
36
|
-
elsif block_given?
|
37
|
-
yield key
|
38
|
-
elsif NULL != default_value
|
39
|
-
default_value
|
40
|
-
else
|
41
|
-
raise KEY_ERROR, 'key not found'
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def put_if_absent(key, value)
|
46
|
-
computed = false
|
47
|
-
result = compute_if_absent(key) do
|
48
|
-
computed = true
|
49
|
-
value
|
50
|
-
end
|
51
|
-
computed ? nil : result
|
52
|
-
end unless method_defined?(:put_if_absent)
|
53
|
-
|
54
|
-
def value?(value)
|
55
|
-
each_value do |v|
|
56
|
-
return true if value.equal?(v)
|
57
|
-
end
|
58
|
-
false
|
59
|
-
end unless method_defined?(:value?)
|
60
|
-
|
61
|
-
def keys
|
62
|
-
arr = []
|
63
|
-
each_pair {|k, v| arr << k}
|
64
|
-
arr
|
65
|
-
end unless method_defined?(:keys)
|
66
|
-
|
67
|
-
def values
|
68
|
-
arr = []
|
69
|
-
each_pair {|k, v| arr << v}
|
70
|
-
arr
|
71
|
-
end unless method_defined?(:values)
|
72
|
-
|
73
|
-
def each_key
|
74
|
-
each_pair {|k, v| yield k}
|
75
|
-
end unless method_defined?(:each_key)
|
76
|
-
|
77
|
-
def each_value
|
78
|
-
each_pair {|k, v| yield v}
|
79
|
-
end unless method_defined?(:each_value)
|
80
|
-
|
81
|
-
def empty?
|
82
|
-
each_pair {|k, v| return false}
|
83
|
-
true
|
84
|
-
end unless method_defined?(:empty?)
|
85
|
-
|
86
|
-
def size
|
87
|
-
count = 0
|
88
|
-
each_pair {|k, v| count += 1}
|
89
|
-
count
|
90
|
-
end unless method_defined?(:size)
|
91
|
-
|
92
|
-
def marshal_dump
|
93
|
-
raise TypeError, "can't dump hash with default proc" if @default_proc
|
94
|
-
h = {}
|
95
|
-
each_pair {|k, v| h[k] = v}
|
96
|
-
h
|
97
|
-
end
|
98
|
-
|
99
|
-
def marshal_load(hash)
|
100
|
-
initialize
|
101
|
-
populate_from(hash)
|
102
|
-
end
|
103
|
-
|
104
|
-
undef :freeze
|
105
|
-
|
106
|
-
private
|
107
|
-
def initialize_copy(other)
|
108
|
-
super
|
109
|
-
populate_from(other)
|
110
|
-
end
|
111
|
-
|
112
|
-
def populate_from(hash)
|
113
|
-
hash.each_pair {|k, v| self[k] = v}
|
114
|
-
self
|
115
|
-
end
|
116
|
-
|
117
|
-
def validate_options_hash!(options)
|
118
|
-
if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Fixnum) || initial_capacity < 0)
|
119
|
-
raise ArgumentError, ":initial_capacity must be a positive Fixnum"
|
120
|
-
end
|
121
|
-
if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1)
|
122
|
-
raise ArgumentError, ":load_factor must be a number between 0 and 1"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|