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

Rewrite Companion providers to use streams to allow simultaneous upload/download without saving to disk #3159

Merged
merged 51 commits into from Nov 1, 2021
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
27c64c7
rewrite to async/await
mifi Jul 26, 2021
ce4e8f3
Only fetch size (HEAD) if needed #3034
mifi Jul 26, 2021
b9d2091
Update packages/@uppy/companion/src/server/controllers/url.js
mifi Jul 29, 2021
88b7c51
Merge branch 'main' into companion-optional-head
mifi Aug 29, 2021
0b6c488
Change HEAD to GET in getURLMeta
mifi Aug 30, 2021
77c4f25
fix lint
mifi Aug 30, 2021
4226c95
fix lint
mifi Aug 30, 2021
cf494e5
cut off length of file names
mifi Aug 30, 2021
4aabeea
try to fix flaky test
mifi Aug 30, 2021
11429a7
remove iife and cleanup code a bit
mifi Aug 31, 2021
0ba8349
fix lint by reordering code
mifi Aug 31, 2021
55370c5
rename Uploader to MultipartUploader
mifi Aug 31, 2021
f406288
Rewrite Uploader to use fs-capacitor #3098
mifi Sep 2, 2021
7a08af4
add comment in dev Dashboard and pull out variable
mifi Sep 2, 2021
2d6efdf
fix a bug where remote xhr upload would ignore progress events in the UI
mifi Sep 2, 2021
1a77274
fix bug where s3 multipart cancel wasn't working
mifi Sep 2, 2021
1b763be
fix also cancel for xhr
mifi Sep 2, 2021
cdb6239
Rewrite providers to use streams
mifi Sep 3, 2021
2f7fc2d
Merge branch 'main' into companion-upload-while-downloading
mifi Sep 3, 2021
50cd8c3
Implement streamingUpload flag
mifi Sep 7, 2021
bd255aa
rearrange validation logic
mifi Sep 7, 2021
e756b0a
add COMPANION_STREAMING_UPLOAD to env.test.sh too
mifi Sep 7, 2021
9113472
implement maxFileSize option in companion
mifi Sep 7, 2021
919ec18
fix bug
mifi Sep 8, 2021
eecdba9
fix memory leak when non 200 status
mifi Sep 8, 2021
bc62a69
fix lint
mifi Sep 8, 2021
a16f34c
Add backward-compatibility for companion providers
mifi Sep 8, 2021
313d75b
document new provider API
mifi Sep 8, 2021
65ac8c7
remove static as it doesn't work on node 10
mifi Sep 8, 2021
c8ff49c
try to fix build issue
mifi Sep 8, 2021
735bde1
degrade to node 14 in github actions
mifi Sep 8, 2021
812a44f
Merge branch 'main' into companion-upload-while-downloading
mifi Sep 8, 2021
a1bbb62
pull out duplicated logic into reusable function
mifi Sep 8, 2021
6a6b697
fix lint
mifi Sep 9, 2021
42c2b3d
make methods private
mifi Oct 23, 2021
84385bc
Merge branch 'main' into companion-upload-while-downloading
mifi Oct 23, 2021
e322b23
re-add unsplash download_location request
mifi Oct 23, 2021
4783593
add try/catch
mifi Oct 23, 2021
670ca8f
Only set default chunkSize if needed
mifi Oct 23, 2021
1e28ef2
Improve flaky test
mifi Oct 23, 2021
d0ff2cc
Apply suggestions from code review
mifi Oct 24, 2021
9a6af79
fix review feedback & lint
mifi Oct 27, 2021
4eff356
Apply suggestions from code review
mifi Oct 27, 2021
0f148b5
Merge commit 'e30601df8a89c1a83a6fdb2eb1c8e0eea5cd42cf' into companio…
mifi Oct 28, 2021
ecb86da
remove unneeded ts-ignore
mifi Oct 28, 2021
b775d4a
Update packages/@uppy/companion/src/server/controllers/url.js
mifi Oct 28, 2021
259e493
Update packages/@uppy/companion/src/server/Uploader.js
mifi Oct 28, 2021
21b9d64
reduce nesting
mifi Oct 28, 2021
2338d2f
fix lint
mifi Oct 28, 2021
55a754a
optimize promisify
mifi Oct 28, 2021
291d8e3
Update packages/@uppy/companion/test/__tests__/uploader.js
mifi Oct 29, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
75 changes: 45 additions & 30 deletions examples/custom-provider/server/customprovider.js
Expand Up @@ -32,11 +32,14 @@ function adaptData (res) {
* an example of a custom provider module. It implements @uppy/companion's Provider interface
*/
class MyCustomProvider {
static version = 2

constructor () {
this.authProvider = 'myunsplash'
}

list ({ token, directory }, done) {
// eslint-disable-next-line class-methods-use-this
async list ({ token, directory }) {
const path = directory ? `/${directory}/photos` : ''
const options = {
url: `${BASE_URL}/collections${path}`,
Expand All @@ -47,18 +50,20 @@ class MyCustomProvider {
},
}

request(options, (err, resp, body) => {
if (err) {
console.log(err)
done(err)
return
}
return new Promise((resolve, reject) => (
request(options, (err, resp, body) => {
if (err) {
console.log(err)
reject(err)
return
}

done(null, adaptData(body))
})
resolve(adaptData(body))
})))
}

download ({ id, token }, onData) {
// eslint-disable-next-line class-methods-use-this
async download ({ id, token }) {
const options = {
url: `${BASE_URL}/photos/${id}`,
method: 'GET',
Expand All @@ -68,21 +73,30 @@ class MyCustomProvider {
},
}

request(options, (err, resp, body) => {
if (err) {
console.log(err)
return
}

const url = body.links.download
request.get(url)
.on('data', (chunk) => onData(null, chunk))
.on('end', () => onData(null, null))
.on('error', (err) => console.log(err))
const resp = await new Promise((resolve, reject) => {
const req = request(options)
.on('response', (response) => {
// Don't allow any more data to flow yet.
// https://github.com/request/request/issues/1990#issuecomment-184712275
response.pause()

if (resp.statusCode !== 200) {
req.abort() // Or we will leak memory
reject(new Error(`HTTP response ${resp.statusCode}`))
return
}

resolve(response)
})
.on('error', reject)
})

// The returned stream will be consumed and uploaded from the current position
return { stream: resp }
}

size ({ id, token }, done) {
// eslint-disable-next-line class-methods-use-this
async size ({ id, token }) {
const options = {
url: `${BASE_URL}/photos/${id}`,
method: 'GET',
Expand All @@ -92,15 +106,16 @@ class MyCustomProvider {
},
}

request(options, (err, resp, body) => {
if (err) {
console.log(err)
done(err)
return
}
return new Promise((resolve, reject) => (
request(options, (err, resp, body) => {
if (err) {
console.log(err)
reject(err)
return
}

done(null, body.width * body.height)
})
resolve(body.size)
})))
}
}

Expand Down
5 changes: 3 additions & 2 deletions examples/custom-provider/server/index.js
Expand Up @@ -4,6 +4,7 @@ const express = require('express')
const bodyParser = require('body-parser')
const session = require('express-session')
const uppy = require('../../../packages/@uppy/companion')
const MyCustomProvider = require('./customprovider')

const app = express()

Expand Down Expand Up @@ -42,8 +43,8 @@ const uppyOptions = {
key: 'your unsplash key here',
secret: 'your unsplash secret here',
},
// you provider module
module: require('./customprovider'),
// you provider class/module:
module: MyCustomProvider,
},
},
server: {
Expand Down
5 changes: 5 additions & 0 deletions examples/dev/Dashboard.js
Expand Up @@ -29,6 +29,8 @@ const DropTarget = require('@uppy/drop-target/src')
const UPLOADER = 'tus'
// const UPLOADER = 's3'
// const UPLOADER = 's3-multipart'
// xhr will use protocol 'multipart' in companion, if used with a remote service, e.g. google drive.
// If local upload will use browser XHR
// const UPLOADER = 'xhr'
// const UPLOADER = 'transloadit'
// const UPLOADER = 'transloadit-s3'
Expand All @@ -44,6 +46,7 @@ const XHR_ENDPOINT = 'https://xhr-server.herokuapp.com/upload'

const TRANSLOADIT_KEY = '...'
const TRANSLOADIT_TEMPLATE = '...'
const TRANSLOADIT_SERVICE_URL = 'https://api2.transloadit.com'

// DEV CONFIG: enable or disable Golden Retriever

Expand Down Expand Up @@ -109,6 +112,7 @@ module.exports = () => {
break
case 'transloadit':
uppyDashboard.use(Transloadit, {
service: TRANSLOADIT_SERVICE_URL,
waitForEncoding: true,
params: {
auth: { key: TRANSLOADIT_KEY },
Expand Down Expand Up @@ -141,6 +145,7 @@ module.exports = () => {
bundle: true,
})
break
default:
}

if (RESTORE) {
Expand Down
8 changes: 4 additions & 4 deletions packages/@uppy/aws-s3-multipart/src/index.js
Expand Up @@ -4,7 +4,7 @@ const EventTracker = require('@uppy/utils/lib/EventTracker')
const emitSocketProgress = require('@uppy/utils/lib/emitSocketProgress')
const getSocketHost = require('@uppy/utils/lib/getSocketHost')
const { RateLimitedQueue } = require('@uppy/utils/lib/RateLimitedQueue')
const Uploader = require('./MultipartUploader')
const MultipartUploader = require('./MultipartUploader')

function assertServerError (res) {
if (res && res.error) {
Expand Down Expand Up @@ -187,7 +187,7 @@ module.exports = class AwsS3Multipart extends BasePlugin {
this.uppy.emit('s3-multipart:part-uploaded', cFile, part)
}

const upload = new Uploader(file.data, {
const upload = new MultipartUploader(file.data, {
// .bind to pass the file object to each handler.
createMultipartUpload: this.opts.createMultipartUpload.bind(this, file),
listParts: this.opts.listParts.bind(this, file),
Expand Down Expand Up @@ -320,7 +320,7 @@ module.exports = class AwsS3Multipart extends BasePlugin {

this.onFileRemove(file.id, () => {
queuedRequest.abort()
socket.send('pause', {})
socket.send('cancel', {})
this.resetUploaderReferences(file.id, { abort: true })
resolve(`upload ${file.id} was removed`)
})
Expand Down Expand Up @@ -348,7 +348,7 @@ module.exports = class AwsS3Multipart extends BasePlugin {

this.onCancelAll(file.id, () => {
queuedRequest.abort()
socket.send('pause', {})
socket.send('cancel', {})
this.resetUploaderReferences(file.id)
resolve(`upload ${file.id} was canceled`)
})
Expand Down
1 change: 1 addition & 0 deletions packages/@uppy/companion/KUBERNETES.md
Expand Up @@ -25,6 +25,7 @@ data:
COMPANION_DOMAIN: "YOUR SERVER DOMAIN"
COMPANION_DOMAINS: "sub1.domain.com,sub2.domain.com,sub3.domain.com"
COMPANION_PROTOCOL: "YOUR SERVER PROTOCOL"
COMPANION_STREAMING_UPLOAD: true
COMPANION_REDIS_URL: redis://:superSecretPassword@uppy-redis.uppy.svc.cluster.local:6379
COMPANION_SECRET: "shh!Issa Secret!"
COMPANION_DROPBOX_KEY: "YOUR DROPBOX KEY"
Expand Down
2 changes: 2 additions & 0 deletions packages/@uppy/companion/env.test.sh
Expand Up @@ -5,6 +5,8 @@ export COMPANION_SELF_ENDPOINT="localhost:3020"
export COMPANION_HIDE_METRICS="false"
export COMPANION_HIDE_WELCOME="false"

export COMPANION_STREAMING_UPLOAD="true"

export COMPANION_PROTOCOL="http"
export COMPANION_DATADIR="./test/output"
export COMPANION_SECRET="secret"
Expand Down
1 change: 1 addition & 0 deletions packages/@uppy/companion/env_example
Expand Up @@ -4,6 +4,7 @@ COMPANION_DOMAIN=uppy.xxxx.com
COMPANION_SELF_ENDPOINT=uppy.xxxx.com
COMPANION_HIDE_METRICS=false
COMPANION_HIDE_WELCOME=false
COMPANION_STREAMING_UPLOAD=true

COMPANION_PROTOCOL=https
COMPANION_DATADIR=/mnt/uppy-server-data
Expand Down
2 changes: 2 additions & 0 deletions packages/@uppy/companion/package.json
Expand Up @@ -85,6 +85,8 @@
"@types/uuid": "3.4.7",
"@types/webpack": "^5.28.0",
"@types/ws": "6.0.4",
"into-stream": "^6.0.0",
"nock": "^13.1.3",
"supertest": "3.4.2",
"typescript": "~4.3"
},
Expand Down
1 change: 1 addition & 0 deletions packages/@uppy/companion/src/companion.js
Expand Up @@ -39,6 +39,7 @@ const defaultOptions = {
},
debug: true,
logClientVersion: true,
streamingUpload: false,
}

// make the errors available publicly for custom providers
Expand Down