Skip to content
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

Merged
merged 19 commits into from
Oct 15, 2024
Merged

Conversation

parfeon
Copy link
Contributor

@parfeon parfeon commented Sep 11, 2024

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.

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).
@parfeon parfeon added status: in progress This issue is being worked on. priority: medium This PR should be reviewed after all high priority PRs. type: feature This PR contains new feature. labels Sep 11, 2024
@parfeon parfeon self-assigned this Sep 11, 2024
@Xavrax
Copy link
Contributor

Xavrax commented Sep 11, 2024

image

10k changes

Copy link
Contributor

@Xavrax Xavrax left a 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.

.github/workflows/run-tests.yml Show resolved Hide resolved
@@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespace ;o

// Types
// ----------------------------------------------

// Sharable data type definition.
Copy link
Contributor

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 :/

Copy link
Contributor Author

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.

Comment on lines 183 to 188
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;
}
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

@Xavrax Xavrax left a 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>
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

@Xavrax Xavrax Sep 13, 2024

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. :/

Copy link
Contributor

@Xavrax Xavrax left a 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 -*- */
Copy link
Contributor

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

Comment on lines 302 to 304
// Temporarily release lock to avoid deadlocks from subscription ee core
// code access the list of subscribables.
pubnub_mutex_unlock(set->mutw);
Copy link
Contributor

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?

Comment on lines +611 to +612
if (0 == pbref_counter_free(listener->counter)) { free(listener); }
}
Copy link
Contributor

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"
Copy link
Contributor

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

parfeon and others added 2 commits October 2, 2024 21:24
feat(retry): add retry policy

Add failed request automated retry configuration and timer implementations.
@parfeon parfeon marked this pull request as ready for review October 2, 2024 18:34
@parfeon parfeon requested a review from seba-aln as a code owner October 2, 2024 18:34
@parfeon parfeon requested a review from Xavrax October 3, 2024 07:30
Copy link
Contributor

@Xavrax Xavrax left a 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
Copy link
Contributor

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.

Copy link
Contributor Author

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: Cpp11c++11` (previous value wasn't recognized)

Copy link
Contributor

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

CMakeLists.txt Outdated Show resolved Hide resolved
core/pbauto_heartbeat.c Show resolved Hide resolved
Comment on lines +11 to +17
void pbcc_free_ptr(void** ptr)
{
if (NULL == ptr || NULL == *ptr) return;

free(*ptr);
*ptr = NULL;
}
Copy link
Contributor

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.

Copy link
Contributor Author

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 :)

Comment on lines +40 to +48
#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; \
}
Copy link
Contributor

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.

Copy link
Contributor Author

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”?

Copy link
Contributor

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_netcore.c Show resolved Hide resolved
{
if (NULL == entity || NULL == *entity) { return false; }

printf("~~~~~~> RESULT: %d\n", is_pubnub_entity_(*entity));
Copy link
Contributor

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 -*- */
Copy link
Contributor

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).

Copy link
Contributor Author

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.

core/pbcc_subscribe_event_engine_events.c Outdated Show resolved Hide resolved
core/pubnub_retry_configuration.c Show resolved Hide resolved
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
Copy link
Contributor

@Xavrax Xavrax left a 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.

Comment on lines +156 to +176
#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
Copy link
Contributor

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?

Copy link
Contributor Author

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)?

Comment on lines 57 to 59
ifndef USE_CRYPTO_API
USE_CRYPTO_API = 0
USE_CRYPTO_API = 1
endif
Copy link
Contributor

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?

Copy link
Contributor Author

@parfeon parfeon Oct 14, 2024

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.

Comment on lines +331 to +332
rslt.match_or_group.ptr = (char*)found.start + 1;
rslt.match_or_group.size = found.end - found.start - 2;
Copy link
Contributor

@Xavrax Xavrax Oct 14, 2024

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?

Copy link
Contributor Author

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.

Comment on lines 116 to 123
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);
Copy link
Contributor

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?

Copy link
Contributor Author

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.
Copy link
Contributor

@Xavrax Xavrax left a 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

@parfeon
Copy link
Contributor Author

parfeon commented Oct 15, 2024

@pubnub-release-bot release

@parfeon parfeon merged commit dab23a6 into master Oct 15, 2024
5 checks passed
@parfeon parfeon deleted the CLEN-2083 branch October 15, 2024 14:01
@pubnub-release-bot
Copy link
Contributor

🚀 Release successfully completed 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: medium This PR should be reviewed after all high priority PRs. status: in progress This issue is being worked on. type: feature This PR contains new feature.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants