ImportEtherpad: Use a real ueberdb object for the temp Pad

Now plugin authors have access to the full set of DB operations.
This commit is contained in:
Richard Hansen 2022-04-19 16:23:56 -04:00
parent 6a183db850
commit 10117bc988
1 changed files with 48 additions and 54 deletions

View File

@ -24,6 +24,7 @@ const db = require('../db/DB');
const hooks = require('../../static/js/pluginfw/hooks'); const hooks = require('../../static/js/pluginfw/hooks');
const log4js = require('log4js'); const log4js = require('log4js');
const supportedElems = require('../../static/js/contentcollector').supportedElems; const supportedElems = require('../../static/js/contentcollector').supportedElems;
const ueberdb = require('ueberdb2');
const logger = log4js.getLogger('ImportEtherpad'); const logger = log4js.getLogger('ImportEtherpad');
@ -55,66 +56,59 @@ exports.setPadRaw = async (padId, r, authorId = '') => {
// First validate and transform values. Do not commit any records to the database yet in case // First validate and transform values. Do not commit any records to the database yet in case
// there is a problem with the data. // there is a problem with the data.
const dbRecords = new Map(); const data = new Map();
const existingAuthors = new Set(); const existingAuthors = new Set();
await Promise.all(Object.entries(records).map(([key, value]) => q.pushAsync(async () => { const padDb = new ueberdb.Database('memory', {data});
if (!value) { await padDb.init();
return; try {
} await Promise.all(Object.entries(records).map(([key, value]) => q.pushAsync(async () => {
const keyParts = key.split(':'); if (!value) return;
const [prefix, id] = keyParts; const keyParts = key.split(':');
if (prefix === 'globalAuthor' && keyParts.length === 2) { const [prefix, id] = keyParts;
// In the database, the padIDs subkey is an object (which is used as a set) that records every if (prefix === 'globalAuthor' && keyParts.length === 2) {
// pad the author has worked on. When exported, that object becomes a single string containing // In the database, the padIDs subkey is an object (which is used as a set) that records
// the exported pad's ID. // every pad the author has worked on. When exported, that object becomes a single string
if (typeof value.padIDs !== 'string') { // containing the exported pad's ID.
throw new TypeError('globalAuthor padIDs subkey is not a string'); if (typeof value.padIDs !== 'string') {
} throw new TypeError('globalAuthor padIDs subkey is not a string');
checkOriginalPadId(value.padIDs); }
if (await authorManager.doesAuthorExist(id)) { checkOriginalPadId(value.padIDs);
existingAuthors.add(id); if (await authorManager.doesAuthorExist(id)) {
existingAuthors.add(id);
return;
}
value.padIDs = {[padId]: 1};
} else if (padKeyPrefixes.includes(prefix)) {
checkOriginalPadId(id);
if (prefix === 'pad' && keyParts.length === 2) {
const pool = new AttributePool().fromJsonable(value.pool);
const unsupportedElements = new Set();
pool.eachAttrib((k, v) => {
if (!supportedElems.has(k)) unsupportedElements.add(k);
});
if (unsupportedElements.size) {
logger.warn(`(pad ${padId}) unsupported attributes (try installing a plugin): ` +
`${[...unsupportedElements].join(', ')}`);
}
}
keyParts[1] = padId;
key = keyParts.join(':');
} else {
logger.warn(`(pad ${padId}) Ignoring record with unsupported key: ${key}`);
return; return;
} }
value.padIDs = {[padId]: 1}; await padDb.set(key, value);
} else if (padKeyPrefixes.includes(prefix)) { })));
checkOriginalPadId(id);
if (prefix === 'pad' && keyParts.length === 2) {
const pool = new AttributePool().fromJsonable(value.pool);
const unsupportedElements = new Set();
pool.eachAttrib((k, v) => {
if (!supportedElems.has(k)) unsupportedElements.add(k);
});
if (unsupportedElements.size) {
logger.warn(`(pad ${padId}) unsupported attributes (try installing a plugin): ` +
`${[...unsupportedElements].join(', ')}`);
}
}
keyParts[1] = padId;
key = keyParts.join(':');
} else {
logger.warn(`(pad ${padId}) Ignoring record with unsupported key: ${key}`);
return;
}
dbRecords.set(key, value);
})));
const pad = new Pad(padId, { const pad = new Pad(padId, padDb);
// Only fetchers are needed to check the pad's integrity. await pad.init(null, authorId);
get: async (k) => dbRecords.get(k), await pad.check();
getSub: async (k, sub) => { } finally {
let v = dbRecords.get(k); await padDb.close();
for (const sk of sub) { }
if (v == null) return null;
v = v[sk];
}
return v;
},
});
await pad.init(null, authorId);
await pad.check();
await Promise.all([ await Promise.all([
...[...dbRecords].map(([k, v]) => q.pushAsync(() => db.set(k, v))), ...[...data].map(([k, v]) => q.pushAsync(() => db.set(k, v))),
...[...existingAuthors].map((a) => q.pushAsync(() => authorManager.addPad(a, padId))), ...[...existingAuthors].map((a) => q.pushAsync(() => authorManager.addPad(a, padId))),
]); ]);
}; };