rage-iodine 5.2.1 → 5.3.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/.github/workflows/release.yml +28 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +2 -0
- data/README.md +17 -17
- data/SECURITY.md +32 -0
- data/ext/iodine/extconf.rb +10 -0
- data/ext/iodine/fio.c +117 -5
- data/ext/iodine/fio.h +12 -14
- data/ext/iodine/fio_json_parser.h +5 -4
- data/ext/iodine/fio_tls_openssl.c +140 -90
- data/ext/iodine/fiobj_data.c +13 -11
- data/ext/iodine/fiobj_str.h +1 -1
- data/ext/iodine/fiobject.h +5 -4
- data/ext/iodine/iodine.c +3 -0
- data/ext/iodine/iodine.h +1 -0
- data/ext/iodine/iodine_caller.c +25 -13
- data/ext/iodine/iodine_http.c +2 -1
- data/ext/iodine/iodine_store.c +24 -18
- data/ext/iodine/iodine_worker_pool.c +569 -0
- data/ext/iodine/iodine_worker_pool.h +19 -0
- data/ext/iodine/iodine_worker_pool_test.c +145 -0
- data/ext/iodine/iodine_worker_pool_test.h +19 -0
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +11 -2
- metadata +9 -3
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Test helpers for Iodine::WorkerPool.
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- busy(duration:): Blocking operation that releases the GVL.
|
|
6
|
+
When called within a fiber scheduler context, this will trigger
|
|
7
|
+
blocking_operation_wait and use the worker pool.
|
|
8
|
+
|
|
9
|
+
Based on io-event worker_pool_test.c by Samuel Williams.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#include "iodine.h"
|
|
13
|
+
|
|
14
|
+
#ifdef HAVE_IODINE_WORKER_POOL
|
|
15
|
+
|
|
16
|
+
#include "iodine_worker_pool_test.h"
|
|
17
|
+
|
|
18
|
+
#include <ruby/thread.h>
|
|
19
|
+
#include <ruby/fiber/scheduler.h>
|
|
20
|
+
#include <unistd.h>
|
|
21
|
+
#include <sys/select.h>
|
|
22
|
+
|
|
23
|
+
static ID id_duration;
|
|
24
|
+
|
|
25
|
+
struct busy_operation_data {
|
|
26
|
+
int read_fd;
|
|
27
|
+
int write_fd;
|
|
28
|
+
double duration;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/* The actual blocking operation that can be cancelled */
|
|
32
|
+
static void *busy_blocking_operation(void *data) {
|
|
33
|
+
struct busy_operation_data *busy_data = (struct busy_operation_data *)data;
|
|
34
|
+
|
|
35
|
+
/* Use select() to wait for the pipe to become readable */
|
|
36
|
+
fd_set read_fds;
|
|
37
|
+
struct timeval timeout;
|
|
38
|
+
|
|
39
|
+
FD_ZERO(&read_fds);
|
|
40
|
+
FD_SET(busy_data->read_fd, &read_fds);
|
|
41
|
+
|
|
42
|
+
timeout.tv_sec = (long)busy_data->duration;
|
|
43
|
+
timeout.tv_usec = (int)((busy_data->duration - timeout.tv_sec) * 1000000);
|
|
44
|
+
|
|
45
|
+
/* This will block until:
|
|
46
|
+
1. The pipe becomes readable (cancellation)
|
|
47
|
+
2. The timeout expires
|
|
48
|
+
3. An error occurs */
|
|
49
|
+
int result = select(busy_data->read_fd + 1, &read_fds, NULL, NULL, &timeout);
|
|
50
|
+
|
|
51
|
+
if (result > 0 && FD_ISSET(busy_data->read_fd, &read_fds)) {
|
|
52
|
+
/* Pipe became readable - we were cancelled */
|
|
53
|
+
char buffer;
|
|
54
|
+
read(busy_data->read_fd, &buffer, 1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return NULL;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Unblock function that writes to the pipe to cancel the operation */
|
|
61
|
+
static void busy_unblock_function(void *data) {
|
|
62
|
+
struct busy_operation_data *busy_data = (struct busy_operation_data *)data;
|
|
63
|
+
char wake_byte = 1;
|
|
64
|
+
write(busy_data->write_fd, &wake_byte, 1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Cleanup function for rb_ensure */
|
|
68
|
+
static VALUE busy_operation_cleanup(VALUE data_value) {
|
|
69
|
+
struct busy_operation_data *busy_data =
|
|
70
|
+
(struct busy_operation_data *)data_value;
|
|
71
|
+
close(busy_data->read_fd);
|
|
72
|
+
close(busy_data->write_fd);
|
|
73
|
+
return Qnil;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* The main operation execution */
|
|
77
|
+
static VALUE busy_operation_execute(VALUE data_value) {
|
|
78
|
+
struct busy_operation_data *busy_data =
|
|
79
|
+
(struct busy_operation_data *)data_value;
|
|
80
|
+
|
|
81
|
+
rb_nogvl(busy_blocking_operation, busy_data, busy_unblock_function, busy_data,
|
|
82
|
+
RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_OFFLOAD_SAFE);
|
|
83
|
+
|
|
84
|
+
return Qnil;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Iodine::WorkerPool.busy(duration: 1.0) -> nil
|
|
89
|
+
*
|
|
90
|
+
* Creates a blocking operation for testing that releases the GVL.
|
|
91
|
+
* When called within a fiber scheduler context with a worker pool,
|
|
92
|
+
* this will trigger blocking_operation_wait.
|
|
93
|
+
*
|
|
94
|
+
* @param duration [Float] How long to block (default: 1.0 second)
|
|
95
|
+
* @return [nil]
|
|
96
|
+
*/
|
|
97
|
+
static VALUE worker_pool_test_busy(int argc, VALUE *argv, VALUE self) {
|
|
98
|
+
double duration = 1.0;
|
|
99
|
+
|
|
100
|
+
VALUE kwargs = Qnil;
|
|
101
|
+
VALUE rb_duration = Qundef;
|
|
102
|
+
|
|
103
|
+
rb_scan_args(argc, argv, "0:", &kwargs);
|
|
104
|
+
|
|
105
|
+
if (!NIL_P(kwargs)) {
|
|
106
|
+
VALUE kwvals[1];
|
|
107
|
+
ID kwkeys[1] = {id_duration};
|
|
108
|
+
rb_get_kwargs(kwargs, kwkeys, 0, 1, kwvals);
|
|
109
|
+
rb_duration = kwvals[0];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (rb_duration != Qundef && !NIL_P(rb_duration)) {
|
|
113
|
+
duration = NUM2DBL(rb_duration);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Create pipe for cancellation */
|
|
117
|
+
int pipe_fds[2];
|
|
118
|
+
if (pipe(pipe_fds) != 0) {
|
|
119
|
+
rb_sys_fail("pipe creation failed");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
struct busy_operation_data busy_data = {
|
|
123
|
+
.read_fd = pipe_fds[0], .write_fd = pipe_fds[1], .duration = duration};
|
|
124
|
+
|
|
125
|
+
return rb_ensure(busy_operation_execute, (VALUE)&busy_data,
|
|
126
|
+
busy_operation_cleanup, (VALUE)&busy_data);
|
|
127
|
+
(void)self;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* Initialize the test functions */
|
|
131
|
+
void iodine_worker_pool_test_init(VALUE WorkerPoolKlass) {
|
|
132
|
+
id_duration = rb_intern("duration");
|
|
133
|
+
|
|
134
|
+
rb_define_singleton_method(WorkerPoolKlass, "__busy", worker_pool_test_busy,
|
|
135
|
+
-1);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#else /* !HAVE_IODINE_WORKER_POOL */
|
|
139
|
+
|
|
140
|
+
void iodine_worker_pool_test_init(VALUE WorkerPoolKlass) {
|
|
141
|
+
/* WorkerPool not available */
|
|
142
|
+
(void)WorkerPoolKlass;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#endif /* HAVE_IODINE_WORKER_POOL */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Test helpers for Iodine::WorkerPool.
|
|
3
|
+
Provides a busy() class method for testing GVL release and cancellation.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#ifndef H_IODINE_WORKER_POOL_TEST_H
|
|
7
|
+
#define H_IODINE_WORKER_POOL_TEST_H
|
|
8
|
+
|
|
9
|
+
#include <ruby.h>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Initializes test methods on the WorkerPool class.
|
|
13
|
+
* Called from iodine_worker_pool_init() when HAVE_IODINE_WORKER_POOL is defined.
|
|
14
|
+
*
|
|
15
|
+
* @param WorkerPoolKlass The Iodine::WorkerPool class
|
|
16
|
+
*/
|
|
17
|
+
void iodine_worker_pool_test_init(VALUE WorkerPoolKlass);
|
|
18
|
+
|
|
19
|
+
#endif
|
data/lib/iodine/version.rb
CHANGED
data/lib/rack/handler/iodine.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
require 'iodine' unless defined?(::Iodine::VERSION)
|
|
2
|
-
|
|
2
|
+
begin
|
|
3
|
+
require 'rage/cli'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
end
|
|
3
6
|
|
|
4
7
|
module Iodine
|
|
5
8
|
# Iodine's {Iodine::Rack} module provides a Rack compliant interface (connecting Iodine to Rack) for an HTTP and Websocket Server.
|
|
@@ -7,7 +10,13 @@ module Iodine
|
|
|
7
10
|
|
|
8
11
|
# Runs a Rack app, as par the Rack handler requirements.
|
|
9
12
|
def self.run(app, options = {})
|
|
10
|
-
Rage::CLI
|
|
13
|
+
if !defined?(Rage::CLI) && ENV["RSPEC_TEST_ENV"]
|
|
14
|
+
Iodine.listen(service: :http, handler: app, port: options[:Port], address: options[:Host])
|
|
15
|
+
Iodine.start
|
|
16
|
+
else
|
|
17
|
+
Rage::CLI.new([], { port: options[:Port], binding: options[:Host], environment: options[:environment] }).server
|
|
18
|
+
end
|
|
19
|
+
|
|
11
20
|
true
|
|
12
21
|
end
|
|
13
22
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rage-iodine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Boaz Segev
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rake
|
|
@@ -121,6 +121,7 @@ extensions:
|
|
|
121
121
|
extra_rdoc_files: []
|
|
122
122
|
files:
|
|
123
123
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
|
124
|
+
- ".github/workflows/release.yml"
|
|
124
125
|
- ".github/workflows/ruby.yml"
|
|
125
126
|
- ".gitignore"
|
|
126
127
|
- ".rspec"
|
|
@@ -131,6 +132,7 @@ files:
|
|
|
131
132
|
- LIMITS.md
|
|
132
133
|
- README.md
|
|
133
134
|
- Rakefile
|
|
135
|
+
- SECURITY.md
|
|
134
136
|
- SPEC-PubSub-Draft.md
|
|
135
137
|
- SPEC-WebSocket-Draft.md
|
|
136
138
|
- bin/console
|
|
@@ -226,6 +228,10 @@ files:
|
|
|
226
228
|
- ext/iodine/iodine_tcp.h
|
|
227
229
|
- ext/iodine/iodine_tls.c
|
|
228
230
|
- ext/iodine/iodine_tls.h
|
|
231
|
+
- ext/iodine/iodine_worker_pool.c
|
|
232
|
+
- ext/iodine/iodine_worker_pool.h
|
|
233
|
+
- ext/iodine/iodine_worker_pool_test.c
|
|
234
|
+
- ext/iodine/iodine_worker_pool_test.h
|
|
229
235
|
- ext/iodine/mustache_parser.h
|
|
230
236
|
- ext/iodine/redis_engine.c
|
|
231
237
|
- ext/iodine/redis_engine.h
|
|
@@ -272,7 +278,7 @@ requirements:
|
|
|
272
278
|
- Ruby >= 2.5.0 recommended.
|
|
273
279
|
- TLS requires OpenSSL >= 1.1.0.
|
|
274
280
|
- Or Windows with Ruby >= 3.0.0 build with MingW and MingW as compiler.
|
|
275
|
-
rubygems_version: 3.6.
|
|
281
|
+
rubygems_version: 3.6.9
|
|
276
282
|
specification_version: 4
|
|
277
283
|
summary: iodine - a fast HTTP / Websocket Server with Pub/Sub support, optimized for
|
|
278
284
|
Ruby MRI on Linux / BSD / Windows
|