This is createMigrate code allowing to async migrations.
This could potentially be patched, but this code will have more responsibilities in near future (D7668), so it's better to maintain this that way.
Depends on D7289
Differential D7658
[web-db] implement asynchronous `redux-persist` migrations kamil on Apr 27 2023, 6:58 AM. Authored by Tags None Referenced Files
Details This is createMigrate code allowing to async migrations. This could potentially be patched, but this code will have more responsibilities in near future (D7668), so it's better to maintain this that way. Depends on D7289
Tests could not be added directly, this function will read something from local storage (D7668) - that being said this test will fail, but code I used: // @flow import { creatAsyncMigrate } from './create-async-migrate.js'; describe('async redux migrations', () => { it('should run migrations with async functions', async () => { const persistedState = { oldKey: 'oldKeyValue', _persist: { version: 1, rehydrated: false, }, }; const asyncMigrations = { [1]: async state => { return { ...state, oldKey: 'oldKeyValue', }; }, // needs to run [2]: async state => { return { ...state, newKey: 'newKeyValue', }; }, // needs to run [3]: async state => { return { ...state, oldKey: 'oldKeyUpdated', }; }, }; const migrate = creatAsyncMigrate(asyncMigrations, { debug: true, }); const currentVersion = 3; const migratedState = await migrate(persistedState, currentVersion); expect(migratedState).toEqual({ oldKey: 'oldKeyUpdated', newKey: 'newKeyValue', _persist: { version: 1, rehydrated: false, }, }); }); it(`should do nothing when inboundVersion and currentVersion match`, async () => { const persistedState = { oldKey: 'oldKeyValue', _persist: { version: 3, rehydrated: false, }, }; const asyncMigrations = { [1]: async state => { return { ...state, oldKey: 'oldKeyValue', }; }, [2]: async state => { return { ...state, newKey: 'newKeyValue', }; }, [3]: async state => { return { ...state, oldKey: 'oldKeyUpdated', }; }, }; const migrate = creatAsyncMigrate(asyncMigrations, { debug: true, }); const currentVersion = 3; const migratedState = await migrate(persistedState, currentVersion); expect(migratedState).toEqual(persistedState); }); it(`should return undefined for undefined persisted state`, async () => { const persistedState = undefined; const asyncMigrations = { [1]: async state => { return { ...state, oldKey: 'oldKeyValue', }; }, }; const migrate = creatAsyncMigrate(asyncMigrations, { debug: true, }); const currentVersion = 1; const migratedState = await migrate(persistedState, currentVersion); expect(migratedState).toBeUndefined(); }); });
Diff Detail
Event Timeline
Comment Actions @tomek questions you added are valid but those are questions to the redux-persist author. I wanted to copy-paste code from source code to preserve old logic, as this returns function which will be used inside redux-persist logic. I only updated from the sync function which returns a promise - to implicitly return a promise from the async function (which will allow us to put await before any migration). Any additional modification could cause some undefined behaviors, but if you feel strongly about investigating, I can try to improve this code in our use case.
Comment Actions Ah, that makes sense! But now it brings more serious issue: we shouldn't just copy and paste code from a library. Ideally, we would like to avoid modification and e.g. wrap code with our logic. If that's not possible, we can e.g. patch the library. If using this code directly is the only option, we should rewrite this code using the original one as an inspiration. Comment Actions Due to complexity and some legacy problems patching the library was too hard. I deeply analyzed function from redux-persist and based on this knowledge (arguments, return type, when can throw, what should do) I provided my own implementation, using existing one only as an inspiration.
|