Browse Source

Merge pull request #1374 from gre/hotfixes/1.1.2

Prepare 1.1.2
master
Gaëtan Renaudeau 7 years ago
committed by GitHub
parent
commit
81488091f1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/migrations/index.js
  2. 29
      src/migrations/migrations.js
  3. 67
      src/migrations/migrations.spec.js
  4. BIN
      src/migrations/mocks/userdata_v1.0.5_mock-03-missing-file.zip
  5. BIN
      src/migrations/mocks/userdata_v1.0.5_mock-04-app-json-present.zip
  6. BIN
      src/migrations/mocks/userdata_v1.1.1_mock-01.zip
  7. 12
      src/sentry/install.js

8
src/migrations/index.js

@ -8,14 +8,16 @@ import migrations from './migrations'
// Logic to run all the migrations based on what was not yet run:
export const runMigrations = async (): Promise<void> => {
const current = await db.getNamespace('migrations')
// Legacy: the migration nonce was previously stored in separate file
// it can happen, so we have to check it from here also.
const current = (await db.getKey('app', 'migrations')) || (await db.getNamespace('migrations'))
let { nonce } = current || { nonce: migrations.length }
const outdated = migrations.length - nonce
if (!outdated) {
if (!current) {
await db.setNamespace('migrations', { nonce })
await db.setKey('app', 'migrations.nonce', nonce)
}
return
}
@ -31,6 +33,6 @@ export const runMigrations = async (): Promise<void> => {
}
logger.log(`${outdated} migration(s) performed.`)
} finally {
await db.setNamespace('migrations', { nonce })
await db.setKey('app', 'migrations.nonce', nonce)
}
}

29
src/migrations/migrations.js

