-
Notifications
You must be signed in to change notification settings - Fork 57
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
Subscription Event Engine and Events Listener implementation #196
Conversation
Add core Event Engine implementation with required set of types and methods. feat(subscribe-event-engine): add subscribe event engine Add Subscribe Event Engine built atop of core Event Engine implementation. feat(entities): add base PubNub entities Add following entities: channel, channel group, uuid and channel metadata objects. feat(subscription): add subscription and subscription sets Add objects to manage subscription and provides interface fow updated listeners. feat(listeners): add event listener Add new event listeners which make it possible to add listeners to specific entity or group of entities (though subscription and subscription set).
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.
18/40 files reviewed.
Overall I love your design.
Some questions.
Also it would be nice to have example that shows users how to use the new API.
core/pbauto_heartbeat.c
Outdated
@@ -559,7 +560,7 @@ bool pubnub_is_auto_heartbeat_enabled(pubnub_t* pb) | |||
} | |||
|
|||
|
|||
void pbauto_heartbeat_free_channelInfo(pubnub_t* pb) | |||
void pbauto_heartbeat_free_channelInfo(pubnub_t* pb) |
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.
whitespace ;o
core/pbcc_event_engine.c
Outdated
// Types | ||
// ---------------------------------------------- | ||
|
||
// Sharable data type definition. |
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.
We use
/** Cryptor algorithm identifier. */
this kind of the inline docs in c-core :/
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.
I tried to find a reason to use this form, but only multiline comments (which is not the case for one-liner) came to my mind. I don't mind. Will change.
core/pbcc_event_engine.c
Outdated
pbcc_ee_invocation_t* inv = _pbcc_ee_invocation_copy( | ||
(pbcc_ee_invocation_t*)pbarray_element_at(invocations, i)); | ||
if (PBAR_OK != pbarray_add(ee->invocations,inv)) { | ||
pbcc_ee_invocation_free(inv); | ||
rslt = PNR_OUT_OF_MEMORY; | ||
} |
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.
As we say that there is no more memory - should we still continue the process?
Shouldn't we somehow only free the allocations and break the loop?
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.
Good catch!
break
is missing and failed transition invocation handled few lines below by removing invocations which have been added from this new transition into EE invocations queue.
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.
Seems good (30/40 files review)
@@ -3,6 +3,7 @@ | |||
#if !defined INC_PUBNUB_INTERNAL_COMMON | |||
#define INC_PUBNUB_INTERNAL_COMMON | |||
|
|||
#include <stdbool.h> |
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.
I see many random import changes.
Probably they're related to the architecture and feature sets. Am I right?
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.
Some imports have been removed because IDE shown that they are unused, some added in other place.
To be honest, <stdbool.h>
and core/c99/stdbool.h
: not sure about intention. Do we still need the latest c89 support (as I understand this is the only reason why core/c99/stdbool.h
exists because bool
is missing from C89 std)?
Moreover, additionally I was confused by feature flags which let specify custom booleans at a compile-time and wasn't sure whether it needed to be utilized in any way.
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.
Do we still need the latest c89 support
This topic is still under the discussion. :/
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.
Overall LGTM
Some new comments.
- I'm asking for sub EE sample to progress with the PR ;d.
@@ -0,0 +1,643 @@ | |||
/* -*- c-file-style:"stroustrup"; indent-tabs-mode: nil -*- */ |
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.
Tbh - I would love to have such utilities all across the SDK ;d
core/pubnub_subscribe_event_engine.c
Outdated
// Temporarily release lock to avoid deadlocks from subscription ee core | ||
// code access the list of subscribables. | ||
pubnub_mutex_unlock(set->mutw); |
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.
I'm a little bit worried about this statement.
Is it possible that this quite short amount of time unguarded mutex might mess anything in execution?
if (0 == pbref_counter_free(listener->counter)) { free(listener); } | ||
} |
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.
Shouldn't we set listener
to NULL
?
@@ -0,0 +1,2485 @@ | |||
#include "pbcc_subscribe_event_engine.h" |
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.
Nitpicking: If I were you, I would split this file into smaller ones. ;d
feat(retry): add retry policy Add failed request automated retry configuration and timer implementations.
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.
There was a lot of files and lines.
I hope that I didn't miss anything.
Overall LGTM.
Some questions and things to do before the merge.
@@ -88,7 +88,7 @@ PenaltyExcessCharacter: 4 | |||
PenaltyReturnTypeOnItsOwnLine: 100 |
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.
Do you use format for single files?
I want to reformat the whole repository but there are some issues with compilation so I'm confused how does it work on your side.
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.
Hm, I didn't receive a penalty there.
Also, it already was there and the only thing which I changed was the Standard:
value:
Cpp11→
c++11` (previous value wasn't recognized)
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.
mhm.
Please do not format whole codebase within this PR.
I want to do it at some point, but it makes ~80k lines change :D
void pbcc_free_ptr(void** ptr) | ||
{ | ||
if (NULL == ptr || NULL == *ptr) return; | ||
|
||
free(*ptr); | ||
*ptr = NULL; | ||
} |
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.
This is quite risky approach.
What in case whereas ptr
points to the allocated memory.
I know that propably not in your use-case but I'm aware of the future development and using this function on allocated pointer to allocated pointer (which is ofc very tricky and nobody should do this ofc) might fail.
I can assume some array of pointers that might be failing here.
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.
I will remove this function because the task for which it has been done has been solved in another way :)
#define PBCC_ALLOCATE_TYPE(var, type, print_error_message, return_value) \ | ||
type *var = (type *)malloc(sizeof(type)); \ | ||
if (NULL == var) { \ | ||
if (true == print_error_message) { \ | ||
PUBNUB_LOG_ERROR("[%s] Failed to allocate memory for '%s'\n",\ | ||
__func__, #type); \ | ||
} \ | ||
return return_value; \ | ||
} |
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.
I'm aware of macros.
This one seems to be valid but I'm affraid that it might generate very strange compilation errors.
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.
What do you mean by “strange”?
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.
I'm back in the days when compilers couldn't distinguish the generated from macro code from the hand-written ones.
I remember that I had to count lines of macro to find where exactly the problem occurred ;D
But I'm not against macros - just wanted to add a note about it. ;d
core/pubnub_entities.c
Outdated
{ | ||
if (NULL == entity || NULL == *entity) { return false; } | ||
|
||
printf("~~~~~~> RESULT: %d\n", is_pubnub_entity_(*entity)); |
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.
debug print
@@ -0,0 +1,28 @@ | |||
/* -*- c-file-style:"stroustrup"; indent-tabs-mode: nil -*- */ |
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.
Have you used sanitizers to test it?
If not I can do it for you tomorrow (or any other day).
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.
@Xavrax nope. You asked me to add it, so I just copied everywhere :)
Need to see if there are any for CLion.
Fixed issue because of which `matched` field had wrong value and length. fix(event-engine): fix consequential subscribe invocations In certain situations, Event Engine contained invocations which held outdated data and shouldn't be called. refactor(demo): completed subscribe event engine and listeners sample application
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.
Great job!
LGTM
Few questions.
Gonna approve right after sanitizers' issues are resolved.
#if PUBNUB_USE_RETRY_CONFIGURATION | ||
if (NULL != pb->core.retry_configuration && | ||
pubnub_retry_configuration_retryable_result_(pb)) { | ||
uint16_t delay = pubnub_retry_configuration_delay_(pb); | ||
|
||
if (delay > 0) { | ||
if (NULL == pb->core.retry_timer) | ||
pb->core.retry_timer = pbcc_request_retry_timer_alloc(pb); | ||
if (NULL != pb->core.retry_timer) { | ||
pbcc_request_retry_timer_start(pb->core.retry_timer, delay); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
/** There were no need to start retry timer, we can free it if exists. */ | ||
if (NULL != pb->core.retry_timer) { | ||
pb->core.http_retry_count = 0; | ||
pbcc_request_retry_timer_free(&pb->core.retry_timer); | ||
} | ||
#endif // #if PUBNUB_USE_RETRY_CONFIGURATION |
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.
Q: is it possible to merge it in different files to have one universal function?
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.
@Xavrax can you elaborate more on this one? This code is identical in three files - do you want to add new function which have this code inside and use it in those files (function will return boolean to know whether flow should continue or not)?
ifndef USE_CRYPTO_API | ||
USE_CRYPTO_API = 0 | ||
USE_CRYPTO_API = 1 | ||
endif |
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.
Q: Should it be enabled by default? In Cmake default value is OFF
?
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.
@Xavrax in current file (at the end of the line) you can see that crypto files were there unconditionally and when guards has been fixed it started to cause problems.
Here it has been enabled by default because CI runs all
task which require crypto module to be used - this is the reason why I enabled it in those files.
rslt.match_or_group.ptr = (char*)found.start + 1; | ||
rslt.match_or_group.size = found.end - found.start - 2; |
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.
Q:
+ "
character
- "\n
characters
Am I right?
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.
@Xavrax When I tried to find listener for group, I've got something like this: "channel_group\"
. Then I checked how regular channel parsed, and it looks like there were these fixed added before.
core/pbcc_request_retry_timer.c
Outdated
pubnub_mutex_lock(timer->mutw); | ||
timer->running = true; | ||
timer->delay = delay; | ||
pubnub_mutex_unlock(timer->mutw); | ||
pubnub_mutex_lock(timer->pb->monitor); | ||
timer->pb->state = PBS_WAIT_RETRY; | ||
timer->pb->core.http_retry_count++; | ||
pubnub_mutex_unlock(timer->pb->monitor); |
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.
Q: is it okay to lock those locks separetely?
Won't it cause any UB?
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.
@Xavrax I don't think it is critical, but I can put one of them inside another after sanitizer check (I hope it is not critical).
Fix issue because of which demo app crashed in attempt to free up static strings. refactor(retry-timer): update mutex lock scope Include one of mutex in another (timer inside of PubNub context mutex).
Fix issues because of which library crashes in attempt to move memory into overlapping region.
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.
Works on my side <3
@pubnub-release-bot release |
🚀 Release successfully completed 🚀 |
feat(event-engine): add general event engine
Add core Event Engine implementation with the required set of types and methods.
feat(subscribe-event-engine): add subscribe event engine
Add Subscribe Event Engine built atop of the core Event Engine implementation.
feat(entities): add base PubNub entities
Add the following entities: channel, channel group, uuid and channel metadata objects.
feat(subscription): add subscription and subscription sets
Add objects to manage subscriptions and provides interface for update listeners.
feat(listeners): add event listener
Add new event listeners, which make it possible to add listeners to a specific entity or group of entities (though subscription and subscription set).
feat(retry): add request retry configuration
Added ability to configure automated retry policies for failed requests.