transloadit: Add getAssemblyOptions.

This patch adds a `getAssemblyOptions` function option to the
Transloadit plugin. This option can return an object or a Promise for an
object to configure the Transloadit assembly. The returned object can
contain `params`, a `signature`, and `fields`.

`getAssemblyOptions` is called on each file, so each file can return a
different set of options. Files that returned the same options are
bundled together and run through a single assembly. Files that return
different options will be run through different assemblies.

This means that it is now possible to make assembly parameters depend on
user input from eg. the MetaData plugin, and have different parameters
for different files. It's now also possible to generate very short-lived
signatures on the server when an upload starts.
This commit is contained in:
Renée Kooi 2017-07-04 14:12:27 +02:00
parent 36c999de1d
commit 5f7d3d79cf
No known key found for this signature in database
GPG key ID: 30516CF2A8E63718

View file

@ -26,6 +26,13 @@ module.exports = class Transloadit extends Plugin {
signature: null,
params: null,
fields: {},
getAssemblyOptions (file, options) {
return {
params: options.params,
signature: options.signature,
fields: options.fields
}
},
locale: defaultLocale
}
@ -62,14 +69,44 @@ module.exports = class Transloadit extends Plugin {
this.sockets = {}
}
createAssembly (filesToUpload) {
getAssemblyOptions (fileIDs) {
const options = this.opts
return Promise.all(
fileIDs.map((fileID) => {
const file = this.getFile(fileID)
return Promise.resolve(options.getAssemblyOptions(file, options)).then((assemblyOptions) => ({
fileIDs: [fileID],
options: assemblyOptions
}))
})
)
}
dedupeAssemblyOptions (list) {
const dedupeMap = Object.create(null)
list.forEach(({ fileIDs, options }) => {
const id = JSON.stringify(options)
if (dedupeMap[id]) {
dedupeMap[id].fileIDs.push(...fileIDs)
} else {
dedupeMap[id] = {
options,
fileIDs: [...fileIDs]
}
}
})
return Object.keys(dedupeMap).map((id) => dedupeMap[id])
}
createAssembly (fileIDs, options) {
this.core.log('Transloadit: create assembly')
return this.client.createAssembly({
params: this.opts.params,
fields: this.opts.fields,
expectedFiles: Object.keys(filesToUpload).length,
signature: this.opts.signature
params: options.params,
fields: options.fields,
expectedFiles: fileIDs.length,
signature: options.signature
}).then((assembly) => {
this.updateState({
assemblies: Object.assign(this.state.assemblies, {
@ -103,13 +140,13 @@ module.exports = class Transloadit extends Plugin {
}
const files = Object.assign({}, this.core.state.files)
Object.keys(filesToUpload).forEach((id) => {
fileIDs.forEach((id) => {
files[id] = attachAssemblyMetadata(files[id], assembly)
})
this.core.setState({ files })
this.core.emit('transloadit:assembly', assembly, Object.keys(filesToUpload))
this.core.emit('transloadit:assembly', assembly, fileIDs)
return this.connectSocket(assembly)
}).then(() => {
@ -208,27 +245,31 @@ module.exports = class Transloadit extends Plugin {
})
}
prepareUpload (fileIDs) {
const filesToUpload = fileIDs.map(getFile, this).reduce(intoFileMap, {})
function getFile (fileID) {
return this.core.state.files[fileID]
}
function intoFileMap (map, file) {
map[file.id] = file
return map
}
getFile (fileID) {
return this.core.state.files[fileID]
}
prepareUpload (fileIDs) {
fileIDs.forEach((fileID) => {
this.core.emit('core:preprocess-progress', fileID, {
mode: 'indeterminate',
message: this.opts.locale.strings.creatingAssembly
})
})
return this.createAssembly(filesToUpload).then(() => {
fileIDs.forEach((fileID) => {
this.core.emit('core:preprocess-complete', fileID)
const createAssembly = ({ fileIDs, options }) => {
return this.createAssembly(fileIDs, options).then(() => {
fileIDs.forEach((fileID) => {
this.core.emit('core:preprocess-complete', fileID)
})
})
})
}
return this.getAssemblyOptions(fileIDs)
.then((allOptions) => this.dedupeAssemblyOptions(allOptions))
.then((assemblies) => Promise.all(
assemblies.map(createAssembly)
))
}
afterUpload (fileIDs) {
@ -238,7 +279,7 @@ module.exports = class Transloadit extends Plugin {
// If we don't have to wait for encoding metadata or results, we can close
// the socket immediately and finish the upload.
if (!this.shouldWait()) {
const file = this.core.getState().files[fileID]
const file = this.getFile(fileID)
const socket = this.socket[file.assembly]
socket.close()
return
@ -253,7 +294,7 @@ module.exports = class Transloadit extends Plugin {
})
const onAssemblyFinished = (assembly) => {
const file = this.core.state.files[fileID]
const file = this.getFile(fileID)
// An assembly for a different upload just finished. We can ignore it.
if (assembly.assembly_id !== file.transloadit.assembly) {
return
@ -273,7 +314,7 @@ module.exports = class Transloadit extends Plugin {
}
const onAssemblyError = (assembly, error) => {
const file = this.core.state.files[fileID]
const file = this.getFile(fileID)
// An assembly for a different upload just errored. We can ignore it.
if (assembly.assembly_id !== file.transloadit.assembly) {
return