@ -18,7 +18,7 @@ const migrations: Migration[] = [
const dbPath = db.getDBPath()
const legacyKeys = ['accounts', 'countervalues', 'settings', 'user']
const [accounts, countervalues, settings, user] = await Promise.all(
legacyKeys.map(key => getLegacyData(path.join(dbPath, `${key}.json`))),
legacyKeys.map(key => getFileData(dbPath, key)),
)
const appData = { user, settings, accounts, countervalues }
await db.setNamespace('app', appData)
@ -28,15 +28,33 @@ const migrations: Migration[] = [
const windowParams = await db.getKey('app', 'settings.window')
await db.setKey('app', 'settings.window', undefined)
await db.setNamespace('windowParams', windowParams)
await Promise.all(legacyKeys.map(key => fsUnlink(path.join(dbPath, `${key}.json`))))
await Promise.all(
legacyKeys.map(async key => {
try {
await fsUnlink(path.join(dbPath, `${key}.json`))
} catch (err) {} // eslint-disable-line
}),
)
},
},
{
doc: 'merging migrations into app.json',
run: async () => {
const migrations = await db.getNamespace('migrations')
await db.setKey('app', 'migrations', migrations)
const dbPath = db.getDBPath()
try {
await fsUnlink(path.resolve(dbPath, 'migrations.json'))
} catch (err) {} // eslint-disable-line
},
},
]
async function getLegacyData(filePath) {
async function getFileData(dbPath, fileName) {
const filePath = path.join(dbPath, `${fileName}.json`)
let finalData
const fileContent = await fsReadfile(filePath, 'utf-8')
try {
const fileContent = await fsReadfile(filePath, 'utf-8')
const { data } = JSON.parse(fileContent)
finalData = data
} catch (err) {
@ -45,7 +63,8 @@ async function getLegacyData(filePath) {
const buf = await fsReadfile(filePath)
return buf.toString('base64')
}
throw err
// will be stripped down by JSON.stringify
return undefined
}
return finalData
}

67
src/migrations/migrations.spec.js

@ -12,6 +12,7 @@ import db from 'helpers/db'
const rimraf = promisify(rimrafModule)
const fsReaddir = promisify(fs.readdir)
const fsReadFile = promisify(fs.readFile)
const tmpDir = os.tmpdir()
@ -20,14 +21,12 @@ const accountsTransform = {
set: encodeAccountsModel,
}
describe('migration 1', () => {
describe('from nonce 0', () => {
describe('without encryption', () => {
test('merging db files', async () => {
const dir = await extractMock('userdata_v1.0.5_mock-01')
let files
db.init(dir)
files = await fsReaddir(dir)
expect(files).toEqual([
await expectFiles(dir, [
'accounts.json',
'countervalues.json',
'migrations.json',
@ -35,8 +34,7 @@ describe('migration 1', () => {
'user.json',
])
await runMigrations()
files = await fsReaddir(dir)
expect(files).toEqual(['app.json', 'migrations.json', 'windowParams.json'])
await expectFiles(dir, ['app.json', 'windowParams.json'])
db.init(dir)
db.registerTransform('app', 'accounts', accountsTransform)
const accounts = await db.getKey('app', 'accounts')
@ -50,6 +48,40 @@ describe('migration 1', () => {
},
})
})
test('handle missing file without crash', async () => {
const dir = await extractMock('userdata_v1.0.5_mock-03-missing-file')
await expectFiles(dir, [
'countervalues.json',
'migrations.json',
'settings.json',
'user.json',
])
db.init(dir)
let err
try {
await runMigrations()
} catch (e) {
err = e
}
expect(err).toBeUndefined()
await expectFiles(dir, ['app.json', 'windowParams.json'])
})
test('handle where app.json is already present', async () => {
const dir = await extractMock('userdata_v1.0.5_mock-04-app-json-present')
await expectFiles(dir, [
'accounts.json',
'app.json',
'countervalues.json',
'migrations.json',
'settings.json',
'user.json',
])
db.init(dir)
await runMigrations()
await expectFiles(dir, ['app.json', 'windowParams.json'])
})
})
describe('with encryption', () => {
@ -59,8 +91,7 @@ describe('migration 1', () => {
db.registerTransform('app', 'accounts', accountsTransform)
await runMigrations()
await db.setEncryptionKey('app', 'accounts', 'passw0rd')
const files = await fsReaddir(dir)
expect(files).toEqual(['app.json', 'migrations.json', 'windowParams.json'])
await expectFiles(dir, ['app.json', 'windowParams.json'])
const accounts = await db.getKey('app', 'accounts')
expect(accounts.length).toBe(6)
expect(accounts[0].balance).toBeInstanceOf(BigNumber)
@ -79,6 +110,21 @@ describe('migration 1', () => {
})
})
describe('from nonce 1', () => {
test('merging migration file into app file', async () => {
const dir = await extractMock('userdata_v1.1.1_mock-01')
await expectFiles(dir, ['app.json', 'migrations.json', 'windowParams.json'])
const migrationsBefore = await fsReadFile(path.resolve(dir, 'migrations.json'), 'utf-8')
expect(migrationsBefore).toBe('{"data":{"nonce":1}}')
db.init(dir)
db.registerTransform('app', 'accounts', accountsTransform)
await runMigrations()
await expectFiles(dir, ['app.json', 'windowParams.json'])
const migrations = await db.getKey('app', 'migrations')
expect(migrations).toEqual({ nonce: 2 })
})
})
async function extractMock(mockName) {
const destDirectory = path.resolve(tmpDir, mockName)
const zipFilePath = path.resolve(__dirname, 'mocks', `${mockName}.zip`)
@ -94,3 +140,8 @@ function extractZip(zipFilePath, destDirectory) {
childProcess.on('error', reject)
})
}
async function expectFiles(dir, expectedFiles) {
const files = await fsReaddir(dir)
expect(files).toEqual(expectedFiles)
}

BIN
src/migrations/mocks/userdata_v1.0.5_mock-03-missing-file.zip

Binary file not shown.

BIN
src/migrations/mocks/userdata_v1.0.5_mock-04-app-json-present.zip

Binary file not shown.

BIN
src/migrations/mocks/userdata_v1.1.1_mock-01.zip

Binary file not shown.

12
src/sentry/install.js

@ -16,6 +16,18 @@ export default (Raven: any, shouldSendCallback: () => boolean, userId: string) =
},
environment: __DEV__ ? 'development' : 'production',
shouldSendCallback,
ignoreErrors: [
'status code 404',
'timeout',
'socket hang up',
'getaddrinfo ',
'ETIMEDOUT',
'ECONNRESET',
'ENETUNREACH',
'request timed out',
'NetworkDown',
'ERR_CONNECTION_TIMED_OUT',
],
autoBreadcrumbs: {
xhr: false, // it is track anonymously from logger
console: false, // we don't track because not anonymized

Loading…
Cancel
Save