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

Nightscout 14.0.5 Liquorice #6135

Merged
merged 13 commits into from
Sep 27, 2020
Merged
49 changes: 18 additions & 31 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,25 @@ function create (env, ctx) {
));
});

// Allow static resources to be cached for week
var maxAge = 7 * 24 * 60 * 60 * 1000;

if (process.env.NODE_ENV === 'development') {
maxAge = 1;
console.log('Development environment detected, setting static file cache age to 1 second');
}

var staticFiles = express.static(env.static_files, {
maxAge
});

// serve the static content
app.use(staticFiles);

if (ctx.bootErrors && ctx.bootErrors.length > 0) {
app.get('*', require('./lib/server/booterror')(ctx));
const bootErrorView = require('./lib/server/booterror')(env, ctx);
bootErrorView.setLocals(app.locals);
app.get('*', bootErrorView);
return app;
}

Expand Down Expand Up @@ -256,36 +273,6 @@ function create (env, ctx) {
res.sendFile(__dirname + '/swagger.yaml');
});

/* // FOR DEBUGGING MEMORY LEEAKS
if (env.settings.isEnabled('dumps')) {
var heapdump = require('heapdump');
app.get('/api/v2/dumps/start', function(req, res) {
var path = new Date().toISOString() + '.heapsnapshot';
path = path.replace(/:/g, '-');
console.info('writing dump to', path);
heapdump.writeSnapshot(path);
res.send('wrote dump to ' + path);
});
}
*/

// app.get('/package.json', software);

// Allow static resources to be cached for week
var maxAge = 7 * 24 * 60 * 60 * 1000;

if (process.env.NODE_ENV === 'development') {
maxAge = 1;
console.log('Development environment detected, setting static file cache age to 1 second');
}

var staticFiles = express.static(env.static_files, {
maxAge
});

// serve the static content
app.use(staticFiles);

// API docs

const swaggerUi = require('swagger-ui-express');
Expand Down
23 changes: 17 additions & 6 deletions env.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,20 @@ var env = {
settings: require('./lib/settings')()
};

var shadowEnv;

// Module to constrain all config and environment parsing to one spot.
// See README.md for info about all the supported ENV VARs
function config ( ) {

// Assume users will typo whitespaces into keys and values

shadowEnv = {};

Object.keys(process.env).forEach((key, index) => {
shadowEnv[_trim(key)] = _trim(process.env[key]);
});

env.PORT = readENV('PORT', 1337);
env.HOSTNAME = readENV('HOSTNAME', null);
env.IMPORT_CONFIG = readENV('IMPORT_CONFIG', null);
Expand Down Expand Up @@ -122,7 +133,7 @@ function updateSettings() {
});

//should always find extended settings last
env.extendedSettings = findExtendedSettings(process.env);
env.extendedSettings = findExtendedSettings(shadowEnv);

