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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c7dd77022028a6bdd65a929622793240c5c6d844ed91b46741a7964ef8b734b
4
- data.tar.gz: a03c8b323b45d88304cb628201bce9a90d8eb31263b0bc7ebf303beb09c2ce25
3
+ metadata.gz: 76bd41c95f58dc8b78c6a748264393b3f7a1410ce348e5e2ebd6ac9b92cd5d75
4
+ data.tar.gz: 9c3518807c7a919eece0fa0d83cdcf9556b3a6f97ff36dea44a365f7d8817b64
5
5
  SHA512:
6
- metadata.gz: e5d438ae9a488b9d814b43bb915adb2035bf64f094740d8ead2ef4a402f3e095ac894e50608bba819e7bb5abc26c8aff1cfe902022cebb8deb165976ff1095f3
7
- data.tar.gz: fc9ae3246f6226feafca77dc6c0d52d73629c107daea5fffaa95bb89cfe4775b522d8222f90336e8dcc4e30a794a678a0dab316ebcb564c28d932107d485ede5
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
- * in case the request needs to be paused, Iodine will subscribe to a channel with this name;
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
  };
@@ -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
- IodineStore.remove((VALUE)h->fiber);
128
+ h->fiber = NULL;
129
+ h->subscription = NULL;
135
130
 
136
131
  *h = (http_s){
137
132
  .private_data.vtbl = h->private_data.vtbl,
@@ -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
- // create / register env variable
683
- env = copy2env(handle);
684
- // create rack.io
685
- VALUE tmp = IodineRackIO.create(h, env);
686
- // pass env variable to handler
687
- rbresponse =
688
- IodineCaller.call2((VALUE)h->udata, iodine_call_proc_id, 1, &env);
689
- // close rack.io
690
- IodineRackIO.close(tmp);
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 *))iodine_handle_deferred_request_in_GVL,
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 `request_id` channel means the fiber attached to
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
- subscription_s *sub = fio_subscribe(.channel = fiobj_obj2cstr(s->h->request_id),
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
- fio_uuid_link(s->uuid, (void *)sub, http_close_deferred_request_handler);
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");
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '2.3.0'.freeze
2
+ VERSION = '3.0.1'.freeze
3
3
  end
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: 2.3.0
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-27 00:00:00.000000000 Z
11
+ date: 2023-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake