Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document specific configuration #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ key | type | required | description
--- | ---- | -------- | -----------
url | string | yes | The URL to generate a PDF from
meta | object | | Optional meta data object to send back to the webhook url
doctype | string | | Optional identifier to use special configuration settings per document

#### Example

Expand Down Expand Up @@ -366,6 +367,60 @@ module.exports = {

```

## Document Level Settings
Optionally, you can specify different settings using a document type identifier for your documents.

This allows for using document specific webhook, generator options (such as printOptions), or storage configurations.

```javascript

module.exports = {
// The settings of the API
api: {
// The port your express.js instance listens to requests from. (default: 3000)
port: 3000,
// Spawn command when a job has been pushed to the API
postPushCommand: ['/home/user/.npm-global/bin/pdf-bot', ['-c', './pdf-bot.config.js', 'shift:all']],
// The token used to validate requests to your API. Not required, but 100% recommended.
token: 'api-token'
},

document: {
//a label for configuration to refer to in requests
'foo_doc': {
storagekey: 's3',
generator: {
printOptions: {
//... special print options here (like margins and headers)
}
},
//override webhook
webhook: {
// The endpoint to send PDF messages to.
url: 'http://localhost:3000/webhooks/foo_pdf'
}
}
'bar_doc': {
//use default generator settings
//override webhook
webhook: {
// The endpoint to send PDF messages to.
url: 'http://localhost:3000/webhooks/bar_pdf'
}
}
}
// html-pdf-chrome
generator: {
// Triggers that specify when the PDF should be generated
completionTrigger: new htmlPdf.CompletionTrigger.Timer(1000), // waits for 1 sec
// The port to listen for Chrome (default: 9222)
port: 9222
}
// ... other options
}
```


## Options

```javascript
Expand Down
128 changes: 86 additions & 42 deletions bin/pdf-bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,20 @@ var defaultConfig = {
},
db: lowDb(),
// html-pdf-chrome options
generator: {

},
generator: {},
queue: {
generationRetryStrategy: function(job, retries) {
generationRetryStrategy: function (job, retries) {
return decaySchedule[retries - 1] ? decaySchedule[retries - 1] : 0
},
generationMaxTries: 5,
parallelism: 4,
webhookRetryStrategy: function(job, retries) {
webhookRetryStrategy: function (job, retries) {
return decaySchedule[retries - 1] ? decaySchedule[retries - 1] : 0
},
webhookMaxTries: 5,
lowDbOptions: {

}
lowDbOptions: {}
},
document: {},
storage: {
/*
's3': createS3Config({
Expand Down Expand Up @@ -93,7 +90,7 @@ program
port: port,
postPushCommand: apiOptions.postPushCommand,
token: apiOptions.token
}).listen(port, function() {
}).listen(port, function () {
debug('Listening to port %d', port)
})
})
Expand All @@ -106,17 +103,17 @@ program
function startPrompt() {
prompt.start({noHandleSIGINT: true})
prompt.get([
{
name: 'storagePath',
description: 'Enter a path for storage',
default: path.join(process.cwd(), 'pdf-storage'),
required: true
},
{
name: 'token',
description: 'An access token for your API',
required: false
}], function (err, result) {
{
name: 'storagePath',
description: 'Enter a path for storage',
default: path.join(process.cwd(), 'pdf-storage'),
required: true
},
{
name: 'token',
description: 'An access token for your API',
required: false
}], function (err, result) {
if (err) {
process.exit(0)
}
Expand Down Expand Up @@ -170,7 +167,7 @@ program

program
.command('db:migrate')
.action(function() {
.action(function () {
openConfig()

var db = configuration.db(configuration)
Expand All @@ -186,7 +183,7 @@ program

program
.command('db:destroy')
.action(function() {
.action(function () {
openConfig()

var db = configuration.db(configuration)
Expand All @@ -205,7 +202,7 @@ program
process.exit(0)
} else {
db.destroy()
.then(function() {
.then(function () {
console.log('The database has been destroyed.')
db.close()
process.exit(0)
Expand All @@ -218,8 +215,7 @@ program
program
.command('generate [jobID]')
.description('Generate PDF for job')
.action(function (jobId, options){
openConfig()
.action(function (jobId, options) {

return queue.getById(jobId)
.then(function (job) {
Expand All @@ -228,7 +224,7 @@ program
queue.close()
process.exit(1)
}

openConfig(false, job.doctype)
return processJob(job, configuration)
})
.catch(handleDbError)
Expand All @@ -244,7 +240,7 @@ program
openConfig()

return listJobs(queue, options.failed, options.completed, options.limit)
.then(function() {
.then(function () {
queue.close()
process.exit(0)
})
Expand All @@ -264,7 +260,7 @@ program
console.log('Job not found.')
return;
}

openConfig(false, job.doctype)
return ping(job, configuration.webhook).then(response => {
queue.close()

Expand All @@ -280,8 +276,8 @@ program

program
.command('ping:retry-failed')
.action(function() {
openConfig()
.action(function () {


var maxTries = configuration.queue.webhookMaxTries
var retryStrategy = configuration.queue.webhookRetryStrategy
Expand All @@ -292,7 +288,7 @@ program
queue.close()
process.exit(0)
}

openConfig(false, next.doctype)
return ping(next, configuration.webhook).then(function (response) {
queue.close()

Expand Down Expand Up @@ -325,7 +321,7 @@ program
colWidths: [40, 40, 50, 20, 20, 20]
});

for(var i in job.pings) {
for (var i in job.pings) {
var ping = job.pings[i]

table.push([
Expand Down Expand Up @@ -367,13 +363,15 @@ program
.command('push [url]')
.description('Push new job to the queue')
.option('-m, --meta [meta]', 'JSON string with meta data. Default: \'{}\'')
.option('-d, --doctype [doctype]', 'Document identifier to use alternate configuration. Default: \'\'')
.action(function (url, options) {
openConfig()

return queue
.addToQueue({
url: url,
meta: JSON.parse(options.meta || '{}')
meta: JSON.parse(options.meta || '{}'),
doctype: options.doctype || ''
})
.then(function (response) {
queue.close()
Expand Down Expand Up @@ -404,6 +402,8 @@ program
queue.close()
process.exit(0)
}
//have to repull the document specific configuration, if type has changed
if (next.doctype) openConfig(false, next.doctype)

return processJob(next, configuration)
})
Expand All @@ -415,6 +415,11 @@ program
.description('Run all unfinished jobs in the queue')
.action(function (url) {
openConfig()
const defaulttype = '__default'
var docConfigLookup = {
'__default': configuration
}


return queue.isBusy()
.then(function (isBusy) {
Expand Down Expand Up @@ -445,16 +450,26 @@ program
console.log('Running chunk %s, %s chunks left', k, chunks.length)

var promises = []
for(var i in chunk) {
promises.push(processJob(chunk[i], clone(configuration), false))
for (var i in chunk) {
var next = chunk[i]
var doctype = next.doctype ? next.doctype : defaulttype

if (!docConfigLookup.hasOwnProperty(doctype)) {
openConfig(doctype)
docConfigLookup[doctype] = configuration
}

configuration = docConfigLookup[defaulttype]

promises.push(processJob(next, clone(configuration), false))
}

Promise.all(promises)
.then(function(){
.then(function () {
return runNextChunk(k + 1)
})
.catch(function(){
return queue.setIsBusy(false).then(function() {
.catch(function () {
return queue.setIsBusy(false).then(function () {
queue.close()
process.exit(1)
})
Expand All @@ -481,6 +496,7 @@ if (!process.argv.slice(2).length) {
program.outputHelp();
}


function processJob(job, configuration, exitProcess = true) {
var generatorOptions = configuration.generator
var storagePlugins = configuration.storage
Expand All @@ -504,7 +520,32 @@ function processJob(job, configuration, exitProcess = true) {
})
}

function openConfig(delayQueueCreation = false) {
function processConfiguration(configuration, doctype = '') {
var defaultGeneratorOpts = configuration.generator || {}
var defaultWebhookOpts = configuration.webhook
var storagePlugins = configuration.storage || {}
var documentOptions = configuration.document || {}

var docgen = (documentOptions[doctype] && documentOptions[doctype].generator)
? documentOptions[doctype].generator : defaultGeneratorOpts

var generator = Object.assign(defaultGeneratorOpts, docgen)

var docSpecificConfig = {
//webhooks use the doc specific config or the default config
webhook: (documentOptions[doctype] && documentOptions[doctype].webhook) ? documentOptions[doctype].webhook : defaultWebhookOpts,
storage: (documentOptions[doctype] && documentOptions[doctype].storagekey && storagePlugins[documentOptions[doctype].storagekey])
? storagePlugins[documentOptions[doctype].storagekey]
: storagePlugins,
//generators use the default config with changes from the document specific config, if present
generator: generator
}

return Object.assign(configuration, docSpecificConfig)
}


function openConfig(delayQueueCreation = false, doctype = '') {
configuration = defaultConfig

if (!program.config) {
Expand Down Expand Up @@ -532,6 +573,8 @@ function openConfig(delayQueueCreation = false) {
throw new Error('There is no pdf folder in the storage folder. Create it: storage/pdf')
}

configuration = processConfiguration(configuration, doctype)

function initiateQueue() {
var db = configuration.db(configuration)
var queueOptions = configuration.queue
Expand All @@ -553,16 +596,17 @@ function listJobs(queue, failed = false, limit) {
limit
).then(function (response) {
var table = new Table({
head: ['ID', 'URL', 'Meta', 'PDF Gen. tries', 'Created at', 'Completed at'],
colWidths: [40, 40, 50, 20, 20, 20]
head: ['ID', 'URL', 'Doc Type', 'Meta', 'PDF Gen. tries', 'Created at', 'Completed at'],
colWidths: [40, 40, 20, 45, 20, 20, 20]
});

for(var i in response) {
for (var i in response) {
var job = response[i]

table.push([
job.id,
job.url,
job.doctype,
JSON.stringify(job.meta),
job.generations.length,
formatDate(job.created_at),
Expand Down
3 changes: 2 additions & 1 deletion src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ function createApi(createQueue, options = {}) {
queue
.addToQueue({
url: req.body.url,
meta: req.body.meta || {}
meta: req.body.meta || {},
doctype: req.body.doctype || ''
}).then(function (response) {
queue.close()

Expand Down
Loading