if (!readENVTruthy('TREATMENTS_AUTH', true)) {
env.settings.authDefaultRoles = env.settings.authDefaultRoles || "";
Expand All @@ -132,10 +143,10 @@ function updateSettings() {

function readENV(varName, defaultValue) {
//for some reason Azure uses this prefix, maybe there is a good reason
var value = process.env['CUSTOMCONNSTR_' + varName]
|| process.env['CUSTOMCONNSTR_' + varName.toLowerCase()]
|| process.env[varName]
|| process.env[varName.toLowerCase()];
var value = shadowEnv['CUSTOMCONNSTR_' + varName]
|| shadowEnv['CUSTOMCONNSTR_' + varName.toLowerCase()]
|| shadowEnv[varName]
|| shadowEnv[varName.toLowerCase()];

if (varName == 'DISPLAY_UNITS') {
if (value && value.toLowerCase().includes('mmol')) {
Expand All @@ -162,7 +173,7 @@ function findExtendedSettings (envs) {
extended.devicestatus = {};
extended.devicestatus.advanced = true;
extended.devicestatus.days = 1;
if(process.env['DEVICESTATUS_DAYS'] && process.env['DEVICESTATUS_DAYS'] == '2') extended.devicestatus.days = 1;
if(shadowEnv['DEVICESTATUS_DAYS'] && shadowEnv['DEVICESTATUS_DAYS'] == '2') extended.devicestatus.days = 1;

function normalizeEnv (key) {
return key.toUpperCase().replace('CUSTOMCONNSTR_', '');
Expand Down
36 changes: 14 additions & 22 deletions lib/data/dataloader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const _ = require('lodash');
const async = require('async');
const times = require('../times');
const fitTreatmentsToBGCurve = require('./treatmenttocurve');
const constants = require('../constants');

Expand Down Expand Up @@ -144,8 +143,11 @@ function init(env, ctx) {
done(err, result);
}

// clear treatments to the base set, we're going to merge from multiple queries
ddata.treatments = []; // ctx.cache.treatments ? _.cloneDeep(ctx.cache.treatments) : [];
// clear data we'll get from the cache

ddata.treatments = [];
ddata.devicestatus = [];
ddata.entries = [];

ddata.dbstats = {};

Expand Down Expand Up @@ -196,11 +198,8 @@ function loadEntries(ddata, ctx, callback) {

if (!err && results) {

const ageFilter = ddata.lastUpdated - constants.TWO_DAYS;
const r = ctx.ddata.processRawDataForRuntime(results);
ctx.cache.insertData('entries', r, ageFilter);

const currentData = ctx.cache.getData('entries').reverse();
const currentData = ctx.cache.insertData('entries', r).reverse();

const mbgs = [];
const sgvs = [];
Expand Down Expand Up @@ -324,12 +323,11 @@ function loadTreatments(ddata, ctx, callback) {

ctx.treatments.list(tq, function(err, results) {
if (!err && results) {
const ageFilter = ddata.lastUpdated - longLoad;
const r = ctx.ddata.processRawDataForRuntime(results);

// update cache
ctx.cache.insertData('treatments', r, ageFilter);
ddata.treatments = ctx.ddata.idMergePreferNew(ddata.treatments, ctx.cache.getData('treatments'));
// update cache and apply to runtime data
const r = ctx.ddata.processRawDataForRuntime(results);
const currentData = ctx.cache.insertData('treatments', r);
ddata.treatments = ctx.ddata.idMergePreferNew(ddata.treatments, currentData);
}

callback();
Expand Down Expand Up @@ -361,7 +359,6 @@ function loadProfileSwitchTreatments(ddata, ctx, callback) {
ctx.treatments.list(tq, function(err, results) {
if (!err && results) {
ddata.treatments = mergeProcessSort(ddata.treatments, results);
//mergeToTreatments(ddata, results);
}

// Store last profile switch
Expand Down Expand Up @@ -418,7 +415,6 @@ function loadLatestSingle(ddata, ctx, dataType, callback) {
ctx.treatments.list(tq, function(err, results) {
if (!err && results) {
ddata.treatments = mergeProcessSort(ddata.treatments, results);
//mergeToTreatments(ddata, results);
}
callback();
});
Expand Down Expand Up @@ -473,16 +469,12 @@ function loadDeviceStatus(ddata, env, ctx, callback) {

ctx.devicestatus.list(opts, function(err, results) {
if (!err && results) {
// ctx.cache.devicestatus = mergeProcessSort(ctx.cache.devicestatus, results, ageFilter);

const ageFilter = ddata.lastUpdated - longLoad;
// update cache and apply to runtime data
const r = ctx.ddata.processRawDataForRuntime(results);
ctx.cache.insertData('devicestatus', r, ageFilter);

const res = ctx.cache.getData('devicestatus');
const currentData = ctx.cache.insertData('devicestatus', r);

const res2 = _.map(res, function eachStatus(result) {
//result.mills = new Date(result.created_at).getTime();
const res2 = _.map(currentData, function eachStatus(result) {
if ('uploaderBattery' in result) {
result.uploader = {
battery: result.uploaderBattery
Expand All @@ -492,7 +484,7 @@ function loadDeviceStatus(ddata, env, ctx, callback) {
return result;
});

ddata.devicestatus = mergeProcessSort(ddata.devicestatus, res2, ageFilter);
ddata.devicestatus = mergeProcessSort(ddata.devicestatus, res2);
} else {
ddata.devicestatus = [];
}
Expand Down
8 changes: 5 additions & 3 deletions lib/data/ddata.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ function init () {

Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'object' && obj[key]) {
if (obj[key].hasOwnProperty('_id')) {
if (Object.prototype.hasOwnProperty.call(obj[key], '_id')) {
obj[key]._id = obj[key]._id.toString();
}
if (obj[key].hasOwnProperty('created_at') && !obj[key].hasOwnProperty('mills')) {
if (Object.prototype.hasOwnProperty.call(obj[key], 'created_at')
&& !Object.prototype.hasOwnProperty.call(obj[key], 'mills')) {
obj[key].mills = new Date(obj[key].created_at).getTime();
}
if (obj[key].hasOwnProperty('sysTime') && !obj[key].hasOwnProperty('mills')) {
if (Object.prototype.hasOwnProperty.call(obj[key], 'sysTime')
&& !Object.prototype.hasOwnProperty.call(obj[key], 'mills')) {
obj[key].mills = new Date(obj[key].sysTime).getTime();
}
}
Expand Down
3 changes: 3 additions & 0 deletions lib/profilefunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ function init (profileData) {
// preprocess the timestamps to seconds for a couple orders of magnitude faster operation
profile.preprocessProfileOnLoad = function preprocessProfileOnLoad (container) {
_.each(container, function eachValue (value) {

if (value === null) return;

if (Object.prototype.toString.call(value) === '[object Array]') {
profile.preprocessProfileOnLoad(value);
}
Expand Down
40 changes: 32 additions & 8 deletions lib/server/booterror.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
'use strict';

const express = require('express');
const path = require('path');
var _ = require('lodash');

var head = '<!DOCTYPE html><html><head><title>Nightscout - Boot Error</title></head><body><h1>Nightscout - Boot Error</h1><dl>';
var tail = '</dl></body></html>';
function bootError(env, ctx) {

function bootError(ctx) {
const app = new express();
let locals = {};

app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.set("views", path.join(__dirname, "../../views/"));

app.get('*', (req, res, next) => {

if (req.url.includes('images')) return next();

return function pageHandler (req, res) {
var errors = _.map(ctx.bootErrors, function (obj) {
obj.err = _.pick(obj.err, Object.getOwnPropertyNames(obj.err));
return '<dt>' + obj.desc + '</dt><dd>' + JSON.stringify(obj.err).replace(/\\n/g, '<br/>') + '</dd>';

let message;

if (typeof obj.err === 'string' || obj.err instanceof String) {
message = obj.err;
} else {
message = JSON.stringify(_.pick(obj.err, Object.getOwnPropertyNames(obj.err)));
}
return '<dt>' + obj.desc + '</dt><dd>' + message.replace(/\\n/g, '<br/>') + '</dd>';
}).join(' ');

res.set('Content-Type', 'text/html');
res.send(head + errors + tail);
res.render('error.html', {
errors,
locals
});

});

app.setLocals = function (_locals) {
locals = _locals;
}

return app;
}

module.exports = bootError;
31 changes: 27 additions & 4 deletions lib/server/bootevent.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,25 @@ function boot (env, language) {
}
}

function checkSettings (ctx, next) {

ctx.bootErrors = ctx.bootErrors || [];

console.log('Checking settings');

if (!env.storageURI) {
ctx.bootErrors.push({'desc': 'Mandatory setting missing',
err: 'MONGODB_URI setting is missing, cannot connect to database'});
}

if (!env.api_secret) {
ctx.bootErrors.push({'desc': 'Mandatory setting missing',
err: 'API_SECRET setting is missing, cannot enable REST API'});
}

next();
}

function setupStorage (ctx, next) {

if (hasBootErrors(ctx)) {
Expand All @@ -107,7 +126,6 @@ function boot (env, language) {
if (err) {
throw err;
}

ctx.store = store;
console.log('OpenAPS Storage system ready');
next();
Expand All @@ -116,14 +134,18 @@ function boot (env, language) {
//TODO assume mongo for now, when there are more storage options add a lookup
require('../storage/mongo-storage')(env, function ready(err, store) {
// FIXME, error is always null, if there is an error, the index.js will throw an exception
if (err) {
console.info('ERROR CONNECTING TO MONGO', err);
ctx.bootErrors = ctx.bootErrors || [ ];
ctx.bootErrors.push({'desc': 'Unable to connect to Mongo', err: err});
}
console.log('Mongo Storage system ready');
ctx.store = store;

next();
});
}
} catch (err) {
console.info('mongo err', err);
console.info('ERROR CONNECTING TO MONGO', err);
ctx.bootErrors = ctx.bootErrors || [ ];
ctx.bootErrors.push({'desc': 'Unable to connect to Mongo', err: err});
next();
Expand Down Expand Up @@ -233,7 +255,7 @@ function boot (env, language) {
});

ctx.bus.on('data-loaded', function updatePlugins ( ) {
console.info('reloading sandbox data');
// console.info('reloading sandbox data');
var sbx = require('../sandbox')().serverInit(env, ctx);
ctx.plugins.setProperties(sbx);
ctx.notifications.initRequests();
Expand Down Expand Up @@ -285,6 +307,7 @@ function boot (env, language) {
.acquire(checkNodeVersion)
.acquire(checkEnv)
.acquire(augmentSettings)
.acquire(checkSettings)
.acquire(setupStorage)
.acquire(setupAuthorization)
.acquire(setupInternals)
Expand Down
Loading