···11-import { eq, getTableColumns, gt, inArray, isNull, sql } from "drizzle-orm";
11+import { count, eq, getTableColumns, gt, inArray, isNull, sql } from "drizzle-orm";
22import { BatchItem } from "drizzle-orm/batch";
33import { DrizzleD1Database } from "drizzle-orm/d1";
44import flatten from "just-flatten-it";
55+import isEmpty from "just-is-empty";
66+import remove from "just-remove";
77+import { RepostInfo } from "../../classes/repost";
58import { mediaFiles, posts, repostCounts, reposts } from "../../db/app.schema";
69import { users } from "../../db/auth.schema";
710import { MAX_POSTED_LENGTH } from "../../limits";
···6669 .where(inArray(mediaFiles.fileName, flatten(userMedia))));
6770 }
68716969- const allPosts = await db.select({id: posts.uuid}).from(posts);
7272+ // clean up post data
7373+ const allPosts = await db.select({id: posts.uuid, info: posts.repostInfo}).from(posts);
7074 for (const post of allPosts) {
7171- const count = db.$count(reposts, eq(reposts.uuid, post.id));
7272- batchedQueries.push(db.insert(repostCounts).values({uuid: post.id,
7373- count: count}).onConflictDoNothing());
7575+ // Clean up repost counts
7676+ const countHelper = db.$count(reposts, eq(reposts.uuid, post.id));
7777+ batchedQueries.push(db.insert(repostCounts)
7878+ .values({uuid: post.id, count: countHelper})
7979+ .onConflictDoUpdate({target: repostCounts.uuid, set: {count: countHelper}}));
8080+8181+ // Clean up repost info of posts
8282+ // TODO: this doesn't work properly, and I accidentally obliterated my
8383+ // test data, and the bug is already fixed so there's no real reason to keep going with this
8484+ // it'll just be a silly quirk.
8585+ if (!isEmpty(post.info) && false) {
8686+ // this post has repost info
8787+ let repostInfoMap: Map<string, RepostInfo> = new Map();
8888+ post.info!.forEach((itm) => repostInfoMap.set(itm.guid, itm));
8989+ // Keep this too to make sure we worked on all objects, if anything is left over in this array, delete it.
9090+ // could probably do a where not exists but meh
9191+ let repostInfoGuids: string[] = post.info!.map((itm) => itm.guid);
9292+9393+ const repostInfoData = await db.select({id: reposts.scheduleGuid, count: count()}).from(reposts)
9494+ .where(inArray(reposts.scheduleGuid, repostInfoGuids)).all();
9595+9696+ for (const res of repostInfoData) {
9797+ // if the object is empty, remove from the map
9898+ if (res.count == 0) {
9999+ repostInfoMap.delete(res.id!);
100100+ }
101101+ // remove from this array
102102+ repostInfoGuids = remove(repostInfoGuids, [res.id]);
103103+ }
104104+ // delete any records that don't exist
105105+ repostInfoGuids.forEach((itm) => repostInfoMap.delete(itm));
106106+ const newRepostInfo = Array.from(repostInfoMap.values());
107107+ batchedQueries.push(db.update(posts).set({repostInfo: newRepostInfo}).where(eq(posts.uuid, post.id)));
108108+ }
74109 }
110110+75111 if (batchedQueries.length > 0)
76112 await db.batch(batchedQueries as BatchQuery);
77113};
+15-7
src/utils/dbQuery.ts
···390390 return {ok: false, msg: `Num of reposts rules for this post has exceeded the limit of ${MAX_REPOST_RULES_PER_POST} rules`};
391391 }
392392393393+ const repostInfoTimeStr = repostInfo.time.toISOString();
393394 // Check to see if we have an exact repost match.
394395 // If we do, do not update the repostInfo, as repost table will drop the duplicates for us anyways.
395395- const isNewInfoNotDuped = (el: RepostInfo) => {
396396- return el.time != repostInfo.time && el.count != repostInfo.count &&
397397- el.hours != repostInfo.hours;
396396+ const isNewInfoNotDuped = (el: any) => {
397397+ if (el.time == repostInfoTimeStr) {
398398+ if (el.count == repostInfo.count) {
399399+ return el.hours != repostInfo.hours;
400400+ }
401401+ }
402402+ return true;
398403 };
399404 if (newRepostInfo.every(isNewInfoNotDuped)) {
400405 newRepostInfo.push(repostInfo);
···403408 dbOperations.push(db.update(posts).set({repostInfo: newRepostInfo}).where(and(
404409 eq(posts.userId, userId), eq(posts.cid, cid))));
405410 }
406406-407411 } else {
408412 // Limit of post reposts on the user's account.
409413 const accountCurrentReposts = await db.$count(posts, and(eq(posts.userId, userId), eq(posts.isRepost, true)));
···452456 if (existingPost.isRepost && !isEmpty(content)) {
453457 dbOperations.push(db.update(posts).set({content: content!}).where(eq(posts.uuid, postUUID)));
454458 }
459459+460460+ // Because there could be conflicts that drop, run a count on the entire list and use the value from that
455461 const newCount = db.$count(reposts, eq(reposts.uuid, postUUID));
456456- dbOperations.push(db.update(repostCounts)
457457- .set({count: newCount})
458458- .where(eq(repostCounts.uuid, postUUID)));
462462+ // we also don't know if the repost count table has repost values for this item, so we should
463463+ // attempt to always insert and update if it already exists
464464+ dbOperations.push(db.insert(repostCounts)
465465+ .values({uuid: postUUID, count: newCount})
466466+ .onConflictDoUpdate({target: repostCounts.uuid, set: {count: newCount}}));
459467 }
460468 else {
461469 // this is a first time repost post, so we know there were no conflicts