Skip to content

Commit

Permalink
eventEngine (#334)
Browse files Browse the repository at this point in the history
* feat: cucumber refactor

* feat: add more steps

* feat: current progress

* refactor event-engine(from draft PR)

* event-engine: update to latest description, added some missing transitions

* prettier!

* take: fix hanging tests due to retry intro

* update as per latest event engine specs

* * cucumber tsflow

* prettier!

* fix: test and version mismatch from branch merge

* fix: version

* add: reconnection configuration

* lint/prettier

* fix: test. destroy() not required

* fix: naming convention and removed unnecessary effect dispatch

* WIP: presence event engine

* organised files and directories for presence

* fix: paths

* fix: lint

* presence and subscribe event engine states

* event engine effects and events

* retry policy configuration

* event engines tests

* updated stateless utilities

* updated PubNub with configurations

* lib and dist

* take-1 fix lint

* fix: elint config

* sync: package-lock

* fix: package-lock

* WIP take-1(non-status events): Listener compatibility with eventEngine

* take-2: (presence) listener structs backward compatibility.

* lib and dist

* lint

* event engine: naming, missing transitions, handling `reconnect` and `restore` all applicable states, removed old definitions for events

* event engine: receiving state as per specifications

* refined naming for event engine events and effects

* retryConfiguration behaviour updates

* presence eventengine: removed unnecessary emitStatus events as per specifications

* config naming convention, eventengine initialisation updates as per new updated naming conventions

* updated tests

* dist, lib and lint fixes

* package-lock dependabot suggestion, fix test

* removed duplicate file

* fix: prevent duplicate listener to be added.

* dist/lib files

* retry delay can be override by retry after value

* handled cursor across the states

* manage cursor from event struct

* dist and lib

* refactor: reconnect event handling

* getSubscribedChannels and channelGroups binding when eventEngine is enabled

* refactor: retry policy delay calculation

* handshake* states: handling cursor value across state and defaulting to 0 for region when context/event has undefined

* receiv* states: handling cursor across states

* lib/dist

* addressed review comments : handling cursor value from context from handshake and receiveFailed

* revert test file changes

* fix: lint

* sync package-lock

* removed flow_interfaces reference

* PubNub SDK v7.5.0 release.

---------

Co-authored-by: Artur Wojciechowski <me@iama.re>
Co-authored-by: PubNub Release Bot <120067856+pubnub-release-bot@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 16, 2024
1 parent 76bc504 commit f0bd4e5
Show file tree
Hide file tree
Showing 194 changed files with 6,349 additions and 8,834 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ module.exports = {
'class-methods-use-this': 0,
'no-prototype-builtins': 1,
'prefer-destructuring': 0,
'no-unused-vars': 0,
'@typescript-eslint/no-unused-vars': 0,
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
};
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dist/titanium/stats.json
dist/contract
dist/cucumber
upload
test/specs

# GitHub Actions #
##################
Expand Down
15 changes: 12 additions & 3 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
---
changelog:
- date: 2024-01-16
version: v7.5.0
changes:
- type: feature
text: "Added `enableEventEngine`, `maintainPresenceState` flags and `retryConfiguration` for retry policy configuration."
- type: bug
text: "Fixes issue of allowing duplicate listener registration."
- type: bug
text: "Fixes file name conflict in lib directory."
- date: 2023-11-28
version: v7.4.5
changes:
Expand Down Expand Up @@ -929,7 +938,7 @@ supported-platforms:
- 'Ubuntu 14.04 and up'
- 'Windows 7 and up'
version: 'Pubnub Javascript for Node'
version: '7.4.5'
version: '7.5.0'
sdks:
- full-name: PubNub Javascript SDK
short-name: Javascript
Expand All @@ -945,7 +954,7 @@ sdks:
- distribution-type: source
distribution-repository: GitHub release
package-name: pubnub.js
location: https://github.com/pubnub/javascript/archive/refs/tags/v7.4.5.zip
location: https://github.com/pubnub/javascript/archive/refs/tags/v7.5.0.zip
requires:
- name: 'agentkeepalive'
min-version: '3.5.2'
Expand Down Expand Up @@ -1616,7 +1625,7 @@ sdks:
- distribution-type: library
distribution-repository: GitHub release
package-name: pubnub.js
location: https://github.com/pubnub/javascript/releases/download/v7.4.5/pubnub.7.4.5.js
location: https://github.com/pubnub/javascript/releases/download/v7.5.0/pubnub.7.5.0.js
requires:
- name: 'agentkeepalive'
min-version: '3.5.2'
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## v7.5.0
January 16 2024

#### Added
- Added `enableEventEngine`, `maintainPresenceState` flags and `retryConfiguration` for retry policy configuration.

#### Fixed
- Fixes issue of allowing duplicate listener registration.
- Fixes file name conflict in lib directory. Fixed the following issues reported by [@priyanshu102002](https://github.com/priyanshu102002): [#355](https://github.com/pubnub/javascript/issues/355).

## v7.4.5
November 28 2023

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ Watch [Getting Started with PubNub JS SDK](https://app.dashcam.io/replay/64ee0d2
npm install pubnub
```
* or download one of our builds from our CDN:
* https://cdn.pubnub.com/sdk/javascript/pubnub.7.4.5.js
* https://cdn.pubnub.com/sdk/javascript/pubnub.7.4.5.min.js
* https://cdn.pubnub.com/sdk/javascript/pubnub.7.5.0.js
* https://cdn.pubnub.com/sdk/javascript/pubnub.7.5.0.min.js
2. Configure your keys:
Expand Down
12 changes: 12 additions & 0 deletions cucumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
default: [
'test/specs/features/**/*.feature',
'--require test/contract/setup.js',
'--require test/contract/definitions/**/*.ts',
'--require test/contract/shared/**/*.ts',
'--format summary',
'--format progress-bar',
// '--format @cucumber/pretty-formatter',
'--publish-quiet',
].join(' '),
};
1,271 changes: 1,132 additions & 139 deletions dist/web/pubnub.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/web/pubnub.min.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions lib/core/components/_endpoint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
26 changes: 22 additions & 4 deletions lib/core/components/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var makeDefaultOrigins = function () { return Array.from({ length: 20 }, functio
var default_1 = /** @class */ (function () {
function default_1(_a) {
var setup = _a.setup;
var _b, _c, _d;
var _b, _c, _d, _e;
this._PNSDKSuffix = {};
this.instanceId = "pn-".concat(uuid_1.default.createUUID());
this.secretKey = setup.secretKey || setup.secret_key;
Expand Down Expand Up @@ -40,8 +40,8 @@ var default_1 = /** @class */ (function () {
this.customDecrypt = setup.customDecrypt;
this.fileUploadPublishRetryLimit = (_b = setup.fileUploadPublishRetryLimit) !== null && _b !== void 0 ? _b : 5;
this.useRandomIVs = (_c = setup.useRandomIVs) !== null && _c !== void 0 ? _c : true;
// flag for beta subscribe feature enablement
this.enableSubscribeBeta = (_d = setup.enableSubscribeBeta) !== null && _d !== void 0 ? _d : false;
this.enableEventEngine = (_d = setup.enableEventEngine) !== null && _d !== void 0 ? _d : false;
this.maintainPresenceState = (_e = setup.maintainPresenceState) !== null && _e !== void 0 ? _e : true;
// if location config exist and we are in https, force secure to true.
if (typeof location !== 'undefined' && location.protocol === 'https:') {
this.secure = true;
Expand All @@ -53,6 +53,9 @@ var default_1 = /** @class */ (function () {
this.useInstanceId = setup.useInstanceId || false;
this.useRequestId = setup.useRequestId || false;
this.requestMessageCountThreshold = setup.requestMessageCountThreshold;
if (setup.retryConfiguration) {
this._setRetryConfiguration(setup.retryConfiguration);
}
// set timeout to how long a transaction request will wait for the server (default 15 seconds)
this.setTransactionTimeout(setup.transactionalRequestTimeout || 15 * 1000);
// set timeout to how long a subscribe event loop will run (default 310 seconds)
Expand Down Expand Up @@ -177,7 +180,22 @@ var default_1 = /** @class */ (function () {
return this;
};
default_1.prototype.getVersion = function () {
return '7.4.5';
return '7.5.0';
};
default_1.prototype._setRetryConfiguration = function (configuration) {
if (configuration.minimumdelay < 2) {
throw new Error('Minimum delay can not be set less than 2 seconds for retry');
}
if (configuration.maximumDelay > 150) {
throw new Error('Maximum delay can not be set more than 150 seconds for retry');
}
if (configuration.maximumDelay && maximumRetry > 6) {
throw new Error('Maximum retry for exponential retry policy can not be more than 6');
}
else if (configuration.maximumRetry > 10) {
throw new Error('Maximum retry for linear retry policy can not be more than 10');
}
this.retryConfiguration = configuration;
};
default_1.prototype._addPnsdkSuffix = function (name, suffix) {
this._PNSDKSuffix[name] = suffix;
Expand Down
212 changes: 212 additions & 0 deletions lib/core/components/eventEmitter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var EventEmitter = /** @class */ (function () {
function EventEmitter(_a) {
var modules = _a.modules, listenerManager = _a.listenerManager, getFileUrl = _a.getFileUrl;
this.modules = modules;
this.listenerManager = listenerManager;
this.getFileUrl = getFileUrl;
if (modules.cryptoModule)
this._decoder = new TextDecoder();
}
EventEmitter.prototype.emitEvent = function (e) {
var channel = e.channel, publishMetaData = e.publishMetaData;
var subscriptionMatch = e.subscriptionMatch;
if (channel === subscriptionMatch) {
subscriptionMatch = null;
}
if (e.channel.endsWith('-pnpres')) {
var announce = {};
announce.channel = null;
announce.subscription = null;
if (channel) {
announce.channel = channel.substring(0, channel.lastIndexOf('-pnpres'));
}
if (subscriptionMatch) {
announce.subscription = subscriptionMatch.substring(0, subscriptionMatch.lastIndexOf('-pnpres'));
}
announce.action = e.payload.action;
announce.state = e.payload.data;
announce.timetoken = publishMetaData.publishTimetoken;
announce.occupancy = e.payload.occupancy;
announce.uuid = e.payload.uuid;
announce.timestamp = e.payload.timestamp;
if (e.payload.join) {
announce.join = e.payload.join;
}
if (e.payload.leave) {
announce.leave = e.payload.leave;
}
if (e.payload.timeout) {
announce.timeout = e.payload.timeout;
}
this.listenerManager.announcePresence(announce);
}
else if (e.messageType === 1) {
var announce = {};
announce.channel = null;
announce.subscription = null;
announce.channel = channel;
announce.subscription = subscriptionMatch;
announce.timetoken = publishMetaData.publishTimetoken;
announce.publisher = e.issuingClientId;
if (e.userMetadata) {
announce.userMetadata = e.userMetadata;
}
announce.message = e.payload;
this.listenerManager.announceSignal(announce);
}
else if (e.messageType === 2) {
var announce = {};
announce.channel = null;
announce.subscription = null;
announce.channel = channel;
announce.subscription = subscriptionMatch;
announce.timetoken = publishMetaData.publishTimetoken;
announce.publisher = e.issuingClientId;
if (e.userMetadata) {
announce.userMetadata = e.userMetadata;
}
announce.message = {
event: e.payload.event,
type: e.payload.type,
data: e.payload.data,
};
this.listenerManager.announceObjects(announce);
if (e.payload.type === 'uuid') {
var eventData = this._renameChannelField(announce);
this.listenerManager.announceUser(__assign(__assign({}, eventData), { message: __assign(__assign({}, eventData.message), { event: this._renameEvent(eventData.message.event), type: 'user' }) }));
}
else if (message.payload.type === 'channel') {
var eventData = this._renameChannelField(announce);
this.listenerManager.announceSpace(__assign(__assign({}, eventData), { message: __assign(__assign({}, eventData.message), { event: this._renameEvent(eventData.message.event), type: 'space' }) }));
}
else if (message.payload.type === 'membership') {
var eventData = this._renameChannelField(announce);
var _a = eventData.message.data, user = _a.uuid, space = _a.channel, membershipData = __rest(_a, ["uuid", "channel"]);
membershipData.user = user;
membershipData.space = space;
this.listenerManager.announceMembership(__assign(__assign({}, eventData), { message: __assign(__assign({}, eventData.message), { event: this._renameEvent(eventData.message.event), data: membershipData }) }));
}
}
else if (e.messageType === 3) {
var announce = {};
announce.channel = channel;
announce.subscription = subscriptionMatch;
announce.timetoken = publishMetaData.publishTimetoken;
announce.publisher = e.issuingClientId;
announce.data = {
messageTimetoken: e.payload.data.messageTimetoken,
actionTimetoken: e.payload.data.actionTimetoken,
type: e.payload.data.type,
uuid: e.issuingClientId,
value: e.payload.data.value,
};
announce.event = e.payload.event;
this.listenerManager.announceMessageAction(announce);
}
else if (e.messageType === 4) {
var announce = {};
announce.channel = channel;
announce.subscription = subscriptionMatch;
announce.timetoken = publishMetaData.publishTimetoken;
announce.publisher = e.issuingClientId;
var msgPayload = e.payload;
if (this.modules.cryptoModule) {
var decryptedPayload = void 0;
try {
var decryptedData = this.modules.cryptoModule.decrypt(e.payload);
decryptedPayload =
decryptedData instanceof ArrayBuffer ? JSON.parse(this._decoder.decode(decryptedData)) : decryptedData;
}
catch (e) {
decryptedPayload = null;
announce.error = "Error while decrypting message content: ".concat(e.message);
}
if (decryptedPayload !== null) {
msgPayload = decryptedPayload;
}
}
if (e.userMetadata) {
announce.userMetadata = e.userMetadata;
}
announce.message = msgPayload.message;
announce.file = {
id: msgPayload.file.id,
name: msgPayload.file.name,
url: this.getFileUrl({
id: msgPayload.file.id,
name: msgPayload.file.name,
channel: channel,
}),
};
this.listenerManager.announceFile(announce);
}
else {
var announce = {};
announce.channel = null;
announce.subscription = null;
announce.channel = channel;
announce.subscription = subscriptionMatch;
announce.timetoken = publishMetaData.publishTimetoken;
announce.publisher = e.issuingClientId;
if (e.userMetadata) {
announce.userMetadata = e.userMetadata;
}
if (this.modules.cryptoModule) {
var decryptedPayload = void 0;
try {
var decryptedData = this.modules.cryptoModule.decrypt(e.payload);
decryptedPayload =
decryptedData instanceof ArrayBuffer ? JSON.parse(this._decoder.decode(decryptedData)) : decryptedData;
}
catch (e) {
decryptedPayload = null;
announce.error = "Error while decrypting message content: ".concat(e.message);
}
if (decryptedPayload != null) {
announce.message = decryptedPayload;
}
else {
announce.message = e.payload;
}
}
else {
announce.message = e.payload;
}
this.listenerManager.announceMessage(announce);
}
};
EventEmitter.prototype._renameEvent = function (e) {
return e === 'set' ? 'updated' : 'removed';
};
EventEmitter.prototype._renameChannelField = function (announce) {
var channel = announce.channel, eventData = __rest(announce, ["channel"]);
eventData.spaceId = channel;
return eventData;
};
return EventEmitter;
}());
exports.default = EventEmitter;
7 changes: 5 additions & 2 deletions lib/core/components/listener_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ var default_1 = /** @class */ (function () {
function default_1() {
this._listeners = [];
}
default_1.prototype.addListener = function (newListeners) {
this._listeners.push(newListeners);
default_1.prototype.addListener = function (newListener) {
if (this._listeners.includes(newListener)) {
return;
}
this._listeners.push(newListener);
};
default_1.prototype.removeListener = function (deprecatedListener) {
var newListeners = [];
Expand Down
2 changes: 2 additions & 0 deletions lib/core/components/push_payload.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"use strict";
/* */
/* eslint max-classes-per-file: ["error", 5] */
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
Expand Down
3 changes: 3 additions & 0 deletions lib/core/constants/categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ exports.default = {
PNReconnectedCategory: 'PNReconnectedCategory',
PNConnectedCategory: 'PNConnectedCategory',
PNRequestMessageCountExceededCategory: 'PNRequestMessageCountExceededCategory',
PNDisconnectedCategory: 'PNDisconnectedCategory',
PNConnectionErrorCategory: 'PNConnectionErrorCategory',
PNDisconnectedUnexpectedlyCategory: 'PNDisconnectedUnexpectedlyCategory',
};
Loading

0 comments on commit f0bd4e5

Please sign in to comment.