-
Notifications
You must be signed in to change notification settings - Fork 161
[WIP] Add option to merge nats core and jetstream subscriptions #971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8147ea1
cf3fbb7
e7958e5
30d0d82
7655acd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1352,6 +1352,7 @@ | |
| void natsSubscription_Destroy(natsSubscription *sub) | ||
| { | ||
| bool doUnsub = false; | ||
| int shareCount = 0; | ||
|
|
||
| if (sub == NULL) | ||
| return; | ||
|
|
@@ -1370,10 +1371,130 @@ | |
| if (sub->jsi != NULL) | ||
| sub->jsi->dc = false; | ||
|
|
||
| if (sub->shareCount > 0) | ||
| sub->shareCount--; | ||
|
|
||
| shareCount = sub->shareCount; | ||
| natsSub_Unlock(sub); | ||
|
|
||
| // Don't close or free the subscription if it's still in use | ||
| if (shareCount != 0) | ||
| return; | ||
|
|
||
| if (doUnsub) | ||
| (void)natsSubscription_Unsubscribe(sub); | ||
|
|
||
| natsSub_release(sub); | ||
| } | ||
|
|
||
| static void | ||
| _sharedRespHandler(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure) | ||
| { | ||
| int len = 0; | ||
| const char *subj = subj = natsMsg_GetSubject(msg); | ||
|
|
||
| len = strlen(subj); | ||
| printf("Received message on subject: %s subjlen = %d; subscription subj = %s, nc->reqIdOffset = %d\n", | ||
| subj, len, sub->subject, nc->reqIdOffset); | ||
|
|
||
| if (len == nc->reqIdOffset + 1 && subj[len - 1] == '0') | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would work only for the first NATS core request ;-) (the core reply subject normally is |
||
| { | ||
| printf("In nc resp handler\n"); | ||
| natsConnection_respHandler(nc, sub, msg, closure); | ||
| } | ||
| else | ||
| { | ||
| printf("In js async reply handler\n"); | ||
| js_handleAsyncReply(nc, sub, msg, closure); | ||
| } | ||
| } | ||
|
|
||
| natsStatus | ||
| natsSubscription_CreateSharedSubscription(jsCtx *js) | ||
| { | ||
| natsSubscription *sub = NULL; | ||
| natsStatus s = NATS_OK; | ||
| natsConnection *nc = js->nc; | ||
|
|
||
| // If either are already set, we shouldn't create a new one | ||
AdamPayzant marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if ((nc->respMux != NULL) || (js->rsub != NULL) || (js->nc != nc)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reference to |
||
| return NATS_INVALID_ARG; | ||
| } | ||
|
|
||
| natsMutex_Lock(nc->mu); | ||
| natsMutex_Lock(js->mu); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand why you would do this way, but I don't recall if there is already such case of holding the two locks, this would need to be verified to see if there could be a lock ordering issue. |
||
|
|
||
| nc->respPool = NATS_CALLOC(RESP_INFO_POOL_MAX_SIZE, sizeof(respInfo*)); | ||
| if (nc->respPool == NULL) | ||
| s = nats_setDefaultError(NATS_NO_MEMORY); | ||
| if (s == NATS_OK) | ||
| s = natsStrHash_Create(&nc->respMap, 4); | ||
|
|
||
| IFOK(s, natsCondition_Create(&(js->cond))); | ||
| IFOK(s, natsStrHash_Create(&(js->pm), 64)); | ||
| if (s == NATS_OK) | ||
| { | ||
| js->rpre = NATS_MALLOC(js->rpreLen+1); | ||
| if (js->rpre == NULL) | ||
| s = nats_setDefaultError(NATS_NO_MEMORY); | ||
| else | ||
| { | ||
| char nuid[NUID_BUFFER_LEN+1]; | ||
|
|
||
| s = natsNUID_Next(nuid, sizeof(nuid)); | ||
| if (s == NATS_OK) | ||
| { | ||
| memcpy(js->rpre, js->nc->inboxPfx, js->nc->inboxPfxLen); | ||
| memcpy(js->rpre+js->nc->inboxPfxLen, nuid+((int)strlen(nuid)-8), 8); | ||
| js->rpre[js->rpreLen-1] = '.'; | ||
| js->rpre[js->rpreLen] = '\0'; | ||
| } | ||
| } | ||
| } | ||
| if (s == NATS_OK) | ||
| { | ||
| char *subj = NULL; | ||
|
|
||
| if (nats_asprintf(&subj, "%s*", js->rpre) < 0) | ||
| s = nats_setDefaultError(NATS_NO_MEMORY); | ||
| else | ||
| { | ||
| s = natsConn_subscribeNoPool(&sub, js->nc, subj, _sharedRespHandler, (void*) js); | ||
| if (s == NATS_OK) | ||
| { | ||
| nc->respSub = subj; | ||
| nc->reqIdOffset = js->rpreLen; | ||
|
|
||
| sub->shareCount = 2; | ||
| nc->respMux = sub; | ||
| js->rsub = sub; | ||
| } | ||
| else { | ||
| NATS_FREE(subj); | ||
| } | ||
| } | ||
|
|
||
| if (s == NATS_OK) | ||
| { | ||
| _retain(js); | ||
| natsSubscription_SetPendingLimits(js->rsub, -1, -1); | ||
| natsSubscription_SetOnCompleteCB(js->rsub, js_subComplete, (void*) js); | ||
| } | ||
| } | ||
| if (s != NATS_OK) | ||
| { | ||
| // Undo the things we created so we retry again next time. | ||
| // It is either that or we have to always check individual | ||
| // objects to know if we have to create them. | ||
| NATS_FREE(js->rpre); | ||
| js->rpre = NULL; | ||
| natsStrHash_Destroy(js->pm); | ||
| js->pm = NULL; | ||
| natsCondition_Destroy(js->cond); | ||
| js->cond = NULL; | ||
| } | ||
|
|
||
| natsMutex_Unlock(nc->mu); | ||
| natsMutex_Unlock(js->mu); | ||
| return NATS_UPDATE_ERR_STACK(s); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42397,3 +42397,59 @@ int main(int argc, char **argv) | |
| printf("ALL PASSED\n"); | ||
| return 0; | ||
| } | ||
|
|
||
| void test_JetStreamSharedSub(void) | ||
| { | ||
| natsStatus s; | ||
| natsMsg *msg = NULL; | ||
| natsMsg *req = NULL; | ||
| struct threadArg arg; | ||
| natsSubscription *sub = NULL; | ||
|
|
||
| JS_SETUP(2, 12, 0); | ||
|
|
||
| s = _createDefaultThreadArgsForCbTests(&arg); | ||
| if ( s != NATS_OK) | ||
| FAIL("Unable to setup test!"); | ||
|
|
||
| arg.string = "I will help you"; | ||
| arg.status = NATS_OK; | ||
| arg.control= 4; | ||
|
|
||
| test("Creating shared subscription: "); | ||
| s = natsSubscription_CreateSharedSubscription(js); | ||
| testCond(s == NATS_OK); | ||
|
|
||
| test("Subscribe: "); | ||
| IFOK(s, natsConnection_Subscribe(&sub, nc, "foo", _recvTestString, (void*) &arg)); | ||
| testCond(s == NATS_OK); | ||
|
|
||
| test("Validate Jetstream Publish: "); | ||
| s = natsMsg_Create(&req, "foo", NULL, "help", 4); | ||
| IFOK(s, js_PublishMsgAsync(js, &req, NULL)); | ||
| testCond(s == NATS_OK); | ||
|
|
||
| test("Wait for publish ack: "); | ||
| s = js_PublishAsyncComplete(js, NULL); | ||
| testCond(s == NATS_OK); | ||
| natsMsg_Destroy(req); | ||
|
|
||
AdamPayzant marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| test("Create req message: "); | ||
| s = natsMsg_Create(&req, "foo", NULL, "help", 4); | ||
| testCond(s == NATS_OK); | ||
|
|
||
| test("Validate Core RequestMsg: "); | ||
| s = natsConnection_RequestMsg(&msg, nc, req, 100); | ||
| natsMutex_Lock(arg.m); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would not the I am not entirely sure what you are trying to test here. |
||
| while ((s != NATS_TIMEOUT) && !arg.msgReceived) | ||
| s = natsCondition_TimedWait(arg.c, arg.m, 2000); | ||
AdamPayzant marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| natsMutex_Unlock(arg.m); | ||
| testCond(s == NATS_OK); | ||
| natsMsg_Destroy(req); | ||
| natsMsg_Destroy(msg); | ||
|
|
||
| natsSubscription_Destroy(sub); | ||
| _destroyDefaultThreadArgs(&arg); | ||
|
|
||
| JS_TEARDOWN; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would need documentation here... which would help me understand what this function is supposed to do ;-)