copy-run.mts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { drizzle } from "drizzle-orm/libsql"
  2. import { eq } from "drizzle-orm"
  3. import pMap from "p-map"
  4. import { db as sourceDb } from "../src/db.js"
  5. import { schema } from "../src/schema.js"
  6. const copyRun = async (runId: number) => {
  7. const destDb = drizzle({
  8. schema,
  9. connection: { url: process.env.TURSO_CONNECTION_URL!, authToken: process.env.TURSO_AUTH_TOKEN! },
  10. })
  11. const run = await sourceDb.query.runs.findFirst({
  12. where: eq(schema.runs.id, runId),
  13. with: { taskMetrics: true },
  14. })
  15. if (!run) {
  16. throw new Error(`Run with ID ${runId} not found in source database`)
  17. }
  18. if (!run.taskMetrics) {
  19. throw new Error("Run is not completed")
  20. }
  21. console.log(`Copying run ${run.id}`)
  22. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  23. const { id: _, ...runTaskMetricsValues } = run.taskMetrics
  24. const [newRunTaskMetrics] = await destDb.insert(schema.taskMetrics).values(runTaskMetricsValues).returning()
  25. if (!newRunTaskMetrics) {
  26. throw new Error("Failed to insert run taskMetrics")
  27. }
  28. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  29. const { id: __, ...runValues } = run
  30. const [newRun] = await destDb
  31. .insert(schema.runs)
  32. .values({ ...runValues, taskMetricsId: newRunTaskMetrics.id })
  33. .returning()
  34. if (!newRun) {
  35. throw new Error("Failed to insert run")
  36. }
  37. const tasks = await sourceDb.query.tasks.findMany({
  38. where: eq(schema.tasks.runId, run.id),
  39. with: { taskMetrics: true },
  40. })
  41. console.log(`Copying ${tasks.length} tasks`)
  42. await pMap(
  43. tasks,
  44. async (task) => {
  45. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  46. const { id: _, ...newTaskMetricsValues } = task.taskMetrics || {
  47. duration: 0,
  48. tokensIn: 0,
  49. tokensOut: 0,
  50. tokensContext: 0,
  51. cacheWrites: 0,
  52. cacheReads: 0,
  53. cost: 0,
  54. createdAt: new Date(),
  55. }
  56. const [newTaskMetrics] = await destDb.insert(schema.taskMetrics).values(newTaskMetricsValues).returning()
  57. if (!newTaskMetrics) {
  58. throw new Error(`Failed to insert taskMetrics for task ${task.id}`)
  59. }
  60. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  61. const { id: __, ...newTaskValues } = task
  62. const [newTask] = await destDb
  63. .insert(schema.tasks)
  64. .values({ ...newTaskValues, runId: newRun.id, taskMetricsId: newTaskMetrics.id })
  65. .returning()
  66. if (!newTask) {
  67. throw new Error(`Failed to insert task ${task.id}`)
  68. }
  69. },
  70. { concurrency: 25 },
  71. )
  72. console.log(`\nSuccessfully copied run ${runId} with ${tasks.length} tasks`)
  73. }
  74. const main = async () => {
  75. const runId = parseInt(process.argv[2], 10)
  76. if (isNaN(runId)) {
  77. console.error("Run ID must be a number")
  78. process.exit(1)
  79. }
  80. try {
  81. await copyRun(runId)
  82. process.exit(0)
  83. } catch (error) {
  84. console.error(error)
  85. process.exit(1)
  86. }
  87. }
  88. main()