[questions][feat] add encounters transaction for crud (#409)

* [questions][chore] refactor question queries

* [questions][chore] destructure values from input

* [questions][feat] add sorting

* [question][fix] fix frontend

* [questions][feat] add sorting

* [questions][feat] add sorting index

* [questions][chore] push migration file

* [questions][fix] fix ci issues

* [questions][fix] fix import errors

* [questions][feat] add encounters transaction for crud

* [questions][chore] fix import

* [questions][chore] update error handling

* [questions][feat] parallelize queries

* [questions][fix] update to use corrcet client

* Update questions-question-encounter-router.ts

* Update questions-question-encounter-router.ts

Co-authored-by: Jeff Sieu <jeffsy00@gmail.com>
pull/430/head
hpkoh 2 years ago committed by GitHub
parent fa5cf0c115
commit 352f8a03ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "QuestionsQuestion" ALTER COLUMN "lastSeenAt" DROP NOT NULL;

@ -0,0 +1,8 @@
-- AlterTable
ALTER TABLE "QuestionsQuestion" ADD COLUMN "contentSearch" TSVECTOR
GENERATED ALWAYS AS
(to_tsvector('english', coalesce(content, '')))
STORED;
-- CreateIndex
CREATE INDEX "QuestionsQuestion_contentSearch_idx" ON "QuestionsQuestion" USING GIN("contentSearch");

@ -0,0 +1,8 @@
-- DropIndex
DROP INDEX "QuestionsQuestion_contentSearch_idx";
-- AlterTable
ALTER TABLE "QuestionsQuestion" ALTER COLUMN "contentSearch" DROP DEFAULT;
-- CreateIndex
CREATE INDEX "QuestionsQuestion_contentSearch_idx" ON "QuestionsQuestion"("contentSearch");

@ -1,7 +1,8 @@
// Refer to the Prisma schema docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
provider = "prisma-client-js"
previewFeatures = ["interactiveTransactions"]
}
datasource db {
@ -402,7 +403,7 @@ model QuestionsQuestion {
userId String?
content String @db.Text
questionType QuestionsQuestionType
lastSeenAt DateTime
lastSeenAt DateTime?
upvotes Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@ -4,6 +4,8 @@ import { TRPCError } from '@trpc/server';
import { createProtectedRouter } from './context';
import type { AggregatedQuestionEncounter } from '~/types/questions';
import { SortOrder } from '~/types/questions.d';
export const questionsQuestionEncounterRouter = createProtectedRouter()
.query('getAggregatedEncounters', {
@ -68,11 +70,40 @@ export const questionsQuestionEncounterRouter = createProtectedRouter()
async resolve({ ctx, input }) {
const userId = ctx.session?.user?.id;
return await ctx.prisma.questionsQuestionEncounter.create({
data: {
...input,
userId,
},
return await ctx.prisma.$transaction(async (tx) => {
const [questionToUpdate, questionEncounterCreated] = await Promise.all([
tx.questionsQuestion.findUnique({
where: {
id: input.questionId,
},
}),
tx.questionsQuestionEncounter.create({
data: {
...input,
userId,
},
})
]);
if (questionToUpdate === null) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'Question does not exist',
});
}
if (!questionToUpdate.lastSeenAt || questionToUpdate.lastSeenAt < input.seenAt) {
await tx.questionsQuestion.update({
data: {
lastSeenAt : input.seenAt,
},
where: {
id: input.questionId,
},
});
}
return questionEncounterCreated;
});
},
})
@ -101,14 +132,48 @@ export const questionsQuestionEncounterRouter = createProtectedRouter()
});
}
return await ctx.prisma.questionsQuestionEncounter.update({
data: {
...input,
},
where: {
id: input.id,
},
return await ctx.prisma.$transaction(async (tx) => {
const [questionToUpdate, questionEncounterUpdated] = await Promise.all([
tx.questionsQuestion.findUnique({
where: {
id: questionEncounterToUpdate.questionId,
},
}),
tx.questionsQuestionEncounter.update({
data: {
...input,
},
where: {
id: input.id,
},
})
]);
if (questionToUpdate!.lastSeenAt === questionEncounterToUpdate.seenAt) {
const latestEncounter = await ctx.prisma.questionsQuestionEncounter.findFirst({
orderBy: {
seenAt: SortOrder.DESC,
},
where: {
questionId: questionToUpdate!.id,
},
});
await tx.questionsQuestion.update({
data: {
lastSeenAt : latestEncounter!.seenAt,
},
where: {
id: questionToUpdate!.id,
},
});
}
return questionEncounterUpdated;
});
},
})
.mutation('delete', {
@ -132,10 +197,43 @@ export const questionsQuestionEncounterRouter = createProtectedRouter()
});
}
return await ctx.prisma.questionsQuestionEncounter.delete({
where: {
id: input.id,
},
return await ctx.prisma.$transaction(async (tx) => {
const [questionToUpdate, questionEncounterDeleted] = await Promise.all([
tx.questionsQuestion.findUnique({
where: {
id: questionEncounterToDelete.questionId,
},
}),
tx.questionsQuestionEncounter.delete({
where: {
id: input.id,
},
})
]);
if (questionToUpdate!.lastSeenAt === questionEncounterToDelete.seenAt) {
const latestEncounter = await ctx.prisma.questionsQuestionEncounter.findFirst({
orderBy: {
seenAt: SortOrder.DESC,
},
where: {
questionId: questionToUpdate!.id,
},
});
const lastSeenVal = latestEncounter ? latestEncounter!.seenAt : null;
await tx.questionsQuestion.update({
data: {
lastSeenAt : lastSeenVal,
},
where: {
id: questionToUpdate!.id,
},
});
}
return questionEncounterDeleted;
});
},
});

Loading…
Cancel
Save