Skip to content

Commit 2d0074b

Browse files
committed
improve db migration
e.g. let the migration crash if some files cannot be found on disk
1 parent 60b4679 commit 2d0074b

File tree

1 file changed

+32
-35
lines changed

1 file changed

+32
-35
lines changed

backend/src/db/migrations/20250502230521-migrate-to-s3.ts

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable @typescript-eslint/no-unsafe-argument */
22

3-
import { existsSync, createReadStream } from 'node:fs'
3+
import { open } from 'node:fs/promises'
44
import path from 'node:path'
55

66
import { S3Client, ObjectCannedACL } from '@aws-sdk/client-s3'
@@ -13,10 +13,11 @@ import { getDriver } from '@db/neo4j'
1313
export const description =
1414
'Upload all image files to a S3 compatible object storage in order to reduce load on our backend.'
1515

16-
export async function up() {
16+
export async function up(_next) {
1717
if (CONFIG.NODE_ENV === 'test') {
1818
// Let's skip this migration for simplicity.
1919
// There is nothing to migrate in test environment and setting up the S3 services seems overkill.
20+
return
2021
}
2122
const { AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_ENDPOINT, AWS_BUCKET } = CONFIG
2223
if (!(AWS_ACCESS_KEY_ID && AWS_SECRET_ACCESS_KEY && AWS_ENDPOINT && AWS_BUCKET)) {
@@ -39,44 +40,40 @@ export async function up() {
3940
const { records } = await transaction.run('MATCH (image:Image) RETURN image.url as url')
4041
let urls: string[] = records.map((r) => r.get('url') as string)
4142
urls = urls.filter((url) => url.startsWith('/uploads'))
42-
const locations = await Promise.all(
43+
// eslint-disable-next-line no-console
44+
console.log('URLS uploaded:')
45+
await Promise.all(
4346
urls
44-
.map((url) => {
45-
return async () => {
46-
const { pathname } = new URL(url, 'http://example.org')
47-
const fileLocation = path.join(__dirname, `../../../public/${pathname}`)
48-
const s3Location = `original${pathname}`
49-
// eslint-disable-next-line n/no-sync, security/detect-non-literal-fs-filename
50-
if (existsSync(fileLocation)) {
51-
const mimeType = lookup(fileLocation)
52-
const params = {
53-
Bucket: AWS_BUCKET,
54-
Key: s3Location,
55-
ACL: ObjectCannedACL.public_read,
56-
ContentType: mimeType || 'image/jpeg',
57-
// eslint-disable-next-line security/detect-non-literal-fs-filename
58-
Body: createReadStream(fileLocation),
59-
}
47+
.map((url) => async () => {
48+
const { pathname } = new URL(url, 'http://example.org')
49+
const fileLocation = path.join(__dirname, `../../../public/${pathname}`)
50+
const s3Location = `original${pathname}`
51+
const mimeType = lookup(fileLocation)
52+
// eslint-disable-next-line security/detect-non-literal-fs-filename
53+
const fileHandle = await open(fileLocation)
54+
const params = {
55+
Bucket: AWS_BUCKET,
56+
Key: s3Location,
57+
ACL: ObjectCannedACL.public_read,
58+
ContentType: mimeType || 'image/jpeg',
59+
Body: fileHandle.createReadStream(),
60+
}
61+
const command = new Upload({ client: s3, params })
6062

61-
const command = new Upload({ client: s3, params })
62-
const data = await command.done()
63-
const { Location: spacesUrl } = data
63+
const data = await command.done()
64+
const { Location: spacesUrl } = data
6465

65-
const updatedRecord = await transaction.run(
66-
'MATCH (image:Image {url: $url}) SET image.url = $spacesUrl RETURN image.url as url',
67-
{ url, spacesUrl },
68-
)
69-
const [updatedUrl] = updatedRecord.records.map(
70-
(record) => record.get('url') as string,
71-
)
72-
return updatedUrl
73-
}
74-
}
66+
const updatedRecord = await transaction.run(
67+
'MATCH (image:Image {url: $url}) SET image.url = $spacesUrl RETURN image.url as url',
68+
{ url, spacesUrl },
69+
)
70+
const [updatedUrl] = updatedRecord.records.map((record) => record.get('url') as string)
71+
// eslint-disable-next-line no-console
72+
console.log(updatedUrl)
73+
return updatedUrl
7574
})
7675
.map((p) => p()),
7776
)
78-
// eslint-disable-next-line no-console
79-
console.log('these are the locations', locations)
8077
await transaction.commit()
8178
} catch (error) {
8279
// eslint-disable-next-line no-console
@@ -90,7 +87,7 @@ export async function up() {
9087
}
9188
}
9289

93-
export async function down() {
90+
export async function down(_next) {
9491
const driver = getDriver()
9592
const session = driver.session()
9693
const transaction = session.beginTransaction()

0 commit comments

Comments
 (0)