finished /claim/claimId serve local first

This commit is contained in:
bill bittner 2017-06-21 16:36:08 -07:00
parent 44f6883b3a
commit 0e5215a84e
4 changed files with 130 additions and 53 deletions

View file

@ -4,12 +4,10 @@ const lbryApi = require('../helpers/libraries/lbryApi.js');
const config = require('config');
const walledAddress = config.get('WalletConfig.lbryAddress');
const errorHandlers = require('../helpers/libraries/errorHandlers.js');
const db = require('../models');
function createPublishParams (claim, filePath, license, nsfw) {
logger.debug(`Creating Publish Parameters for "${claim}"`);
if (typeof nsfw === 'string') {
nsfw = (nsfw.toLowerCase() === 'on');
}
const publishParams = {
name : claim,
file_path: filePath,
@ -36,24 +34,61 @@ function deleteTemporaryFile (filePath) {
});
}
function upsert (Model, values, condition) {
return Model
.findOne({ where: condition })
.then(function (obj) {
if (obj) { // update
return obj.update(values);
} else { // insert
return Model.create(values);
}
}).catch(function (error) {
logger.error('Sequelize findOne error', error);
});
}
module.exports = {
publish (claim, fileName, filePath, fileType, license, nsfw, socket, visitor) {
publish (name, fileName, filePath, fileType, license, nsfw, socket, visitor) {
// validate nsfw
if (typeof nsfw === 'string') {
nsfw = (nsfw.toLowerCase() === 'on');
}
// update the client
socket.emit('publish-status', 'Your image is being published (this might take a second)...');
// send to analytics
visitor.event('Publish Route', 'Publish Request', filePath).send();
// create the publish object
const publishParams = createPublishParams(claim, filePath, license, nsfw);
const publishParams = createPublishParams(name, filePath, license, nsfw);
// get a promise to publish
lbryApi
.publishClaim(publishParams, fileName, fileType)
.then(result => {
logger.info(`Successfully published ${fileName}`);
logger.info(`Successfully published ${fileName}`, result);
// google analytics
visitor.event('Publish Route', 'Publish Success', filePath).send();
socket.emit('publish-complete', { name: claim, result });
// update old record of create new one
upsert(
db.File,
{
name,
claimId : result.claim_id,
outpoint: `${result.txid}:${result.nout}`,
fileName,
filePath,
fileType,
nsfw,
},
{ name, claimId: result.claim_id }
).catch(error => {
logger.error('Sequelize findOne error', error);
});
// update client
socket.emit('publish-complete', { name, result });
})
.catch(error => {
logger.error(`Error publishing ${fileName}`, error);
// google analytics
visitor.event('Publish Route', 'Publish Failure', filePath).send();
socket.emit('publish-failure', errorHandlers.handlePublishError(error));
deleteTemporaryFile(filePath);

View file

@ -19,6 +19,61 @@ function getClaimAndHandleResponse (claimUri, resolve, reject) {
});
}
function resolveAndUpdateIfNeeded (uri, claimName, claimId, outpoint) {
logger.debug('initiating resolve on local record to check outpoint');
// 1. resolve claim
lbryApi
.resolveUri(uri)
.then(result => {
// logger.debug('resolved result:', result);
const resolvedOutpoint = `${result[uri].claim.txid}:${result[uri].claim.nout}`;
logger.debug('database outpoint:', outpoint);
logger.debug('resolved outpoint:', resolvedOutpoint);
// 2. if the outpoint's match, no further work needed
if (outpoint === resolvedOutpoint) {
logger.debug(`local outpoint matched`);
// 2. if the outpoints don't match, get claim and update records
} else {
logger.debug(`local outpoint did not match for ${uri}. Initiating update.`);
getClaimAndUpdate(uri, claimName, claimId);
}
})
.catch(error => {
logger.error(`error resolving ${uri}`, error);
});
}
function getClaimAndUpdate (uri, claimName, claimId) {
// 1. get the claim
lbryApi
.getClaim(uri)
.then(({ outpoint, file_name, download_path, mime_type }) => {
logger.debug('getClaim outpoint', outpoint);
// 2. update the entry in db
db.File
.update({
outpoint: outpoint,
fileName: file_name,
filePath: download_path,
fileType: mime_type,
}, {
where: {
name : claimName,
claimId: claimId,
},
})
.then(result => {
logger.debug('successfully updated mysql record', result);
})
.catch(error => {
logger.error('sequelize error', error);
});
})
.catch(error => {
logger.error(`error while getting claim for ${uri}`, error);
});
}
module.exports = {
getClaimByName (claimName) {
const deferred = new Promise((resolve, reject) => {
@ -51,6 +106,7 @@ module.exports = {
}
})
.catch(error => {
logger.error('sequelize error', error);
reject(error);
});
})
@ -63,39 +119,35 @@ module.exports = {
getClaimByClaimId (claimName, claimId) {
const deferred = new Promise((resolve, reject) => {
const uri = `${claimName}#${claimId}`;
// resolve the Uri
lbryApi
.resolveUri(uri) // note: use 'spread' and make parallel with db.File.findOne()
.then(result => {
const resolvedOutpoint = `${result[uri].claim.txid}:${result[uri].claim.nout}`;
// check locally for the claim
// 1. check locally for the claim
db.File
.findOne({ where: { name: claimName, claimId: claimId } })
.then(claim => {
// if a found locally...
// 2. if a found locally, serve
if (claim) {
logger.debug(`A mysql record was found for ${claimId}`);
// if the outpoint's match return it
if (claim.dataValues.outpoint === resolvedOutpoint) {
logger.debug(`local outpoint matched for ${claimId}`);
// trigger an update if needed
resolveAndUpdateIfNeeded(uri, claimName, claimId, claim.dataValues.outpoint); // ok to just start asynch function, or need to add to a task cue?
// resolve and send
resolve(claim.dataValues);
// if the outpoint's don't match, fetch updated claim
} else {
logger.debug(`local outpoint did not match for ${claimId}`);
getClaimAndHandleResponse(uri, resolve, reject);
}
// ... otherwise use daemon to retrieve it
// 2. otherwise use daemon to retrieve it
} else {
// 3. resolve the Uri
lbryApi
.resolveUri(uri)
.then(result => {
// 4. check to see if the claim is free & public
if (isFreePublicClaim(result[uri].claim)) {
// 5. get claim and serve
getClaimAndHandleResponse(uri, resolve, reject);
} else {
reject('NO_FREE_PUBLIC_CLAIMS');
}
}
})
.catch(error => {
reject(error);
});
}
})
.catch(error => {
reject(error);

View file

@ -1,15 +1,6 @@
const axios = require('axios');
const db = require('../../models');
const logger = require('winston');
function createFilesRecord (name, claimId, outpoint, fileName, filePath, fileType, nsfw) {
db.File
.create({ name, claimId, outpoint, fileName, filePath, fileType, nsfw })
.catch(error => {
logger.error(`Sequelize File.create error`, error);
});
}
module.exports = {
publishClaim (publishParams, fileName, fileType) {
logger.debug(`Publishing claim for "${fileName}"`);
@ -21,8 +12,6 @@ module.exports = {
})
.then(response => {
const result = response.data.result;
createFilesRecord(
publishParams.name, result.claim_id, `${result.txid}:${result.nout}`, fileName, publishParams.file_path, fileType, publishParams.metadata.nsfw);
resolve(result);
})
.catch(error => {
@ -50,11 +39,7 @@ module.exports = {
/*
note: put in a check to make sure we do not resolve until the download is actually complete (response.data.completed === true)
*/
// save a record of the file to the Files table
const result = data.result;
createFilesRecord(
result.name, result.claim_id, result.outpoint, result.file_name, result.download_path, result.mime_type, result.metadata.stream.metadata.nsfw);
resolve(result);
resolve(data.result);
})
.catch(error => {
reject(error);
@ -88,6 +73,11 @@ module.exports = {
params: { uri },
})
.then(({ data }) => {
// check for errors
if (data.result[uri].error) {
reject(data.result[uri].error);
return;
}
resolve(data.result);
})
.catch(error => {

View file

@ -14,10 +14,10 @@ const sequelize = new Sequelize(connectionUri, {
sequelize
.authenticate()
.then(() => {
logger.info('Sequelize has has been established mysql connection successfully.');
logger.info('Sequelize has established mysql connection successfully.');
})
.catch(err => {
logger.error('Sequelize was nable to connect to the database:', err);
logger.error('Sequelize was unable to connect to the database:', err);
});
fs.readdirSync(__dirname).filter(file => file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js').forEach(file => {