wrap database insertion into transactions

This commit is contained in:
2023-08-13 11:43:46 +02:00
parent 5e854191d7
commit c5051e5387
2 changed files with 160 additions and 129 deletions
+8 -13
View File
@@ -140,26 +140,21 @@ router.post(
} }
let attacker_loadout: number | undefined; let attacker_loadout: number | undefined;
let victim_loadout: number | undefined; let victim_loadout: number | undefined;
await db.transaction().execute(async (trx) => {
await checkUpdateOrCreatePlayer( await checkUpdateOrCreatePlayer(
{ id: attacker_id, name: attackerData.name }, { id: attacker_id, name: attackerData.name });
trx
);
await checkUpdateOrCreatePlayer( await checkUpdateOrCreatePlayer(
{ id: victim_id, name: victimData.name }, { id: victim_id, name: victimData.name }
trx
); );
await checkOrCreateWeapon(cause_of_death, trx); await checkOrCreateWeapon(cause_of_death);
await checkOrCreateWeapon(attackerData.current_weapon.id, trx); await checkOrCreateWeapon(attackerData.current_weapon.id);
await checkOrCreateWeapon(victimData.current_weapon.id, trx); await checkOrCreateWeapon(victimData.current_weapon.id);
await checkOrCreateLoadout(attackerData.loadout, trx).then( await checkOrCreateLoadout(attackerData.loadout).then(
(e) => (attacker_loadout = e) (e) => (attacker_loadout = e)
); );
await checkOrCreateLoadout(victimData.loadout, trx).then( await checkOrCreateLoadout(victimData.loadout).then(
(e) => (victim_loadout = e) (e) => (victim_loadout = e)
); );
});
if (attacker_loadout === undefined) { if (attacker_loadout === undefined) {
throw new Error("attacker_loadout is undefined"); throw new Error("attacker_loadout is undefined");
} }
+152 -116
View File
@@ -1,140 +1,176 @@
import { Kysely, Transaction } from 'kysely'; import { Kysely, Transaction } from "kysely";
import db from "./db"; import db from "./db";
import Database from './db/model'; import Database from "./db/model";
import { LoadoutKillData } from "./types"; import { LoadoutKillData } from "./types";
export async function checkUpdateOrCreatePlayer(data: { export async function checkUpdateOrCreatePlayer(data: {
id: number; id: number;
name: string; name: string;
}, trx : Kysely<Database> | Transaction<Database>) { }) {
const player = await trx await db
.selectFrom("ToneAPI_v3.player") .transaction()
.select(["player_name"]) .setIsolationLevel("serializable")
.where("player_id", "=", data.id) .execute(async (trx) => {
.executeTakeFirst(); const player = await trx
if (!player) { .selectFrom("ToneAPI_v3.player")
await trx .select(["player_name"])
.insertInto("ToneAPI_v3.player") .where("player_id", "=", data.id)
.values({ .executeTakeFirst();
player_id: data.id, if (!player) {
player_name: data.name, await trx
}) .insertInto("ToneAPI_v3.player")
.execute(); .values({
} else if (player.player_name != data.name) { player_id: data.id,
await trx player_name: data.name,
.updateTable("ToneAPI_v3.player") })
.set({ player_name: data.name }) .execute();
.where("ToneAPI_v3.player.player_id", "=", data.id) } else if (player.player_name != data.name) {
.execute(); await trx
} .updateTable("ToneAPI_v3.player")
.set({ player_name: data.name })
.where("ToneAPI_v3.player.player_id", "=", data.id)
.execute();
}
});
} }
export async function checkOrCreateWeapon(weapon_id: string, trx : Kysely<Database> | Transaction<Database>) { export async function checkOrCreateWeapon(weapon_id: string) {
const weapon = await trx await db
.selectFrom("ToneAPI_v3.weapon") .transaction()
.select("ToneAPI_v3.weapon.weapon_id") .setIsolationLevel("serializable")
.where("weapon_id", "=", weapon_id) .execute(async (trx) => {
.executeTakeFirst(); const weapon = await trx
if (!weapon) { .selectFrom("ToneAPI_v3.weapon")
await trx .select("ToneAPI_v3.weapon.weapon_id")
.insertInto("ToneAPI_v3.weapon") .where("weapon_id", "=", weapon_id)
.values({ .executeTakeFirst();
weapon_id, if (!weapon) {
}) await trx
.execute(); .insertInto("ToneAPI_v3.weapon")
} .values({
weapon_id,
})
.execute();
}
});
} }
export async function checkOrCreateWeaponMods(weapon_mods: { export async function checkOrCreateWeaponMods(weapon_mods: {
id: string; id: string;
mods: number; mods: number;
}, trx : Kysely<Database> | Transaction<Database>) { }) {
await checkOrCreateWeapon(weapon_mods.id, trx); await checkOrCreateWeapon(weapon_mods.id);
const weaponMods = await trx await db
.selectFrom("ToneAPI_v3.mods_on_weapon") .transaction()
.select("ToneAPI_v3.mods_on_weapon.mod_id") .setIsolationLevel("serializable")
.where("mod_id", "=", weapon_mods.mods) .execute(async (trx) => {
.where("weapon_id", "=", weapon_mods.id) const weaponMods = await trx
.executeTakeFirst(); .selectFrom("ToneAPI_v3.mods_on_weapon")
if (!weaponMods) { .select("ToneAPI_v3.mods_on_weapon.mod_id")
await trx .where("mod_id", "=", weapon_mods.mods)
.insertInto("ToneAPI_v3.mods_on_weapon") .where("weapon_id", "=", weapon_mods.id)
.values({ .executeTakeFirst();
mod_id: weapon_mods.mods, if (!weaponMods) {
weapon_id: weapon_mods.id, await trx
autogenerated: true, .insertInto("ToneAPI_v3.mods_on_weapon")
}) .values({
.execute(); mod_id: weapon_mods.mods,
} weapon_id: weapon_mods.id,
autogenerated: true,
})
.execute();
}
});
} }
export async function checkOrCreateTitan(titan_id: string | null, trx : Kysely<Database> | Transaction<Database>) { export async function checkOrCreateTitan(titan_id: string | null) {
if (titan_id == null) { if (titan_id == null) {
return; return;
} }
const titan = await trx await db
.selectFrom("ToneAPI_v3.titan_chassis") .transaction()
.select("ToneAPI_v3.titan_chassis.titan_id") .setIsolationLevel("serializable")
.where("titan_id", "=", titan_id) .execute(async (trx) => {
.executeTakeFirst(); const titan = await trx
if (!titan) { .selectFrom("ToneAPI_v3.titan_chassis")
await trx .select("ToneAPI_v3.titan_chassis.titan_id")
.insertInto("ToneAPI_v3.titan_chassis") .where("titan_id", "=", titan_id)
.values({ .executeTakeFirst();
titan_id, if (!titan) {
}) await trx
.execute(); .insertInto("ToneAPI_v3.titan_chassis")
} .values({
titan_id,
})
.execute();
}
});
} }
export async function checkOrCreateLoadout(loadoutData: LoadoutKillData, trx : Kysely<Database> | Transaction<Database>) { export async function checkOrCreateLoadout(loadoutData: LoadoutKillData) {
let loadout = await trx const loadout = await db
.selectFrom("ToneAPI_v3.loadout") .transaction()
.select("ToneAPI_v3.loadout.loadout_id") .setIsolationLevel("serializable")
.where("primary_weapon", "=", loadoutData.primary?.id ?? null) .execute(async (trx) => {
.where("primary_mod_id", "=", loadoutData.primary?.mods ?? null) let loadout = await trx
.where("secondary_weapon", "=", loadoutData.secondary?.id ?? null) .selectFrom("ToneAPI_v3.loadout")
.where("secondary_mod_id", "=", loadoutData.secondary?.mods ?? null) .select("ToneAPI_v3.loadout.loadout_id")
.where("anti_titan_weapon", "=", loadoutData.anti_titan?.id ?? null) .where("primary_weapon", "=", loadoutData.primary?.id ?? null)
.where("anti_titan_mod_id", "=", loadoutData.anti_titan?.mods ?? null) .where("primary_mod_id", "=", loadoutData.primary?.mods ?? null)
.where("ToneAPI_v3.loadout.ordnance", "=", loadoutData.ordnance?.id ?? null) .where("secondary_weapon", "=", loadoutData.secondary?.id ?? null)
.where("ToneAPI_v3.loadout.tactical", "=", loadoutData.tactical?.id ?? null) .where("secondary_mod_id", "=", loadoutData.secondary?.mods ?? null)
.where("ToneAPI_v3.loadout.pilot_passive_1", "=", loadoutData.passive1) .where("anti_titan_weapon", "=", loadoutData.anti_titan?.id ?? null)
.where("ToneAPI_v3.loadout.pilot_passive_2", "=", loadoutData.passive2) .where("anti_titan_mod_id", "=", loadoutData.anti_titan?.mods ?? null)
.where("ToneAPI_v3.loadout.titan_id", "=", loadoutData.titan) .where(
.executeTakeFirst(); "ToneAPI_v3.loadout.ordnance",
"=",
loadoutData.ordnance?.id ?? null
)
.where(
"ToneAPI_v3.loadout.tactical",
"=",
loadoutData.tactical?.id ?? null
)
.where("ToneAPI_v3.loadout.pilot_passive_1", "=", loadoutData.passive1)
.where("ToneAPI_v3.loadout.pilot_passive_2", "=", loadoutData.passive2)
.where("ToneAPI_v3.loadout.titan_id", "=", loadoutData.titan)
.executeTakeFirst();
if (!loadout) {
if (loadoutData.primary !== null) {
await checkOrCreateWeaponMods(loadoutData.primary);
}
if (loadoutData.secondary !== null) {
await checkOrCreateWeaponMods(loadoutData.secondary);
}
if (loadoutData.anti_titan !== null) {
await checkOrCreateWeaponMods(loadoutData.anti_titan);
}
if (loadoutData.ordnance !== null) {
await checkOrCreateWeapon(loadoutData.ordnance.id);
}
await checkOrCreateTitan(loadoutData.titan);
const result = await trx
.insertInto("ToneAPI_v3.loadout")
.values({
primary_weapon: loadoutData.primary?.id ?? null,
primary_mod_id: loadoutData.primary?.mods ?? null,
secondary_weapon: loadoutData.secondary?.id ?? null,
secondary_mod_id: loadoutData.secondary?.mods ?? null,
anti_titan_weapon: loadoutData.anti_titan?.id ?? null,
anti_titan_mod_id: loadoutData.anti_titan?.mods ?? null,
ordnance: loadoutData.ordnance?.id ?? null,
tactical: loadoutData.tactical?.id ?? null,
pilot_passive_1: loadoutData.passive1,
pilot_passive_2: loadoutData.passive2,
titan_id: loadoutData.titan,
})
.returning("ToneAPI_v3.loadout.loadout_id")
.executeTakeFirstOrThrow();
return result;
}
});
if (!loadout) { if (!loadout) {
if (loadoutData.primary !== null) { throw Error("loadout is undefined");
await checkOrCreateWeaponMods(loadoutData.primary, trx);
}
if (loadoutData.secondary !== null) {
await checkOrCreateWeaponMods(loadoutData.secondary, trx);
}
if (loadoutData.anti_titan !== null) {
await checkOrCreateWeaponMods(loadoutData.anti_titan, trx);
}
if (loadoutData.ordnance !== null) {
await checkOrCreateWeapon(loadoutData.ordnance.id, trx);
}
await checkOrCreateTitan(loadoutData.titan, trx);
const result = await trx
.insertInto("ToneAPI_v3.loadout")
.values({
primary_weapon: loadoutData.primary?.id ?? null,
primary_mod_id: loadoutData.primary?.mods ?? null,
secondary_weapon: loadoutData.secondary?.id ?? null,
secondary_mod_id: loadoutData.secondary?.mods ?? null,
anti_titan_weapon: loadoutData.anti_titan?.id ?? null,
anti_titan_mod_id: loadoutData.anti_titan?.mods ?? null,
ordnance: loadoutData.ordnance?.id ?? null,
tactical: loadoutData.tactical?.id ?? null,
pilot_passive_1: loadoutData.passive1,
pilot_passive_2: loadoutData.passive2,
titan_id: loadoutData.titan,
})
.returning("ToneAPI_v3.loadout.loadout_id")
.executeTakeFirstOrThrow();
return result.loadout_id;
} }
return loadout.loadout_id; return loadout.loadout_id;
} }