20241223103044_visits_user_id.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. /**
  2. * @param { import("knex").Knex } knex
  3. * @returns { Promise<void> }
  4. */
  5. async function up(knex) {
  6. const hasUserIDColumn = await knex.schema.hasColumn("visits", "user_id");
  7. if (hasUserIDColumn) return;
  8. await knex.schema.alterTable("visits", function(table) {
  9. table
  10. .integer("user_id")
  11. .unsigned();
  12. table
  13. .foreign("user_id")
  14. .references("id")
  15. .inTable("users")
  16. .onDelete("CASCADE")
  17. .withKeyName("visits_user_id_foreign");
  18. });
  19. const [{ count }] = await knex("visits").count("* as count");
  20. const count_number = parseInt(count);
  21. if (Number.isNaN(count_number) || count_number === 0) return;
  22. if (count_number < 1_000_000) {
  23. const last_visit = await knex("visits").orderBy("id", "desc").first();
  24. const size = 100_000;
  25. const loops = Math.floor(last_visit.id / size) + 1;
  26. await Promise.all(
  27. new Array(loops).fill(null).map((_, i) => {
  28. return knex("visits")
  29. .fromRaw(knex.raw("visits v"))
  30. .update({ user_id: knex.ref("links.user_id") })
  31. .updateFrom("links")
  32. .where("links.id", knex.ref("link_id"))
  33. .andWhereBetween("v.id", [i * size, (i * size) + size]);
  34. })
  35. );
  36. } else {
  37. console.warn(
  38. "MIGRATION WARN:" +
  39. "Skipped adding user_id to visits due to high volume of visits and the potential risk of locking the database.\n" +
  40. "Please refer to Kutt's migration guide for more information."
  41. );
  42. }
  43. };
  44. /**
  45. * @param { import("knex").Knex } knex
  46. * @returns { Promise<void> }
  47. */
  48. async function down(knex) {};
  49. module.exports = {
  50. up,
  51. down,
  52. }