semian 0.22.0.RC.1 → 0.22.0
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/README.md +7 -7
- data/ext/semian/resource.c +16 -11
- data/ext/semian/resource.h +29 -0
- data/ext/semian/semian.c +2 -0
- data/lib/semian/protected_resource.rb +1 -1
- data/lib/semian/resource.rb +23 -10
- data/lib/semian/version.rb +1 -1
- data/lib/semian.rb +16 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27fa3d35b047fbe54483763821e246e2ce6f1403d8b3354d5759c4bdf1b43b2b
|
4
|
+
data.tar.gz: '06303901cc95e293dee76cd712283a4a7db1536771133e83563c969a6f3598e5'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31e47dcea63ba9fc861272d9b8c2d591eb5f2d0783b1d8cde667812ba1cc4307ea52b533f8dc3542d011fb98c770ed011ff3a84c3e1ee7239635b01c0717b1ad
|
7
|
+
data.tar.gz: e32d7f17f6d73c95418fe6b80f1dce3423271423d61c8acd1fda356dab02aac41c24637d9a0939d39e5ade7cb015a2e47182361ea5c9187b1b39d93d59058510
|
data/README.md
CHANGED
@@ -270,23 +270,23 @@ SEMIAN_PARAMETERS = {
|
|
270
270
|
dynamic: true,
|
271
271
|
}
|
272
272
|
|
273
|
-
class CurrentSemianSubResource < ActiveSupport::
|
274
|
-
attribute :
|
273
|
+
class CurrentSemianSubResource < ActiveSupport::CurrentAttributes
|
274
|
+
attribute :sub_name
|
275
275
|
end
|
276
276
|
|
277
277
|
Semian::NetHTTP.semian_configuration = proc do |host, port|
|
278
278
|
name = "#{host}_#{port}"
|
279
|
-
if (sub_resource_name = CurrentSemianSubResource.
|
280
|
-
name << "_#{
|
279
|
+
if (sub_resource_name = CurrentSemianSubResource.sub_name)
|
280
|
+
name << "_#{sub_resource_name}"
|
281
281
|
end
|
282
282
|
SEMIAN_PARAMETERS.merge(name: name)
|
283
283
|
end
|
284
284
|
|
285
285
|
# Two requests to example.com can use two different semian resources,
|
286
|
-
# as long as `CurrentSemianSubResource.
|
287
|
-
# CurrentSemianSubResource.set(
|
286
|
+
# as long as `CurrentSemianSubResource.sub_name` is set accordingly:
|
287
|
+
# CurrentSemianSubResource.set(sub_name: "sub_resource_1") { Net::HTTP.get_response(URI("http://example.com")) }
|
288
288
|
# and:
|
289
|
-
# CurrentSemianSubResource.set(
|
289
|
+
# CurrentSemianSubResource.set(sub_name: "sub_resource_2") { Net::HTTP.get_response(URI("http://example.com")) }
|
290
290
|
```
|
291
291
|
|
292
292
|
For most purposes, `"#{host}_#{port}"` is a good default `name`. Custom `name` formats
|
data/ext/semian/resource.c
CHANGED
@@ -5,9 +5,6 @@ ID id_wait_time;
|
|
5
5
|
ID id_timeout;
|
6
6
|
int system_max_semaphore_count;
|
7
7
|
|
8
|
-
static VALUE
|
9
|
-
cleanup_semian_resource_acquire(VALUE self);
|
10
|
-
|
11
8
|
static void
|
12
9
|
check_tickets_xor_quota_arg(VALUE tickets, VALUE quota);
|
13
10
|
|
@@ -33,15 +30,11 @@ static const rb_data_type_t
|
|
33
30
|
semian_resource_type;
|
34
31
|
|
35
32
|
VALUE
|
36
|
-
|
33
|
+
semian_resource_acquire_semaphore(int argc, VALUE *argv, VALUE self)
|
37
34
|
{
|
38
35
|
semian_resource_t *self_res = NULL;
|
39
36
|
semian_resource_t res = { 0 };
|
40
37
|
|
41
|
-
if (!rb_block_given_p()) {
|
42
|
-
rb_raise(rb_eArgError, "acquire requires a block");
|
43
|
-
}
|
44
|
-
|
45
38
|
TypedData_Get_Struct(self, semian_resource_t, &semian_resource_type, self_res);
|
46
39
|
res = *self_res;
|
47
40
|
|
@@ -75,7 +68,19 @@ semian_resource_acquire(int argc, VALUE *argv, VALUE self)
|
|
75
68
|
wait_time = LONG2NUM(res.wait_time);
|
76
69
|
}
|
77
70
|
|
78
|
-
return
|
71
|
+
return wait_time;
|
72
|
+
}
|
73
|
+
|
74
|
+
VALUE
|
75
|
+
semian_resource_acquire(int argc, VALUE *argv, VALUE self)
|
76
|
+
{
|
77
|
+
if (!rb_block_given_p()) {
|
78
|
+
rb_raise(rb_eArgError, "acquire requires a block");
|
79
|
+
}
|
80
|
+
|
81
|
+
VALUE wait_time = semian_resource_acquire_semaphore(argc, argv, self);
|
82
|
+
|
83
|
+
return rb_ensure(rb_yield, wait_time, semian_resource_release_semaphore, self);
|
79
84
|
}
|
80
85
|
|
81
86
|
VALUE
|
@@ -253,8 +258,8 @@ semian_resource_in_use(VALUE self)
|
|
253
258
|
return Qtrue;
|
254
259
|
}
|
255
260
|
|
256
|
-
|
257
|
-
|
261
|
+
VALUE
|
262
|
+
semian_resource_release_semaphore(VALUE self)
|
258
263
|
{
|
259
264
|
semian_resource_t *res = NULL;
|
260
265
|
TypedData_Get_Struct(self, semian_resource_t, &semian_resource_type, res);
|
data/ext/semian/resource.h
CHANGED
@@ -33,10 +33,39 @@ semian_resource_initialize(VALUE self, VALUE id, VALUE tickets, VALUE quota, VAL
|
|
33
33
|
*
|
34
34
|
* If no timeout argument is provided, the default timeout passed to Semian.register will be used.
|
35
35
|
*
|
36
|
+
* The given block is executed with the semaphore held and, when the block
|
37
|
+
* exits, the semaphore is automatically released.
|
36
38
|
*/
|
37
39
|
VALUE
|
38
40
|
semian_resource_acquire(int argc, VALUE *argv, VALUE self);
|
39
41
|
|
42
|
+
/*
|
43
|
+
* call-seq:
|
44
|
+
* resource.acquire_semaphore(timeout: default_timeout) -> wait_time
|
45
|
+
*
|
46
|
+
* Acquires a resource. The call will block for <code>timeout</code> seconds if a ticket
|
47
|
+
* is not available. If no ticket is available within the timeout period, Semian::TimeoutError
|
48
|
+
* will be raised.
|
49
|
+
*
|
50
|
+
* If no timeout argument is provided, the default timeout passed to Semian.register will be used.
|
51
|
+
*
|
52
|
+
* Note: The caller is responsible for releasing the semaphore when done by calling release_semaphore.
|
53
|
+
*/
|
54
|
+
VALUE
|
55
|
+
semian_resource_acquire_semaphore(int argc, VALUE *argv, VALUE self);
|
56
|
+
|
57
|
+
/*
|
58
|
+
* call-seq:
|
59
|
+
* resource.release_semaphore() -> nil
|
60
|
+
*
|
61
|
+
* Releases a resource previously acquired with acquire_semaphore.
|
62
|
+
*
|
63
|
+
* Note: The method is NOT idempotent. The caller must ensure that the method is called exactly
|
64
|
+
* as many times as acquire_semaphore.
|
65
|
+
*/
|
66
|
+
VALUE
|
67
|
+
semian_resource_release_semaphore(VALUE self);
|
68
|
+
|
40
69
|
/*
|
41
70
|
* call-seq:
|
42
71
|
* resource.destroy() -> true
|
data/ext/semian/semian.c
CHANGED
@@ -60,6 +60,8 @@ void Init_semian()
|
|
60
60
|
rb_define_alloc_func(cResource, semian_resource_alloc);
|
61
61
|
rb_define_method(cResource, "initialize_semaphore", semian_resource_initialize, 5);
|
62
62
|
rb_define_method(cResource, "acquire", semian_resource_acquire, -1);
|
63
|
+
rb_define_method(cResource, "acquire_semaphore", semian_resource_acquire_semaphore, -1);
|
64
|
+
rb_define_method(cResource, "release_semaphore", semian_resource_release_semaphore, 0);
|
63
65
|
rb_define_method(cResource, "count", semian_resource_count, 0);
|
64
66
|
rb_define_method(cResource, "semid", semian_resource_id, 0);
|
65
67
|
rb_define_method(cResource, "key", semian_resource_key, 0);
|
@@ -4,7 +4,7 @@ module Semian
|
|
4
4
|
class ProtectedResource
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
def_delegators :@bulkhead, :
|
7
|
+
def_delegators :@bulkhead, :count, :semid, :tickets, :registered_workers
|
8
8
|
def_delegators :@circuit_breaker,
|
9
9
|
:reset,
|
10
10
|
:mark_failed,
|
data/lib/semian/resource.rb
CHANGED
@@ -9,6 +9,12 @@ module Semian
|
|
9
9
|
def instance(name, **kwargs)
|
10
10
|
Semian.resources[name] ||= ProtectedResource.new(name, new(name, **kwargs), nil)
|
11
11
|
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def redefinable(method_name)
|
16
|
+
alias_method(method_name, method_name) # Silence method redefinition warnings
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
14
20
|
def initialize(name, tickets: nil, quota: nil, permissions: Semian.default_permissions, timeout: 0)
|
@@ -26,41 +32,48 @@ module Semian
|
|
26
32
|
@name = name
|
27
33
|
end
|
28
34
|
|
29
|
-
def reset_registered_workers!
|
35
|
+
redefinable def reset_registered_workers!
|
30
36
|
end
|
31
37
|
|
32
|
-
def destroy
|
38
|
+
redefinable def destroy
|
33
39
|
end
|
34
40
|
|
35
|
-
def unregister_worker
|
41
|
+
redefinable def unregister_worker
|
36
42
|
end
|
37
43
|
|
38
|
-
def acquire(*)
|
44
|
+
redefinable def acquire(*)
|
39
45
|
wait_time = 0
|
40
46
|
yield wait_time
|
41
47
|
end
|
42
48
|
|
43
|
-
def
|
49
|
+
redefinable def acquire_semaphore
|
50
|
+
0
|
51
|
+
end
|
52
|
+
|
53
|
+
redefinable def release_semaphore
|
54
|
+
end
|
55
|
+
|
56
|
+
redefinable def count
|
44
57
|
0
|
45
58
|
end
|
46
59
|
|
47
|
-
def tickets
|
60
|
+
redefinable def tickets
|
48
61
|
0
|
49
62
|
end
|
50
63
|
|
51
|
-
def registered_workers
|
64
|
+
redefinable def registered_workers
|
52
65
|
0
|
53
66
|
end
|
54
67
|
|
55
|
-
def semid
|
68
|
+
redefinable def semid
|
56
69
|
0
|
57
70
|
end
|
58
71
|
|
59
|
-
def key
|
72
|
+
redefinable def key
|
60
73
|
"0x00000000"
|
61
74
|
end
|
62
75
|
|
63
|
-
def in_use?
|
76
|
+
redefinable def in_use?
|
64
77
|
false
|
65
78
|
end
|
66
79
|
end
|
data/lib/semian/version.rb
CHANGED
data/lib/semian.rb
CHANGED
@@ -275,6 +275,21 @@ module Semian
|
|
275
275
|
@thread_safe = thread_safe
|
276
276
|
end
|
277
277
|
|
278
|
+
THREAD_BULKHEAD_DISABLED_VAR = :semian_bulkheads_disabled
|
279
|
+
private_constant(:THREAD_BULKHEAD_DISABLED_VAR)
|
280
|
+
|
281
|
+
def bulkheads_disabled_in_thread?(thread)
|
282
|
+
thread.thread_variable_get(THREAD_BULKHEAD_DISABLED_VAR)
|
283
|
+
end
|
284
|
+
|
285
|
+
def disable_bulkheads_for_thread(thread)
|
286
|
+
old_value = thread.thread_variable_get(THREAD_BULKHEAD_DISABLED_VAR)
|
287
|
+
thread.thread_variable_set(THREAD_BULKHEAD_DISABLED_VAR, true)
|
288
|
+
yield
|
289
|
+
ensure
|
290
|
+
thread.thread_variable_set(THREAD_BULKHEAD_DISABLED_VAR, old_value)
|
291
|
+
end
|
292
|
+
|
278
293
|
private
|
279
294
|
|
280
295
|
def create_circuit_breaker(name, **options)
|
@@ -318,7 +333,7 @@ module Semian
|
|
318
333
|
end
|
319
334
|
|
320
335
|
def create_bulkhead(name, **options)
|
321
|
-
return if ENV.key?("SEMIAN_BULKHEAD_DISABLED")
|
336
|
+
return if ENV.key?("SEMIAN_BULKHEAD_DISABLED") || bulkheads_disabled_in_thread?(Thread.current)
|
322
337
|
return unless options.fetch(:bulkhead, true)
|
323
338
|
|
324
339
|
permissions = options[:permissions] || default_permissions
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semian
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.22.0
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Francis
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-
|
13
|
+
date: 2024-11-05 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: |2
|
16
16
|
A Ruby C extention that is used to control access to shared resources
|
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: '0'
|
81
81
|
requirements: []
|
82
|
-
rubygems_version: 3.5.
|
82
|
+
rubygems_version: 3.5.22
|
83
83
|
signing_key:
|
84
84
|
specification_version: 4
|
85
85
|
summary: Bulkheading for Ruby with SysV semaphores
|