agoo 2.7.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of agoo might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a78c4278726e4fc90aad77fa83029fdfa2cbdf84d72796947ae5c22d30165e1
4
- data.tar.gz: 8a3eb7eca852c6811270b7a6697a94184675e231f88f7c35848431b8495c166b
3
+ metadata.gz: e5771b6b916b39b35a7ddb198b3c80191b69cfd0f0d8d8fd792d1a1b90cc741c
4
+ data.tar.gz: 2503a29f723db8fa63b0a3bb6f64879046f4f31b2d15c594d4e22e5c2d745e44
5
5
  SHA512:
6
- metadata.gz: bc450f5bd00d4f256ddd31ccd29ad0075093403e41ff9d1bde7f3924796a32600ac9b6032452989f56b84303b44ee4f5663adce6d09eb3908cc2eef38b337f5e
7
- data.tar.gz: a66662a930ec96e99ac91a15981add0ea63a484df8d0e488e6915e2f4ca7c55cb939c5775f0619e64dea87f2a9b2fdd6d311bcc31338d72693bc230c45b8fbdc
6
+ metadata.gz: 0deeaf2727b3c729229420953662854de902e8a173d7a0ccabbe9e42ea2d2d269c66275520e8950c73f4ef7a758b271456f753695aea0bc8492cf1fbb66fbde9
7
+ data.tar.gz: 4fe4ce7b04976e446f9f0f3c051e360041c70d6a65d2d6bb1f5ab30c9cec1955326ead8caed0a66bd5f403ada280d61c645eca3509e5568c73940a034258d51a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### 2.8.0 - 2019-02-19
4
+
5
+ Extend GraphQL
6
+
7
+ - Add support for the Graphql `extend` functionality.
8
+
9
+ - Add the ID base scalar type.
10
+
11
+ - Use `schema` SDL element instead of `type schema`.
12
+
3
13
  ### 2.7.0 - 2019-01-29
4
14
 
5
15
  Static asset header rules functionality added.
data/ext/agoo/agoo.c CHANGED
@@ -1,10 +1,13 @@
1
1
  // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
2
 
3
+ #include <errno.h>
3
4
  #include <signal.h>
4
5
  #include <stdio.h>
6
+ #include <string.h>
5
7
 
6
8
  #include <ruby.h>
7
9
 
10
+ #include "atomic.h"
8
11
  #include "debug.h"
9
12
  #include "error_stream.h"
10
13
  #include "graphql.h"
@@ -21,10 +24,19 @@
21
24
 
22
25
  extern void graphql_init(VALUE mod);
23
26
 
27
+ sig_atomic_t agoo_stop = 0;
28
+
29
+ static atomic_int shutdown_started = AGOO_ATOMIC_INT_INIT(0);
30
+
24
31
  void
25
32
  agoo_shutdown() {
26
- rserver_shutdown(Qnil);
27
- agoo_log_close();
33
+ if (0 == atomic_fetch_add(&shutdown_started, 1)) {
34
+ rserver_shutdown(Qnil);
35
+ agoo_log_close();
36
+ gql_destroy();
37
+ debug_report();
38
+ exit(0);
39
+ }
28
40
  }
29
41
 
