Created
July 18, 2018 15:51
-
-
Save RomanSteinberg/618b6b1d13e8d3cff7743b7dace818b0 to your computer and use it in GitHub Desktop.
models/task.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Promise = require('bluebird'); | |
const mongoose = require('mongoose'); | |
const _ = require('lodash'); | |
const Answer = require('./answer'); | |
const GooGl = require('./goo-gl'); | |
const Meta = require('./meta'); | |
const Recommendations = require('./recommendations'); | |
const config = require('../config'); | |
const helpers = require('../libs/helpers'); | |
const STATUS_PENDING = 'pending'; | |
const STATUS_FULFILLED = 'fulfilled'; | |
const STATUS_REJECTED = 'rejected'; | |
const LOCALES = ['en', 'ru']; | |
const QUALITIES = ['bad', 'regular', 'good']; | |
const logger = require('../libs/logger.js'); | |
const TaskSchema = new mongoose.Schema({ | |
url: { | |
type: String, | |
required: true, | |
}, | |
locale: { | |
type: String, | |
required: true, | |
}, | |
parserTaskId: { | |
type: mongoose.Schema.ObjectId, | |
required: true, | |
}, | |
uuid: { | |
type: String, | |
required: true, | |
}, | |
status: { | |
type: String, | |
enum: [STATUS_PENDING, STATUS_FULFILLED, STATUS_REJECTED], | |
default: STATUS_PENDING, | |
required: true, | |
}, | |
stages: { | |
type: [String], | |
required: true, | |
}, | |
stage: { | |
type: String, | |
validate(stage) { | |
return this.stages.includes(stage); | |
}, | |
required: true, | |
}, | |
attributes: Object, | |
rate: Number, | |
recommendations: Object, | |
screenshot: String, | |
preview: String, | |
dateDone: Date, | |
error: String, | |
}); | |
TaskSchema.statics = { | |
STATUS_PENDING, | |
STATUS_FULFILLED, | |
STATUS_REJECTED, | |
async getNewWithUuid({ | |
url, | |
locale, | |
stages, | |
parserTaskId, | |
}, uuid) { | |
if (! helpers.url.validate(url)) throw new Error('Bad url'); | |
url = helpers.url.normalise(url); | |
const task = await this.create({ | |
url, | |
locale, | |
parserTaskId, | |
stages, | |
stage: stages[0], | |
uuid, | |
}); | |
return task; | |
}, | |
async getById(id) { | |
const task = await this.findById(id); | |
if (! task) { | |
throw new Error('Task not found'); | |
} | |
return task; | |
}, | |
async getByIdWithUuid(id, uuid) { | |
const task = await this.getById(id); | |
if (config.history.private && task.uuid !== uuid) { | |
throw new Error('Try access to task without owning it'); | |
} | |
return task; | |
}, | |
async getHistoryWithUuid({ from, to }, uuid) { | |
const tasksFilter = { | |
status: 'fulfilled', | |
}; | |
if (config.history.private) { | |
tasksFilter.uuid = uuid; | |
} | |
let tasks = await this | |
.find(tasksFilter) | |
.sort({ _id: -1 }) | |
.exec(); | |
tasks = Object.values(_.groupBy(tasks, 'url')) | |
.map(tasks => tasks[0]) | |
.slice(from, to); | |
return tasks; | |
}, | |
getMeta(lang) { | |
return Meta.get(lang); | |
}, | |
}; | |
TaskSchema.methods = { | |
async setStages(stages) { | |
this.stages = stages; | |
await this.save(); | |
return this; | |
}, | |
async setStage(stage) { | |
logger.info('taskId=' + task.id + '; url=' + task.url + '; error=' + this.error + '; setStage=' + stage.toString()); | |
this.stage = stage; | |
await this.save(); | |
return this; | |
}, | |
async setParserResult({ attributes, screenshot, preview }) { | |
logger.info('taskId=' + task.id + '; url=' + task.url + '; error=' + this.error + '; setParserResult done'); | |
this.attributes = attributes; | |
this.screenshot = screenshot; | |
this.preview = preview; | |
await this.save(); | |
return this; | |
}, | |
async setModelResult(modelTask) { | |
logger.info('taskId=' + task.id + '; url=' + task.url + '; error=' + this.error + '; setModelResult done'); | |
this.rate = modelTask.rate; | |
this.recommendations = modelTask.recommendations; | |
await this.save(); | |
return this; | |
}, | |
async setDone() { | |
this.status = STATUS_FULFILLED; | |
this.dateDone = Date.now(); | |
await this.save(); | |
return this; | |
}, | |
async setError(message) { | |
this.status = STATUS_REJECTED; | |
this.error = message; | |
await this.save(); | |
return this; | |
}, | |
async serialize(uuid) { | |
let answer = null; | |
try { | |
({ rate: answer } = await Answer.getByTaskId(this.id, uuid)); | |
} catch (err) {} | |
const meta = _.fromPairs(LOCALES.map(locale => [locale, this.getMeta(locale)])); | |
const shortUrl = _.fromPairs(await Promise.map(LOCALES, async locale => [locale, await GooGl.getShortUrl(meta[locale].ogUrl.content)])); | |
const recommendations = this.rate < config.rate.recommendationsThreshold ? | |
_.fromPairs(LOCALES.map(locale => [locale, this.getRecommendations(locale)])) : | |
_.fromPairs(LOCALES.map(locale => [locale, []])); | |
const quality = QUALITIES[_.sortedIndex(config.rate.qualityThreshold, this.rate)]; | |
return { | |
..._.pick(this, [ | |
'id', | |
'url', | |
'status', | |
'stages', | |
'stage', | |
'rate', | |
'dateDone', | |
'error', | |
]), | |
answer, | |
meta, | |
shortUrl, | |
recommendations, | |
quality, | |
}; | |
}, | |
getMeta(locale) { | |
return Meta.get(locale, 'task', { | |
title: { rate: Math.round(this.rate) }, | |
url: { taskId: this.id }, | |
image: { taskId: this.id }, | |
}); | |
}, | |
getRecommendations(locale) { | |
return Recommendations.get({ | |
locale, | |
attributes: this.attributes, | |
recommendations: this.recommendations, | |
}); | |
}, | |
}; | |
module.exports = mongoose.model('Task', TaskSchema); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment