sync/src/channel-storage/dbstore.js

89 lines
2.7 KiB
JavaScript
Raw Normal View History

2015-09-26 14:21:42 -07:00
import Promise from 'bluebird';
import { ChannelStateSizeError,
2015-09-26 15:33:13 -07:00
ChannelNotFoundError } from '../errors';
2015-09-26 14:21:42 -07:00
import db from '../database';
import Logger from '../logger';
const SIZE_LIMIT = 1048576;
const QUERY_CHANNEL_ID_FOR_NAME = 'SELECT id FROM channels WHERE name = ?';
const QUERY_CHANNEL_DATA = 'SELECT `key`, `value` FROM channel_data WHERE channel_id = ?';
function queryAsync(query, substitutions) {
return new Promise((resolve, reject) => {
db.query(query, substitutions, (err, res) => {
if (err) {
if (!(err instanceof Error)) {
err = new Error(err);
}
reject(err);
} else {
resolve(res);
}
});
});
}
2015-09-26 15:33:13 -07:00
function buildUpdateQuery(numEntries) {
const values = [];
for (let i = 0; i < numEntries; i++) {
values.push('(?, ?, ?)');
}
return `INSERT INTO channel_data VALUES ${values.join(', ')} ` +
'ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)';
}
2015-09-26 14:21:42 -07:00
export class DatabaseStore {
load(id, channelName) {
if (!id || id === 0) {
return Promise.reject(new Error(`Cannot load state for [${channelName}]: ` +
`id was passed as [${id}]`));
}
2015-09-26 14:21:42 -07:00
return queryAsync(QUERY_CHANNEL_DATA, [id]).then(rows => {
2015-09-26 14:21:42 -07:00
const data = {};
2015-10-01 22:02:59 -07:00
rows.forEach(row => {
2015-09-26 14:21:42 -07:00
try {
data[row.key] = JSON.parse(row.value);
} catch (e) {
Logger.errlog.log(`Channel data for channel "${channelName}", ` +
`key "${row.key}" is invalid: ${e}`);
}
2015-10-01 22:02:59 -07:00
});
2015-09-26 14:21:42 -07:00
return data;
});
}
save(id, channelName, data) {
if (!id || id === 0) {
return Promise.reject(new Error(`Cannot save state for [${channelName}]: ` +
`id was passed as [${id}]`));
}
2015-09-26 14:21:42 -07:00
let totalSize = 0;
let rowCount = 0;
const substitutions = [];
for (const key in data) {
if (typeof data[key] === 'undefined') {
continue;
2015-09-26 14:21:42 -07:00
}
rowCount++;
const value = JSON.stringify(data[key]);
totalSize += value.length;
substitutions.push(id);
substitutions.push(key);
substitutions.push(value);
}
2015-09-26 14:21:42 -07:00
if (totalSize > SIZE_LIMIT) {
throw new ChannelStateSizeError('Channel state size is too large', {
limit: SIZE_LIMIT,
actual: totalSize
});
}
2015-09-26 14:21:42 -07:00
return queryAsync(buildUpdateQuery(rowCount), substitutions);
2015-09-26 14:21:42 -07:00
}
}