30
42
  /* Document-method: shutdown
@@ -36,8 +48,6 @@ agoo_shutdown() {
36
48
  static VALUE
37
49
  ragoo_shutdown(VALUE self) {
38
50
  agoo_shutdown();
39
- gql_destroy();
40
- debug_report();
41
51
 
42
52
  return Qnil;
43
53
  }
@@ -79,15 +89,7 @@ ragoo_unsubscribe(VALUE self, VALUE subject) {
79
89
 
80
90
  static void
81
91
  sig_handler(int sig) {
82
- #ifdef MEM_DEBUG
83
- rb_gc();
84
- #endif
85
- agoo_shutdown();
86
- gql_destroy();
87
- debug_report();
88
- // Use exit instead of rb_exit as rb_exit segfaults most of the time.
89
- //rb_exit(0);
90
- exit(0);
92
+ agoo_stop = 1;
91
93
  }
92
94
 
93
95
  /* Document-module: Agoo
@@ -112,12 +114,15 @@ Init_agoo() {
112
114
  rb_define_module_function(mod, "publish", ragoo_publish, 2);
113
115
  rb_define_module_function(mod, "unsubscribe", ragoo_unsubscribe, 1);
114
116
 
115
- signal(SIGINT, sig_handler);
116
- signal(SIGTERM, sig_handler);
117
- signal(SIGPIPE, SIG_IGN);
117
+ if (SIG_ERR == signal(SIGINT, sig_handler) ||
118
+ SIG_ERR == signal(SIGTERM, sig_handler) ||
119
+ SIG_ERR == signal(SIGPIPE, SIG_IGN) ||
120
+
121
+ // This causes sleeps and queue pops to return immediately and it can be
122
+ // called very frequently on mac OS with multiple threads. Something seems
123
+ // to get stuck.
124
+ SIG_ERR == signal(SIGVTALRM, SIG_IGN)) {
118
125
 
119
- // This causes sleeps and queue pops to return immediately and is can be
120
- // called all the time on mac OS with multiple threads. Something seems to
121
- // get stuck.
122
- signal(SIGVTALRM, SIG_IGN);
126
+ rb_raise(rb_eStandardError, "%s", strerror(errno));
127
+ }
123
128
  }
data/ext/agoo/con.c CHANGED
@@ -88,7 +88,7 @@ agoo_con_destroy(agooCon c) {
88
88
  }
89
89
  if (NULL != c->up) {
90
90
  agoo_upgraded_release_con(c->up);
91
-
91
+
92
92
  c->up = NULL;
93
93
  }
94
94
  agoo_log_cat(&agoo_con_cat, "Connection %llu closed.", (unsigned long long)c->id);
@@ -108,7 +108,7 @@ agoo_con_header_value(const char *header, int hlen, const char *key, int *vlen)
108
108
  const char *hend = header + hlen;
109
109
  const char *value;
110
110
  int klen = (int)strlen(key);
111
-
111
+
112
112
  while (h < hend) {
113
113
  if (0 == strncmp(key, h, klen) && ':' == h[klen]) {
114
114
  h += klen + 1;
@@ -118,7 +118,7 @@ agoo_con_header_value(const char *header, int hlen, const char *key, int *vlen)
118
118
  for (; '\r' != *h && '\0' != *h; h++) {
119
119
  }
120
120
  *vlen = (int)(h - value);
121
-
121
+
122
122
  return value;
123
123
  }
124
124
  for (; h < hend; h++) {
@@ -135,7 +135,7 @@ static HeadReturn
135
135
  bad_request(agooCon c, int status, int line) {
136
136
  agooRes res;
137
137
  const char *msg = agoo_http_code_message(status);
138
-
138
+
139
139
  if (NULL == (res = agoo_res_create(c))) {
140
140
  agoo_log_cat(&agoo_error_cat, "memory allocation of response failed on connection %llu @ %d.",
141
141
  (unsigned long long)c->id, line);
@@ -144,7 +144,7 @@ bad_request(agooCon c, int status, int line) {
144
144
  int cnt = snprintf(buf, sizeof(buf),
145
145
  "HTTP/1.1 %d %s\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n", status, msg);
146
146
  agooText message = agoo_text_create(buf, cnt);
147
-
147
+
148
148
  if (NULL == c->res_tail) {
149
149
  c->res_head = res;
150
150
  } else {
@@ -161,7 +161,7 @@ static bool
161
161
  should_close(const char *header, int hlen) {
162
162
  const char *v;
163
163
  int vlen = 0;
164
-
164
+
165
165
  if (NULL != (v = agoo_con_header_value(header, hlen, "Connection", &vlen))) {
166
166
  return (5 == vlen && 0 == strncasecmp("Close", v, 5));
167
167
  }
@@ -172,7 +172,7 @@ static bool
172
172
  page_response(agooCon c, agooPage p, char *hend) {
173
173
  agooRes res;
174
174
  char *b;
175
-
175
+
176
176
  if (NULL == (res = agoo_res_create(c))) {
177
177
  return true;
178
178
  }
@@ -253,7 +253,7 @@ agoo_con_header_read(agooCon c, size_t *mlenp) {
253
253
  const char *v;
254
254
  int vlen = 0;
255
255
  char *vend;
256
-
256
+
257
257
  if (3 == b - c->buf && 0 == strncmp("PUT", c->buf, 3)) {
258
258
  method = AGOO_PUT;
259
259
  } else if (4 == b - c->buf && 0 == strncmp("POST", c->buf, 4)) {
@@ -345,7 +345,7 @@ agoo_con_header_read(agooCon c, size_t *mlenp) {
345
345
  return bad_request(c, 500, __LINE__);
346
346
  }
347
347
  return HEAD_HANDLED;
348
- }
348
+ }
349
349
  if (NULL == agoo_server.hook404) {
350
350
  return bad_request(c, 404, __LINE__);
351
351
  }
@@ -445,7 +445,7 @@ agoo_con_http_read(agooCon c) {
445
445
 
446
446
  switch (agoo_con_header_read(c, &mlen)) {
447
447
  case HEAD_AGAIN:
448
- // Try again the next time. Didn't read enough..
448
+ // Try again the next time. Didn't read enough..
449
449
  return false;
450
450
  case HEAD_OK:
451
451
  // req was created
@@ -528,7 +528,7 @@ con_ws_read(agooCon c) {
528
528
  ssize_t cnt;
529
529
  uint8_t *b;
530
530
  uint8_t op;
531
- long mlen;
531
+ long mlen;
532
532
 
533
533
  if (NULL != c->req) {
534
534
  cnt = recv(c->sock, c->req->msg + c->bcnt, c->req->mlen - c->bcnt, 0);
@@ -667,7 +667,7 @@ agoo_con_http_write(agooCon c) {
667
667
  if (c->wcnt == message->len) { // finished
668
668
  agooRes res = c->res_head;
669
669
  bool done = res->close;
670
-
670
+
671
671
  c->res_head = res->next;
672
672
  if (res == c->res_tail) {
673
673
  c->res_tail = NULL;
@@ -700,11 +700,11 @@ con_ws_write(agooCon c) {
700
700
  }
701
701
  len = snprintf(msg, sizeof(msg) - 1, "Socket error @ %llu.", (unsigned long long)c->id);
702
702
  push_error(c->up, msg, len);
703
-
703
+
704
704
  agoo_log_cat(&agoo_error_cat, "Socket error @ %llu.", (unsigned long long)c->id);
705
705
  agoo_ws_req_close(c);
706
706
  agoo_res_destroy(res);
707
-
707
+
708
708
  return false;
709
709
  }
710
710
  } else if (res->pong) {
@@ -720,7 +720,7 @@ con_ws_write(agooCon c) {
720
720
  agoo_log_cat(&agoo_error_cat, "Socket error @ %llu.", (unsigned long long)c->id);
721
721
  agoo_ws_req_close(c);
722
722
  agoo_res_destroy(res);
723
-
723
+
724
724
  return false;
725
725
  }
726
726
  } else {
@@ -742,7 +742,7 @@ con_ws_write(agooCon c) {
742
742
  c->timeout = dtime() + CON_TIMEOUT;
743
743
  if (0 == c->wcnt) {
744
744
  agooText t;
745
-
745
+
746
746
  if (agoo_push_cat.on) {
747
747
  if (message->bin) {
748
748
  agoo_log_cat(&agoo_push_cat, "%llu binary", (unsigned long long)c->id);
@@ -767,14 +767,14 @@ con_ws_write(agooCon c) {
767
767
  push_error(c->up, msg, len);
768
768
  agoo_log_cat(&agoo_error_cat, "Socket error @ %llu.", (unsigned long long)c->id);
769
769
  agoo_ws_req_close(c);
770
-
770
+
771
771
  return false;
772
772
  }
773
773
  c->wcnt += cnt;
774
774
  if (c->wcnt == message->len) { // finished
775
775
  agooRes res = c->res_head;
776
776
  bool done = res->close;
777
-
777
+
778
778
  c->res_head = res->next;
779
779
  if (res == c->res_tail) {
780
780
  c->res_tail = NULL;
@@ -801,7 +801,7 @@ con_sse_write(agooCon c) {
801
801
  c->timeout = dtime() + CON_TIMEOUT *2;
802
802
  if (0 == c->wcnt) {
803
803
  agooText t;
804
-
804
+
805
805
  if (agoo_push_cat.on) {
806
806
  agoo_log_cat(&agoo_push_cat, "%llu: %s %p", (unsigned long long)c->id, message->text, (void*)res);
807
807
  }
@@ -821,14 +821,14 @@ con_sse_write(agooCon c) {
821
821
  len = snprintf(msg, sizeof(msg) - 1, "Socket error @ %llu.", (unsigned long long)c->id);
822
822
  push_error(c->up, msg, len);
823
823
  agoo_log_cat(&agoo_error_cat, "Socket error @ %llu.", (unsigned long long)c->id);
824
-
824
+
825
825
  return false;
826
826
  }
827
827
  c->wcnt += cnt;
828
828
  if (c->wcnt == message->len) { // finished
829
829
  agooRes res = c->res_head;
830
830
  bool done = res->close;
831
-
831
+
832
832
  c->res_head = res->next;
833
833
  if (res == c->res_tail) {
834
834
  c->res_tail = NULL;
@@ -885,12 +885,12 @@ process_pub_con(agooPub pub, agooConLoop loop) {
885
885
 
886
886
  if (NULL != up && NULL != up->con && up->con->loop == loop) {
887
887
  int pending;
888
-
888
+
889
889
  // TBD Change pending to be based on length of con queue
890
890
  if (1 == (pending = atomic_fetch_sub(&up->pending, 1))) {
891
891
  if (NULL != up && agoo_server.ctx_nil_value != up->ctx && up->on_empty) {
892
892
  agooReq req = agoo_req_create(0);
893
-
893
+
894
894
  req->up = up;
895
895
  req->method = AGOO_ON_EMPTY;
896
896
  req->hook = agoo_hook_create(AGOO_NONE, NULL, up->ctx, PUSH_HOOK, &agoo_server.eval_queue);
@@ -961,7 +961,7 @@ process_pub_con(agooPub pub, agooConLoop loop) {
961
961
  short
962
962
  agoo_con_http_events(agooCon c) {
963
963
  short events = 0;
964
-
964
+
965
965
  if (NULL != c->res_head && NULL != agoo_res_message(c->res_head)) {
966
966
  events = POLLIN | POLLOUT;
967
967
  } else if (!c->closing) {
@@ -1029,7 +1029,7 @@ con_ready_check(void *ctx, double now) {
1029
1029
  agooCon c = (agooCon)ctx;
1030
1030
 
1031
1031
  if (c->dead || 0 == c->sock) {
1032
- if (remove_dead_res(c)) {
1032
+ if (remove_dead_res(c)) {
1033
1033
  return false;
1034
1034
  }
1035
1035
  } else if (0.0 == c->timeout || now < c->timeout) {
@@ -1106,7 +1106,7 @@ static struct _agooHandler con_handler = {
1106
1106
  .read = con_ready_read,
1107
1107
  .write = con_ready_write,
1108
1108
  .error = NULL,
1109
- .destroy = con_ready_destroy,
1109
+ .destroy = con_ready_destroy,
1110
1110
  };
1111
1111
 
1112
1112
  static agooReadyIO
@@ -1119,7 +1119,7 @@ con_queue_ready_read(agooReady ready, void *ctx) {
1119
1119
  agooConLoop loop = (agooConLoop)ctx;
1120
1120
  struct _agooErr err = AGOO_ERR_INIT;
1121
1121
  agooCon c;
1122
-
1122
+
1123
1123
  agoo_queue_release(&agoo_server.con_queue);
1124
1124
  while (NULL != (c = (agooCon)agoo_queue_pop(&agoo_server.con_queue, 0.0))) {
1125
1125
  c->loop = loop;
@@ -1136,8 +1136,8 @@ static struct _agooHandler con_queue_handler = {
1136
1136
  .check = NULL,
1137
1137
  .read = con_queue_ready_read,
1138
1138
  .write = NULL,
1139
- .error = NULL,
1140
- .destroy = NULL,
1139
+ .error = NULL,
1140
+ .destroy = NULL,
1141
1141
  };
1142
1142
 
1143
1143
  static bool
@@ -1157,8 +1157,8 @@ static struct _agooHandler pub_queue_handler = {
1157
1157
  .check = NULL,
1158
1158
  .read = pub_queue_ready_read,
1159
1159
  .write = NULL,
1160
- .error = NULL,
1161
- .destroy = NULL,
1160
+ .error = NULL,
1161
+ .destroy = NULL,
1162
1162
  };
1163
1163
 
1164
1164
  void*
@@ -1170,7 +1170,7 @@ agoo_con_loop(void *x) {
1170
1170
  agooCon c;
1171
1171
  int con_queue_fd = agoo_queue_listen(&agoo_server.con_queue);
1172
1172
  int pub_queue_fd = agoo_queue_listen(&loop->pub_queue);
1173
-
1173
+
1174
1174
  if (NULL == ready) {
1175
1175
  agoo_log_cat(&agoo_error_cat, "Failed to create connection manager. %s", err.msg);
1176
1176
  exit(EXIT_FAILURE);
@@ -1184,7 +1184,7 @@ agoo_con_loop(void *x) {
1184
1184
  return NULL;
1185
1185
  }
1186
1186
  atomic_fetch_add(&agoo_server.running, 1);
1187
-
1187
+
1188
1188
  while (agoo_server.active) {
1189
1189
  while (NULL != (c = (agooCon)agoo_queue_pop(&agoo_server.con_queue, 0.0))) {
1190
1190
  c->loop = loop;
@@ -1215,7 +1215,7 @@ agoo_conloop_create(agooErr err, int id) {
1215
1215
  AGOO_ERR_MEM(err, "connection thread");
1216
1216
  } else {
1217
1217
  int stat;
1218
-
1218
+
1219
1219
  loop->next = NULL;
1220
1220
  if (AGOO_ERR_OK != agoo_queue_multi_init(err, &loop->pub_queue, 256, true, false)) {
1221
1221
  AGOO_FREE(loop);
@@ -1240,7 +1240,7 @@ agoo_conloop_create(agooErr err, int id) {
1240
1240
  void
1241
1241
  agoo_conloop_destroy(agooConLoop loop) {
1242
1242
  agooRes res;
1243
-
1243
+
1244
1244
  agoo_queue_cleanup(&loop->pub_queue);
1245
1245
  while (NULL != (res = loop->res_head)) {
1246
1246
  loop->res_head = res->next;
@@ -25,13 +25,12 @@ error_stream_new() {
25
25
  ErrorStream es = (ErrorStream)AGOO_MALLOC(sizeof(struct _errorStream));
26
26
 
27
27
  if (NULL == es) {
28
- // Error stream is optional. If it is not there is still meets the
29
- // specs. Better not to break everything if this fails.
30
- return Qnil;
28
+ rb_raise(rb_eNoMemError, "Failed to allocate memory for the error stream.");
31
29
  }
32
30
  es->server = NULL;
33
- es->text = agoo_text_allocate(1024);
34
-
31
+ if (NULL == (es->text = agoo_text_allocate(1024))) {
32
+ rb_raise(rb_eNoMemError, "Failed to allocate memory for the error stream.");
33
+ }
35
34
  return Data_Wrap_Struct(es_class, NULL, es_free, es);
36
35
  }
37
36
 
@@ -48,7 +47,9 @@ es_puts(VALUE self, VALUE str) {
48
47
 
49
48
  es->text = agoo_text_append(es->text, StringValuePtr(str), (int)RSTRING_LEN(str));
50
49
  es->text = agoo_text_append(es->text, "\n", 1);
51
-
50
+ if (NULL == es->text) {
51
+ rb_raise(rb_eNoMemError, "Failed to allocate memory for the error stream puts.");
52
+ }
52
53
  return Qnil;
53
54
  }
54
55
 
@@ -62,9 +63,10 @@ static VALUE
62
63
  es_write(VALUE self, VALUE str) {
63
64
  ErrorStream es = (ErrorStream)DATA_PTR(self);
64
65
  int cnt = (int)RSTRING_LEN(str);
65
-
66
- es->text = agoo_text_append(es->text, StringValuePtr(str), cnt);
67
66
 
67
+ if (NULL == (es->text = agoo_text_append(es->text, StringValuePtr(str), cnt))) {
68
+ rb_raise(rb_eNoMemError, "Failed to allocate memory for the error stream puts.");
69
+ }
68
70
  return INT2NUM(cnt);
69
71
  }
70
72
 
data/ext/agoo/gqlcobj.c CHANGED
@@ -7,6 +7,31 @@
7
7
  #include "debug.h"
8
8
  #include "gqlcobj.h"
9
9
  #include "gqleval.h"
10
+ #include "gqlvalue.h"
11
+ #include "graphql.h"
10
12
 
11
13
 
14
+ gqlType
15
+ gql_cobj_ref_type(gqlRef ref) {
16
+ gqlCobj obj = (gqlCobj)ref;
17
+
18
+ if (NULL != obj && NULL != obj->clas) {
19
+ return gql_type_get(obj->clas->name);
20
+ }
21
+ return NULL;
22
+ }
23
+
24
+ int
25
+ gql_cobj_resolve(agooErr err, gqlDoc doc, gqlRef target, gqlField field, gqlSel sel, gqlValue result, int depth) {
26
+ gqlCobj obj = (gqlCobj)target;
27
+ gqlCmethod method;
28
+
29
+ for (method = obj->clas->methods; NULL != method->key; method++) {
30
+ if (0 == strcmp(method->key, sel->name)) {
31
+ return method->func(err, doc, obj, field, sel, result, depth);
32
+ }
33
+ }
34
+ return agoo_err_set(err, AGOO_ERR_EVAL, "%s is not a field on %s.", sel->name, obj->clas->name);
35
+ }
36
+
12
37
  // TBD when a type is created, add a cobj to it