rage-iodine 2.3.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
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