-
This may not be the best forum to ask a question on implementation but I couldn't find a better place so I apologize in advance if it's misguided. I'm looking at using umzug for lazily running migrations once per player. I want to be able to add migrations, and when a player connects to my server, I want to run a migration for them if we haven't already. My initial thought is we need to be able to dynamically modify the params that get passed to the list of migrations as a function that returns the connected user's id and then run the migrations against that (injecting into WHERE clauses), but how can we mark the migration as having ran for that player and never run them again? Do I need a custom storage method to store this info in a separate db table? Any guidance on how to implement this with umzug would be extremely helpful. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Interesting use case! Yes, I'd think you'll need a custom storage. They're not difficult to write. I don't know what your stack is, but here's a working example I threw together with const umzug = require("[email protected]")
const pgMem = require('pg-mem')
const db = pgMem.newDb()
db.public.query('create table migrations(player_id text, name text)')
class PlayerStorage {
constructor(playerId) {
this.playerId = playerId
}
async executed() {
const result = db.public.query(`
select name from migrations where player_id = '${this.playerId}'`
)
return result.rows.map(r => r.name)
}
async logMigration({name}) {
db.public.query(
`insert into migrations (player_id, name) values ('${this.playerId}', '${name}')`
)
}
async unlogMigration({name}) {
db.public.query(
`delete from migrations where player_id = '${this.playerId}' and name = '${name}'`
)
}
}
const getMigrator = playerId => {
return new umzug.Umzug({
migrations: [
{
name: 'm1',
up: async ({ context }) => console.log('m1 running for ' + context.playerId),
down: async () => {}
},
{
name: 'm2',
up: async ({ context }) => console.log('m2 running for ' + context.playerId),
down: async () => {}
},
],
context: { playerId }, // you could pass `db` in here, assuming your migrations interact with the db
storage: new PlayerStorage(playerId),
logger: console,
})
}
(async () => {
await getMigrator('player1').up()
console.log('____')
await getMigrator('player1').up()
console.log('____')
await getMigrator('player2').up()
})() If you run this (say by pasting into https://npm.runkit.com/umzug, where I tried it out), you'll see that no migrations are run for the second time It's hard to give more guidance without knowing more about the context. But maybe the important pieces of the example above are:
|
Beta Was this translation helpful? Give feedback.
Interesting use case! Yes, I'd think you'll need a custom storage. They're not difficult to write. I don't know what your stack is, but here's a working example I threw together with
pg-mem
as a pseudo-db. You can swap it out with whatever you want though: