rage-iodine 2.3.0 → 3.0.1
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/CHANGELOG.md +41 -0
- data/ext/iodine/http.c +4 -0
- data/ext/iodine/http.h +4 -5
- data/ext/iodine/http_internal.h +2 -7
- data/ext/iodine/iodine_http.c +28 -54
- data/lib/iodine/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76bd41c95f58dc8b78c6a748264393b3f7a1410ce348e5e2ebd6ac9b92cd5d75
|
4
|
+
data.tar.gz: 9c3518807c7a919eece0fa0d83cdcf9556b3a6f97ff36dea44a365f7d8817b64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bab33c03cf6d8f84bc464170e521a344ff3e3af5f3decd303a0d38ff74e0629cf3478b297aa71e4fed41654d00758144ee3824edc7a17745106c4597ba5938b
|
7
|
+
data.tar.gz: 38ba3c1a7b8e19f12f11b924c1e94a8feb1e59b0d99fe0050d98d1291aa41f9dcbe6b79dc83521511a8690f975c0b1a0c0aff14d8ae2e752ae862f9013491425
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,47 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.3.0.1 (2023-12-11)
|
10
|
+
|
11
|
+
**Fix**: Disable scheduling request fibers.
|
12
|
+
|
13
|
+
#### Change log v.3.0.0 (2023-12-09)
|
14
|
+
|
15
|
+
**Update**: Schedule request fibers.
|
16
|
+
**Update**: Improve stability and memory management under high load.
|
17
|
+
|
18
|
+
#### Change log v.2.3.0 (2023-11-27)
|
19
|
+
|
20
|
+
**Fix**: Correctly handle non-persistent HTTP connections.
|
21
|
+
|
22
|
+
#### Change log v.2.2.0 (2023-11-20)
|
23
|
+
|
24
|
+
**Update**: Add `gen_request_tag` and `gen_timestamp` methods.
|
25
|
+
|
26
|
+
**Fix**: Use separate buffer for writing.
|
27
|
+
|
28
|
+
#### Change log v.2.1.1 (2023-11-09)
|
29
|
+
|
30
|
+
**Fix**: Correctly update the fulfilled flag.
|
31
|
+
|
32
|
+
**Fix**: Always send a response.
|
33
|
+
|
34
|
+
#### Change log v.2.1.0 (2023-11-03)
|
35
|
+
|
36
|
+
**Fix**: Return an error on timeouts.
|
37
|
+
|
38
|
+
#### Change log v.2.0.0 (2023-10-31)
|
39
|
+
|
40
|
+
**Update**: Parse params.
|
41
|
+
|
42
|
+
#### Change log v.1.8.0 (2023-09-25)
|
43
|
+
|
44
|
+
**Fix**: Free up memory when closing the protocol.
|
45
|
+
|
46
|
+
#### Change log v.1.7.58 (2023-09-15)
|
47
|
+
|
48
|
+
**Update**: Allow to pause and resume fiber requests.
|
49
|
+
|
9
50
|
#### Change log v.0.7.57 (2023-09-04)
|
10
51
|
|
11
52
|
**Fix**: Fixes possible name collision when loading gem (`.rb` vs. `.so` loading). Credit to @noraj (Alexandre ZANNI) for opening issue #148. Credit to @janbiedermann (Jan Biedermann) for discovering the root cause and offering a solution.
|
data/ext/iodine/http.c
CHANGED
@@ -737,6 +737,8 @@ static void http_resume_wrapper(intptr_t uuid, fio_protocol_s *p_, void *arg) {
|
|
737
737
|
http_pause_handle_s *http = arg;
|
738
738
|
http_s *h = http->h;
|
739
739
|
h->udata = http->udata;
|
740
|
+
h->fiber = http->fiber;
|
741
|
+
h->subscription = http->subscription;
|
740
742
|
http_vtable_s *vtbl = (http_vtable_s *)h->private_data.vtbl;
|
741
743
|
if (http->task)
|
742
744
|
http->task(h);
|
@@ -769,6 +771,8 @@ void http_pause(http_s *h, void (*task)(http_pause_handle_s *http)) {
|
|
769
771
|
.uuid = p->uuid,
|
770
772
|
.h = h,
|
771
773
|
.udata = h->udata,
|
774
|
+
.fiber = h->fiber,
|
775
|
+
.subscription = h->subscription,
|
772
776
|
};
|
773
777
|
vtbl->http_on_pause(h, p);
|
774
778
|
fio_defer(http_pause_wrapper, http, (void *)((uintptr_t)task));
|
data/ext/iodine/http.h
CHANGED
@@ -128,11 +128,8 @@ typedef struct {
|
|
128
128
|
/** in case the request was paused, this will hold a Ruby fiber, that was scheduled during the request. */
|
129
129
|
void *fiber;
|
130
130
|
|
131
|
-
/**
|
132
|
-
|
133
|
-
* once Ruby finishes processing, it will publish to this channel telling Iodine the request can be resumed.
|
134
|
-
*/
|
135
|
-
FIOBJ request_id;
|
131
|
+
/** in case the request needs to be paused, Iodine will subscribe to a channel identified by this object. */
|
132
|
+
void *subscription;
|
136
133
|
} http_s;
|
137
134
|
|
138
135
|
/**
|
@@ -283,6 +280,8 @@ struct http_pause_handle_s {
|
|
283
280
|
uintptr_t uuid;
|
284
281
|
http_s *h;
|
285
282
|
void *udata;
|
283
|
+
void *fiber;
|
284
|
+
void *subscription;
|
286
285
|
void (*task)(http_s *);
|
287
286
|
void (*fallback)(void *);
|
288
287
|
};
|
data/ext/iodine/http_internal.h
CHANGED
@@ -97,10 +97,6 @@ HTTP request/response object management
|
|
97
97
|
|
98
98
|
static inline void http_s_new(http_s *h, http_fio_protocol_s *owner,
|
99
99
|
http_vtable_s *vtbl) {
|
100
|
-
FIOBJ request_id = fiobj_str_buf(14);
|
101
|
-
fiobj_str_write(request_id, "req:", 4);
|
102
|
-
fiobj_str_write_i(request_id, (uint32_t)fio_rand64());
|
103
|
-
|
104
100
|
*h = (http_s){
|
105
101
|
.private_data =
|
106
102
|
{
|
@@ -111,7 +107,6 @@ static inline void http_s_new(http_s *h, http_fio_protocol_s *owner,
|
|
111
107
|
.headers = fiobj_hash_new(),
|
112
108
|
.received_at = fio_last_tick(),
|
113
109
|
.status = 200,
|
114
|
-
.request_id = request_id,
|
115
110
|
};
|
116
111
|
}
|
117
112
|
|
@@ -129,9 +124,9 @@ static inline void http_s_destroy(http_s *h, uint8_t log) {
|
|
129
124
|
fiobj_free(h->cookies);
|
130
125
|
fiobj_free(h->body);
|
131
126
|
fiobj_free(h->params);
|
132
|
-
fiobj_free(h->request_id);
|
133
127
|
|
134
|
-
|
128
|
+
h->fiber = NULL;
|
129
|
+
h->subscription = NULL;
|
135
130
|
|
136
131
|
*h = (http_s){
|
137
132
|
.private_data.vtbl = h->private_data.vtbl,
|
data/ext/iodine/iodine_http.c
CHANGED
@@ -61,6 +61,7 @@ static ID attach_method_id;
|
|
61
61
|
static ID iodine_call_proc_id;
|
62
62
|
static ID fiber_result_var_id;
|
63
63
|
static VALUE http_wait_directive;
|
64
|
+
static ID fiber_id_method_id;
|
64
65
|
|
65
66
|
static VALUE env_template_no_upgrade;
|
66
67
|
static VALUE env_template_websockets;
|
@@ -119,6 +120,7 @@ typedef struct {
|
|
119
120
|
IODINE_HTTP_EMPTY,
|
120
121
|
IODINE_HTTP_ERROR,
|
121
122
|
IODINE_HTTP_WAIT,
|
123
|
+
IODINE_HTTP_DEFERRED,
|
122
124
|
} type;
|
123
125
|
enum iodine_upgrade_type_enum {
|
124
126
|
IODINE_UPGRADE_NONE = 0,
|
@@ -470,9 +472,6 @@ static inline VALUE copy2env(iodine_http_request_handle_s *handle) {
|
|
470
472
|
/* no TLS, no forwarding, assume `http`, which is the default */
|
471
473
|
}
|
472
474
|
}
|
473
|
-
{
|
474
|
-
rb_hash_aset(env, IODINE_REQUEST_ID, rb_str_new_cstr(fiobj_obj2cstr(handle->h->request_id).data));
|
475
|
-
}
|
476
475
|
|
477
476
|
/* add all remaining headers */
|
478
477
|
fiobj_each1(h->headers, 0, iodine_copy2env_task, (void *)env);
|
@@ -674,20 +673,24 @@ Handling HTTP requests
|
|
674
673
|
static inline void *iodine_handle_request_in_GVL(void *handle_) {
|
675
674
|
iodine_http_request_handle_s *handle = handle_;
|
676
675
|
VALUE rbresponse = 0;
|
677
|
-
VALUE env = 0;
|
676
|
+
VALUE env = 0, tmp;
|
678
677
|
http_s *h = handle->h;
|
679
678
|
if (!h->udata)
|
680
679
|
goto err_not_found;
|
681
680
|
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
681
|
+
if (handle->type == IODINE_HTTP_DEFERRED) {
|
682
|
+
rbresponse = rb_ivar_get((VALUE)h->fiber, fiber_result_var_id);
|
683
|
+
} else {
|
684
|
+
// create / register env variable
|
685
|
+
env = copy2env(handle);
|
686
|
+
// create rack.io
|
687
|
+
tmp = IodineRackIO.create(h, env);
|
688
|
+
// pass env variable to handler
|
689
|
+
rbresponse = IodineCaller.call2((VALUE)h->udata, iodine_call_proc_id, 1, &env);
|
690
|
+
// close rack.io
|
691
|
+
IodineRackIO.close(tmp);
|
692
|
+
}
|
693
|
+
|
691
694
|
// test handler's return value
|
692
695
|
if (rbresponse == 0 || rbresponse == Qnil || TYPE(rbresponse) != T_ARRAY) {
|
693
696
|
goto internal_error;
|
@@ -739,7 +742,7 @@ static inline void *iodine_handle_request_in_GVL(void *handle_) {
|
|
739
742
|
// review each header and write it to the response.
|
740
743
|
rb_hash_foreach(response_headers, for_each_header_data, (VALUE)(h));
|
741
744
|
// review for upgrade.
|
742
|
-
if ((intptr_t)h->status < 300 &&
|
745
|
+
if (handle->type != IODINE_HTTP_DEFERRED && (intptr_t)h->status < 300 &&
|
743
746
|
ruby2c_review_upgrade(handle, rbresponse, env))
|
744
747
|
goto external_done;
|
745
748
|
// send the request body.
|
@@ -777,42 +780,6 @@ defer:
|
|
777
780
|
return NULL;
|
778
781
|
}
|
779
782
|
|
780
|
-
// called once a request that was paused previously needs to be resumed
|
781
|
-
static inline void *iodine_handle_deferred_request_in_GVL(void *handle_) {
|
782
|
-
iodine_http_request_handle_s *handle = handle_;
|
783
|
-
http_s *h = handle->h;
|
784
|
-
|
785
|
-
VALUE rbresponse = rb_ivar_get((VALUE)h->fiber, fiber_result_var_id);
|
786
|
-
VALUE tmp = rb_ary_entry(rbresponse, 0);
|
787
|
-
|
788
|
-
// set response status
|
789
|
-
if (TYPE(tmp) == T_STRING) {
|
790
|
-
char *data = RSTRING_PTR(tmp);
|
791
|
-
h->status = fio_atol(&data);
|
792
|
-
} else if (TYPE(tmp) == T_FIXNUM) {
|
793
|
-
h->status = FIX2ULONG(tmp);
|
794
|
-
} else {
|
795
|
-
goto internal_error;
|
796
|
-
}
|
797
|
-
|
798
|
-
// handle header copy from ruby land to C land.
|
799
|
-
VALUE response_headers = rb_ary_entry(rbresponse, 1);
|
800
|
-
|
801
|
-
// review each header and write it to the response.
|
802
|
-
rb_hash_foreach(response_headers, for_each_header_data, (VALUE)(h));
|
803
|
-
|
804
|
-
// send the request body.
|
805
|
-
if (ruby2c_response_send(handle, rbresponse, 0))
|
806
|
-
goto internal_error;
|
807
|
-
|
808
|
-
return NULL;
|
809
|
-
|
810
|
-
internal_error:
|
811
|
-
h->status = 500;
|
812
|
-
handle->type = IODINE_HTTP_ERROR;
|
813
|
-
return NULL;
|
814
|
-
}
|
815
|
-
|
816
783
|
static inline void
|
817
784
|
iodine_perform_handle_action(iodine_http_request_handle_s handle) {
|
818
785
|
switch (handle.type) {
|
@@ -856,11 +823,15 @@ static inline void http_resume_deferred_request_handler(http_s *h) {
|
|
856
823
|
iodine_http_request_handle_s handle = (iodine_http_request_handle_s){
|
857
824
|
.h = h,
|
858
825
|
.upgrade = IODINE_UPGRADE_NONE,
|
826
|
+
.type = IODINE_HTTP_DEFERRED,
|
859
827
|
};
|
860
828
|
|
861
|
-
IodineCaller.enterGVL((void *(*)(void *))
|
829
|
+
IodineCaller.enterGVL((void *(*)(void *))iodine_handle_request_in_GVL,
|
862
830
|
&handle);
|
863
831
|
|
832
|
+
fio_unsubscribe((subscription_s *)h->subscription);
|
833
|
+
IodineStore.remove((VALUE)h->fiber);
|
834
|
+
|
864
835
|
iodine_perform_handle_action(handle);
|
865
836
|
}
|
866
837
|
|
@@ -872,13 +843,15 @@ static inline void http_close_deferred_request_handler(void *sub) {
|
|
872
843
|
fio_unsubscribe((subscription_s *)sub);
|
873
844
|
}
|
874
845
|
|
875
|
-
// when Ruby sends a message into the `
|
846
|
+
// when Ruby sends a message into the `fiber_id` channel means the fiber attached to
|
876
847
|
// to the `http_s h` var can be resumed
|
877
848
|
static inline void http_pause_request_handler(http_pause_handle_s *s) {
|
878
|
-
|
849
|
+
VALUE fiber_id = rb_funcall((VALUE)s->fiber, fiber_id_method_id, 0);
|
850
|
+
subscription_s *sub = fio_subscribe(.channel = {0, RSTRING_LEN(fiber_id), RSTRING_PTR(fiber_id)},
|
879
851
|
.on_message = on_iodine_request_id_message,
|
880
852
|
.udata1 = (void *)s);
|
881
|
-
|
853
|
+
|
854
|
+
s->subscription = (void *)sub;
|
882
855
|
}
|
883
856
|
|
884
857
|
static void on_rack_request(http_s *h) {
|
@@ -1271,6 +1244,7 @@ void iodine_init_http(void) {
|
|
1271
1244
|
iodine_call_proc_id = rb_intern("call");
|
1272
1245
|
fiber_result_var_id = rb_intern("@__result");
|
1273
1246
|
http_wait_directive = ID2SYM(rb_intern("__http_defer__"));
|
1247
|
+
fiber_id_method_id = rb_intern("__get_id");
|
1274
1248
|
|
1275
1249
|
IodineUTF8Encoding = rb_enc_find("UTF-8");
|
1276
1250
|
IodineBinaryEncoding = rb_enc_find("binary");
|
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rage-iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11
|
11
|
+
date: 2023-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|