Skip to content

Commit

Permalink
Add randomized timing for polling to keep multiple instances of the s…
Browse files Browse the repository at this point in the history
…oftware from polling the same servers at the same time. Fix tests broken by recent major npm package updates.
  • Loading branch information
kshetline committed Jan 17, 2020
1 parent 233ac74 commit 5563ac0
Show file tree
Hide file tree
Showing 11 changed files with 42 additions and 40 deletions.
2 changes: 1 addition & 1 deletion e2e/tsconfig.e2e.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"outDir": "../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
"target": "es6",
"types": [
"jasmine",
"jasminewd2",
Expand Down
12 changes: 1 addition & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aw-clock",
"version": "1.2.4",
"version": "1.2.5",
"license": "MIT",
"author": "Kerry Shetline <kerry@shetline.com>",
"scripts": {
Expand Down Expand Up @@ -58,7 +58,6 @@
"karma-webpack": "^4.0.2",
"less-loader": "^5.0.0",
"node-sass": "^4.13.1",
"null-loader": "^3.0.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
"postcss-url": "^8.0.0",
Expand Down
2 changes: 1 addition & 1 deletion protractor.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ exports.config = {
let resolved = false;
let rejected = false;

webpackServerProcess = spawn('webpack-dev-server', ['--port=4200']);
webpackServerProcess = spawn('webpack-dev-server', ['--mode=development', '--port=4200']);
webpackServerProcess.stdout.pipe(process.stdout);

webpackServerProcess.stdout.addListener('data', chunk => {
Expand Down
2 changes: 1 addition & 1 deletion server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aw-clock-server",
"version": "1.2.4",
"version": "1.2.5",
"license": "MIT",
"author": "Kerry Shetline <kerry@shetline.com>",
"private": true,
Expand Down
9 changes: 9 additions & 0 deletions server/src/tai-utc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const DEFAULT_LEAP_SECOND_URLS = DEFAULT_LEAP_SECOND_HTTPS_URL + ';' + DE
const NTP_BASE = 2208988800; // Seconds before 1970-01-01 epoch for 1900-01-01 epoch
const MILLIS_PER_DAY = 86400000;
const DAYS_BETWEEN_POLLS = 7;
const MAX_RANDOM_LEAP_SECOND_POLL_DELAY = 120000; // Two minutes
const TIMEOUT = 5000;
const TIME_AND_DELTA = /^(\d{10,})\s+(\d{2,4})\s*#\s*1\s+[A-Za-z]{3}\s+\d{4}/;

Expand All @@ -30,6 +31,7 @@ function makeError(err: any): Error {
}

export class TaiUtc {
private firstLeapSecondPoll = true;
private lastPollDay = 0;
private lastPollMonth = -1;
private leapSeconds: LeapSecond[] = [];
Expand Down Expand Up @@ -86,6 +88,13 @@ export class TaiUtc {
if (this.leapSeconds.length > 1 && this.lastPollDay < day + DAYS_BETWEEN_POLLS && this.lastPollMonth === month)
return;

await new Promise<void>(resolve => {
// Randomly delay polling so that multiple TaiUtc instances don't all poll at the same time every day.
const delay = (this.firstLeapSecondPoll ? 0 : Math.floor(Math.random() * MAX_RANDOM_LEAP_SECOND_POLL_DELAY));
this.firstLeapSecondPoll = false;
setTimeout(() => resolve(), delay);
});

const promises: Promise<string | Error>[] = [];

this.urls.forEach(url => {
Expand Down
6 changes: 2 additions & 4 deletions spec.bundle.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
const testsContext = require.context('./', true, /\.spec\.ts$/);
testsContext.keys().forEach(key => {
if (key.indexOf('/server/') < 0) { testsContext(key); }
});
const context = require.context('./src/', true, /\.spec\.ts$/);
context.keys().forEach(context);
27 changes: 17 additions & 10 deletions src/clock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import * as $ from 'jquery';
const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';

const SECOND_HAND_ANIMATION_TIME = 200;
const MAX_RANDOM_LEAP_SECOND_POLL_DELAY = 120000; // Two minutes
const LEAP_SECOND_RETRY_DELAY = 300000; // 5 minutes

const MILLIS_PER_DAY = 86400000;
Expand Down Expand Up @@ -63,6 +64,7 @@ export class Clock {
private lastTick = -1;
private inMinuteOfLeapSecond = false;
private pendingLeapSecondForMonth = 0;
private firstLeapSecondPoll = true;
private lastLeapSecondCheckDay = -1;
private upcomingLeapSecond: CurrentDelta;

Expand Down Expand Up @@ -349,15 +351,20 @@ export class Clock {
}

private getLeapSecondInfo(): void {
// noinspection JSIgnoredPromiseFromCall
$.ajax({
url: this.appService.getWeatherServer() + '/tai-utc',
dataType: 'json',
success: (data: CurrentDelta) => this.upcomingLeapSecond = data,
error: () => setTimeout(() => {
this.upcomingLeapSecond = undefined;
this.lastLeapSecondCheckDay = -1;
}, LEAP_SECOND_RETRY_DELAY)
});
setTimeout(() => {
this.firstLeapSecondPoll = false;

// noinspection JSIgnoredPromiseFromCall
$.ajax({
url: this.appService.getWeatherServer() + '/tai-utc',
dataType: 'json',
success: (data: CurrentDelta) => this.upcomingLeapSecond = data,
error: () => setTimeout(() => {
this.upcomingLeapSecond = undefined;
this.lastLeapSecondCheckDay = -1;
}, LEAP_SECOND_RETRY_DELAY)
});
// Randomly delay polling so that multiple clock instances don't all poll at the same time every day.
}, this.firstLeapSecondPoll ? 0 : Math.floor(Math.random() * MAX_RANDOM_LEAP_SECOND_POLL_DELAY));
}
}
2 changes: 1 addition & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
</div>
</div>
<div class="dialog-buttons">
<span class="version-number">1.2.4</span>
<span class="version-number">1.2.5</span>
<button id="settings-reload">Reload</button>
<span>&bull;</span>
<button id="settings-cancel">Cancel</button>
Expand Down
15 changes: 7 additions & 8 deletions webpack-test.config.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
const path = require('path');
const ROOT = path.resolve(__dirname, 'src');
const SERVER = path.resolve(__dirname, 'server');
const NODE_ENV = process.env.NODE_ENV || 'development';

module.exports = {
mode: NODE_ENV,
context: ROOT,

resolve: {
extensions: ['.ts', '.js'],
modules: [
ROOT,
'node_modules',
'server/node_modules'
'node_modules'
]
},

Expand All @@ -19,23 +21,20 @@ module.exports = {
{
enforce: 'pre',
test: /\.js$/,
exclude: [SERVER],
use: 'source-map-loader'
},

// LOADERS
{
test: s => s.endsWith('.ts') && !s.endsWith('/ntp.ts'),
exclude: [/node_modules/],
test: /\.ts$/,
exclude: [/node_modules/, SERVER],
use: {
loader: 'ts-loader',
options: {
transpileOnly: true
}
}
},
{
test: /\/ntp\.ts$/,
use: 'null-loader'
}
]
},
Expand Down

0 comments on commit 5563ac0

Please sign in to comment.