2020-03-20 19:52:36 -07:00
|
|
|
import { Summary } from 'prom-client';
|
2020-02-06 21:55:47 -08:00
|
|
|
import { createMySQLDuplicateKeyUpdate } from '../util/on-duplicate-key-update';
|
|
|
|
|
|
2020-10-23 11:51:59 -07:00
|
|
|
const Media = require('@cytube/mediaquery/lib/media');
|
2020-03-20 19:52:36 -07:00
|
|
|
const LOGGER = require('@calzoneman/jsli')('metadata-cache');
|
2020-02-06 21:55:47 -08:00
|
|
|
|
|
|
|
|
// TODO: these fullname-vs-shortcode hacks really need to be abolished
|
|
|
|
|
function mediaquery2cytube(type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'youtube':
|
|
|
|
|
return 'yt';
|
|
|
|
|
default:
|
|
|
|
|
throw new Error(`mediaquery2cytube: no mapping for ${type}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function cytube2mediaquery(type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'yt':
|
|
|
|
|
return 'youtube';
|
|
|
|
|
default:
|
|
|
|
|
throw new Error(`cytube2mediaquery: no mapping for ${type}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 19:52:36 -07:00
|
|
|
const cachedResultAge = new Summary({
|
|
|
|
|
name: 'cytube_yt_cache_result_age_seconds',
|
|
|
|
|
help: 'Age (in seconds) of cached record'
|
|
|
|
|
});
|
|
|
|
|
|
2020-02-06 21:55:47 -08:00
|
|
|
class MetadataCacheDB {
|
|
|
|
|
constructor(db) {
|
|
|
|
|
this.db = db;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async put(media) {
|
|
|
|
|
media = new Media(media);
|
|
|
|
|
media.type = mediaquery2cytube(media.type);
|
|
|
|
|
return this.db.runTransaction(async tx => {
|
|
|
|
|
let insert = tx.table('media_metadata_cache')
|
|
|
|
|
.insert({
|
|
|
|
|
id: media.id,
|
|
|
|
|
type: media.type,
|
2020-03-20 19:44:11 -07:00
|
|
|
metadata: JSON.stringify(media),
|
|
|
|
|
updated_at: tx.raw('CURRENT_TIMESTAMP')
|
2020-02-06 21:55:47 -08:00
|
|
|
});
|
|
|
|
|
let update = tx.raw(createMySQLDuplicateKeyUpdate(
|
2020-03-20 19:44:11 -07:00
|
|
|
['metadata', 'updated_at']
|
2020-02-06 21:55:47 -08:00
|
|
|
));
|
|
|
|
|
|
|
|
|
|
return tx.raw(insert.toString() + update.toString());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async get(id, type) {
|
|
|
|
|
return this.db.runTransaction(async tx => {
|
|
|
|
|
let row = await tx.table('media_metadata_cache')
|
|
|
|
|
.where({ id, type })
|
|
|
|
|
.first();
|
|
|
|
|
|
|
|
|
|
if (row === undefined || row === null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 19:52:36 -07:00
|
|
|
try {
|
|
|
|
|
let age = (Date.now() - row.updated_at.getTime())/1000;
|
|
|
|
|
if (age > 0) {
|
|
|
|
|
cachedResultAge.observe(age);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
LOGGER.error('Failed to record cachedResultAge metric: %s', error.stack);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 21:55:47 -08:00
|
|
|
let metadata = JSON.parse(row.metadata);
|
|
|
|
|
metadata.type = cytube2mediaquery(metadata.type);
|
|
|
|
|
return new Media(metadata);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export { MetadataCacheDB };
|