Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

launchdarkly-js-sdk-common

Package Overview
Dependencies
Maintainers
1
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

launchdarkly-js-sdk-common - npm Package Compare versions

Comparing version 4.3.1 to 4.3.2

4

CHANGELOG.md

@@ -5,2 +5,6 @@ # Change log

## [4.3.1] - 2022-10-17
### Fixed:
- Fixed an issue that prevented the `flag-used` inspector from being called.
## [4.3.0] - 2022-10-17

@@ -7,0 +11,0 @@ ### Added:

2

package.json
{
"name": "launchdarkly-js-sdk-common",
"version": "4.3.1",
"version": "4.3.2",
"description": "LaunchDarkly SDK for JavaScript - common code",

@@ -5,0 +5,0 @@ "author": "LaunchDarkly <team@launchdarkly.com>",

@@ -173,2 +173,3 @@ import { DiagnosticsAccumulator } from '../diagnosticEvents';

es.mockError('test error');
await sleepAsync(10);
const created1 = await platform.testing.expectStream();

@@ -189,2 +190,36 @@ const es1 = created1.eventSource;

it.each([401, 403])('does not reconnect after an unrecoverable error', async status => {
const config = { ...defaultConfig, streamReconnectDelay: 1, useReport: false };
const stream = new Stream(platform, config, envName);
stream.connect(user);
const created = await platform.testing.expectStream();
const es = created.eventSource;
expect(es.readyState).toBe(EventSource.CONNECTING);
es.mockOpen();
expect(es.readyState).toBe(EventSource.OPEN);
es.mockError({ status });
await sleepAsync(10);
expect(platform.testing.eventSourcesCreated.length()).toEqual(0);
});
it.each([400, 408, 429])('does reconnect after a recoverable error', async status => {
const config = { ...defaultConfig, streamReconnectDelay: 1, useReport: false };
const stream = new Stream(platform, config, envName);
stream.connect(user);
const created = await platform.testing.expectStream();
const es = created.eventSource;
expect(es.readyState).toBe(EventSource.CONNECTING);
es.mockOpen();
expect(es.readyState).toBe(EventSource.OPEN);
es.mockError({ status });
await sleepAsync(10);
expect(platform.testing.eventSourcesCreated.length()).toEqual(1);
});
it('logs a warning for only the first failed connection attempt', async () => {

@@ -202,2 +237,3 @@ const config = { ...defaultConfig, streamReconnectDelay: 1 };

es.mockError('test error');
await sleepAsync(10);
const created1 = await platform.testing.expectStream();

@@ -227,2 +263,3 @@ es = created1.eventSource;

es.mockError('test error #1');
await sleepAsync(10);
const created1 = await platform.testing.expectStream();

@@ -239,2 +276,3 @@ es = created1.eventSource;

es.mockError('test error #2');
await sleepAsync(10);
const created1 = await platform.testing.expectStream();

@@ -247,4 +285,4 @@ es = created1.eventSource;

expect(logger.output.warn).toEqual([
messages.streamError('test error #1', 1),
messages.streamError('test error #2', 1),
expect.stringContaining('test error #1'),
expect.stringContaining('test error #2'),
]);

@@ -251,0 +289,0 @@ });

@@ -20,5 +20,6 @@ const { getLDUserAgentString } = require('./utils');

.sort()
.flatMap(
.map(
key => (Array.isArray(tags[key]) ? tags[key].sort().map(value => `${key}/${value}`) : [`${key}/${tags[key]}`])
)
.reduce((flattened, item) => flattened.concat(item), [])
.join(' ');

@@ -25,0 +26,0 @@ }

@@ -126,3 +126,3 @@ const errors = require('./errors');

errorString(err) +
', will continue retrying every ' +
', will continue retrying after ' +
streamReconnectDelay +

@@ -135,2 +135,4 @@ ' milliseconds.'

const unrecoverableStreamError = err => `Error on stream connection ${errorString(err)}, giving up permanently`;
const wrongOptionType = (name, expectedType, actualType) =>

@@ -233,2 +235,3 @@ 'Config option "' + name + '" should be of type ' + expectedType + ', got ' + actualType + ', using default value';

unknownOption,
unrecoverableStreamError,
userNotSpecified,

@@ -235,0 +238,0 @@ wrongOptionType,

const messages = require('./messages');
const { appendUrlPath, base64URLEncode, objectHasOwnProperty } = require('./utils');
const { getLDHeaders, transformHeaders } = require('./headers');
const { isHttpErrorRecoverable } = require('./errors');

@@ -19,2 +20,4 @@ // The underlying event source implementation is abstracted via the platform object, which should

const streamReadTimeoutMillis = 5 * 60 * 1000; // 5 minutes
const maxRetryDelay = 30 * 1000; // Maximum retry delay 30 seconds.
const jitterRatio = 0.5; // Delay should be 50%-100% of calculated time.

@@ -28,3 +31,3 @@ function Stream(platform, config, environment, diagnosticsAccumulator) {

const withReasons = config.evaluationReasons;
const streamReconnectDelay = config.streamReconnectDelay;
const baseReconnectDelay = config.streamReconnectDelay;
const headers = getLDHeaders(platform, config);

@@ -38,3 +41,19 @@ let firstConnectionErrorLogged = false;

let handlers = null;
let retryCount = 0;
function backoff() {
const delay = baseReconnectDelay * Math.pow(2, retryCount);
return delay > maxRetryDelay ? maxRetryDelay : delay;
}
function jitter(computedDelayMillis) {
return computedDelayMillis - Math.trunc(Math.random() * jitterRatio * computedDelayMillis);
}
function getNextRetryDelay() {
const delay = jitter(backoff());
retryCount += 1;
return delay;
}
stream.connect = function(newUser, newHash, newHandlers) {

@@ -69,4 +88,22 @@ user = newUser;

function handleError(err) {
// The event source may not produce a status. But the LaunchDarkly
// polyfill can. If we can get the status, then we should stop retrying
// on certain error codes.
if (err.status && typeof err.status === 'number' && !isHttpErrorRecoverable(err.status)) {
// If we encounter an unrecoverable condition, then we do not want to
// retry anymore.
closeConnection();
logger.error(messages.unrecoverableStreamError(err));
// Ensure any pending retry attempts are not done.
if (reconnectTimeoutReference) {
clearTimeout(reconnectTimeoutReference);
reconnectTimeoutReference = null;
}
return;
}
const delay = getNextRetryDelay();
if (!firstConnectionErrorLogged) {
logger.warn(messages.streamError(err, streamReconnectDelay));
logger.warn(messages.streamError(err, delay));
firstConnectionErrorLogged = true;

@@ -76,3 +113,3 @@ }

closeConnection();
tryConnect(streamReconnectDelay);
tryConnect(delay);
}

@@ -131,2 +168,7 @@

es.onerror = handleError;
es.onopen = () => {
// If the connection is a success, then reset the retryCount.
retryCount = 0;
};
}

@@ -133,0 +175,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc