* chore: upgrade local build documentation

* style: keep scrolling event in screen

* feat: delay is time entry

* refactor: remove unused

* refactor: remove unused

* refactor: batch store updates

* refactor: virtually remove cap on events

* refactor: style and behaviour tweaks to event block

* style: tweaks on schedules

* chore: remove sentry from server

* style: reorder menu

* chore: update docs
This commit is contained in:
Carlos Valente
2023-04-14 10:13:46 +02:00
committed by GitHub
parent 94a1369d64
commit 770d12888d
48 changed files with 531 additions and 376 deletions
+2 -7
View File
@@ -6,7 +6,6 @@ import cors from 'cors';
// import utils
import { join, resolve } from 'path';
import { initSentry, reportSentryException } from './modules/sentry.js';
import { currentDirectory, environment, externalsStartDirectory, isProduction, resolvedPath } from './setup.js';
import { ONTIME_VERSION } from './ONTIME_VERSION.js';
import { OSCSettings } from 'ontime-types';
@@ -39,8 +38,6 @@ if (!isProduction) {
console.log(`Ontime directory at ${currentDirectory} `);
}
initSentry(isProduction);
// Create express APP
const app = express();
app.disable('x-powered-by');
@@ -209,14 +206,12 @@ export const shutdown = async (exitCode = 0) => {
process.on('exit', (code) => console.log(`Ontime exited with code: ${code}`));
process.on('unhandledRejection', async (error) => {
reportSentryException(error);
process.on('unhandledRejection', async () => {
logger.error('SERVER', 'Error: unhandled rejection');
await shutdown(1);
});
process.on('uncaughtException', async (error) => {
reportSentryException(error);
process.on('uncaughtException', async () => {
logger.error('SERVER', 'Error: uncaught exception');
await shutdown(1);
});
@@ -260,9 +260,11 @@ export class EventLoader {
* Handle side effects from event loading
*/
private _loadEvent() {
eventStore.set('loaded', this.loaded);
eventStore.set('titles', this.titles);
eventStore.set('titlesPublic', this.titlesPublic);
eventStore.batchSet({
loaded: this.loaded,
titles: this.titles,
titlesPublic: this.titlesPublic,
});
}
/**
+2 -3
View File
@@ -7,7 +7,6 @@ import { ensureDirectory } from '../utils/fileManagement.js';
import { validateFile } from '../utils/parserUtils.js';
import { dbModel } from '../models/dataModel.js';
import { parseJson } from '../utils/parser.js';
import { reportSentryException } from './sentry.js';
import { pathToStartDb, resolveDbDirectory, resolveDbPath } from '../setup.js';
/**
@@ -22,8 +21,8 @@ const populateDb = () => {
if (!existsSync(dbInDisk)) {
try {
copyFileSync(pathToStartDb, dbInDisk);
} catch (error) {
reportSentryException(error);
} catch (_) {
/* we do not handle this */
}
}
+2 -3
View File
@@ -1,7 +1,6 @@
import { copyFileSync, existsSync } from 'fs';
import { pathToStartStyles, resolveStylesDirectory, resolveStylesPath } from '../setup.js';
import { ensureDirectory } from '../utils/fileManagement.js';
import { reportSentryException } from './sentry.js';
/**
* @description ensures directories exist and populates stylesheet
@@ -15,8 +14,8 @@ export const populateStyles = () => {
if (!existsSync(stylesInDisk)) {
try {
copyFileSync(pathToStartStyles, stylesInDisk);
} catch (error) {
reportSentryException(error);
} catch (_) {
/* we do not handle this */
}
}
-19
View File
@@ -1,19 +0,0 @@
import * as Sentry from '@sentry/node';
let shouldReport;
export function initSentry(doReport) {
shouldReport = doReport;
Sentry.init({
dsn: 'https://ceb6abdce7374857bb50b65636cbaed1@o4504288369836032.ingest.sentry.io/4504288555565056',
tracesSampleRate: 1.0,
});
}
export function reportSentryException(e) {
if (shouldReport) {
Sentry.captureException(e);
} else {
console.error(e);
}
}
+21 -14
View File
@@ -1,7 +1,17 @@
import { OntimeBaseEvent, OntimeBlock, OntimeDelay, OntimeEvent, SupportedEvent } from 'ontime-types';
import {
OntimeBaseEvent,
OntimeBlock,
OntimeDelay,
OntimeEvent,
SupportedEvent,
} from 'ontime-types';
import { generateId } from 'ontime-utils';
import { DataProvider } from '../classes/data-provider/DataProvider.js';
import { block as blockDef, delay as delayDef, event as eventDef } from '../models/eventsDefinition.js';
import {
block as blockDef,
delay as delayDef,
event as eventDef,
} from '../models/eventsDefinition.js';
import { MAX_EVENTS } from '../settings.js';
import { EventLoader, eventLoader } from '../classes/event-loader/EventLoader.js';
import { eventTimer } from './TimerService.js';
@@ -216,30 +226,27 @@ export async function reorderEvent(eventId, from, to) {
* @param eventId
* @returns {Promise<void>}
*/
export async function applyDelay(eventId) {
export async function applyDelay(eventId: string) {
const rundown = DataProvider.getRundown();
let delayIndex = null;
let delayValue = 0;
for (const [index, e] of rundown.entries()) {
for (const [index, event] of rundown.entries()) {
// look for delay
if (delayIndex === null) {
if (e.id === eventId && e.type === SupportedEvent.Delay) {
delayValue = e.duration;
if (event.id === eventId && event.type === SupportedEvent.Delay) {
delayValue = event.duration;
delayIndex = index;
}
}
// apply delay value to all items until block or end
else {
if (e.type === SupportedEvent.Event) {
// update times
e.timeStart += delayValue;
e.timeEnd += delayValue;
// increment revision
e.revision += 1;
} else if (e.type === SupportedEvent.Block) {
if (event.type === SupportedEvent.Event) {
event.timeStart = Math.max(0, event.timeStart + delayValue);
event.timeEnd = Math.max(event.duration, event.timeStart + delayValue);
event.revision += 1;
} else if (event.type === SupportedEvent.Block) {
break;
}
}
+16 -8
View File
@@ -141,8 +141,10 @@ export class TimerService {
* @private
*/
_onLoad() {
eventStore.set('playback', this.playback);
eventStore.set('timer', this.timer);
eventStore.batchSet({
playback: this.playback,
timer: this.timer,
});
integrationService.dispatch(TimerLifeCycle.onLoad);
}
@@ -182,8 +184,10 @@ export class TimerService {
* @private
*/
_onStart() {
eventStore.set('playback', this.playback);
eventStore.set('timer', this.timer);
eventStore.batchSet({
playback: this.playback,
timer: this.timer,
});
integrationService.dispatch(TimerLifeCycle.onStart);
}
@@ -199,8 +203,10 @@ export class TimerService {
}
_onPause() {
eventStore.set('playback', this.playback);
eventStore.set('timer', this.timer);
eventStore.batchSet({
playback: this.playback,
timer: this.timer,
});
integrationService.dispatch(TimerLifeCycle.onPause);
}
@@ -214,8 +220,10 @@ export class TimerService {
}
_onStop() {
eventStore.set('playback', this.playback);
eventStore.set('timer', this.timer);
eventStore.batchSet({
playback: this.playback,
timer: this.timer,
});
integrationService.dispatch(TimerLifeCycle.onStop);
}
-1
View File
@@ -1 +0,0 @@
export const MAX_EVENTS = 255;
+1
View File
@@ -0,0 +1 @@
export const MAX_EVENTS = 32768;
+10
View File
@@ -8,6 +8,10 @@ let store: Partial<RuntimeStore> = {};
/**
* A runtime store that broadcasts its payload
* - init: allows for adding an initial payload to the store
* - batchSet: allows setting several keys with a single broadcast
* - poll: utility to return state
* - broadcast: send its payload as json object
*/
export const eventStore = {
init(payload: RuntimeStore) {
@@ -25,6 +29,12 @@ export const eventStore = {
// });
this.broadcast();
},
batchSet<K extends keyof RuntimeStore>(values: Record<K, RuntimeStore[K]>) {
Object.entries(values).forEach(([key, value]) => {
store[key] = value;
});
this.broadcast();
},
poll() {
return store;
},