Merge pull request #11 from atridadl/dev

1.1.3
🚧 Small optimizations for queries. Votes should be less "heavy" on DB calls...
This commit is contained in:
Atridad Lahiji 2023-06-04 15:48:43 -06:00 committed by GitHub
commit 818a7567b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 123 additions and 109 deletions

View file

@ -1,6 +1,6 @@
{
"name": "sprintpadawan",
"version": "1.1.2",
"version": "1.1.3",
"description": "Plan. Sprint. Repeat.",
"private": true,
"scripts": {
@ -18,10 +18,10 @@
"@prisma/client": "4.15.0",
"@tailwindcss/typography": "^0.5.9",
"@tanstack/react-query": "^4.29.12",
"@trpc/client": "10.29.0",
"@trpc/next": "10.29.0",
"@trpc/react-query": "10.29.0",
"@trpc/server": "10.29.0",
"@trpc/client": "10.29.1",
"@trpc/next": "10.29.1",
"@trpc/react-query": "10.29.1",
"@trpc/server": "10.29.1",
"ably": "^1.2.40",
"autoprefixer": "^10.4.14",
"fms-ts": "^0.1.7",
@ -47,7 +47,7 @@
"@types/react-dom": "^18.2.4",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"daisyui": "^3.0.1",
"daisyui": "^3.0.3",
"eslint": "^8.42.0",
"eslint-config-next": "^13.4.4",
"next-pwa": "^5.6.0",

86
pnpm-lock.yaml generated
View file

@ -21,17 +21,17 @@ dependencies:
specifier: ^4.29.12
version: 4.29.12(react-dom@18.2.0)(react@18.2.0)
'@trpc/client':
specifier: 10.29.0
version: 10.29.0(@trpc/server@10.29.0)
specifier: 10.29.1
version: 10.29.1(@trpc/server@10.29.1)
'@trpc/next':
specifier: 10.29.0
version: 10.29.0(@tanstack/react-query@4.29.12)(@trpc/client@10.29.0)(@trpc/react-query@10.29.0)(@trpc/server@10.29.0)(next@13.4.4)(react-dom@18.2.0)(react@18.2.0)
specifier: 10.29.1
version: 10.29.1(@tanstack/react-query@4.29.12)(@trpc/client@10.29.1)(@trpc/react-query@10.29.1)(@trpc/server@10.29.1)(next@13.4.4)(react-dom@18.2.0)(react@18.2.0)
'@trpc/react-query':
specifier: 10.29.0
version: 10.29.0(@tanstack/react-query@4.29.12)(@trpc/client@10.29.0)(@trpc/server@10.29.0)(react-dom@18.2.0)(react@18.2.0)
specifier: 10.29.1
version: 10.29.1(@tanstack/react-query@4.29.12)(@trpc/client@10.29.1)(@trpc/server@10.29.1)(react-dom@18.2.0)(react@18.2.0)
'@trpc/server':
specifier: 10.29.0
version: 10.29.0
specifier: 10.29.1
version: 10.29.1
ably:
specifier: ^1.2.40
version: 1.2.40
@ -104,8 +104,8 @@ devDependencies:
specifier: ^5.59.8
version: 5.59.8(eslint@8.42.0)(typescript@5.1.3)
daisyui:
specifier: ^3.0.1
version: 3.0.1(postcss@8.4.24)
specifier: ^3.0.3
version: 3.0.3(postcss@8.4.24)
eslint:
specifier: ^8.42.0
version: 8.42.0
@ -462,8 +462,8 @@ packages:
'@babel/plugin-transform-optional-chaining': 7.22.3(@babel/core@7.22.1)
dev: true
/@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.22.1):
resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==}
/@babel/plugin-proposal-private-property-in-object@7.21.10(@babel/core@7.22.1):
resolution: {integrity: sha512-3YybmT8FN4sZFXp0kTr9Gbu90wAIhC3feNung+qcRQ1wALGoSHgOz1c+fR3ZLGZ0LXqIpYmtE6Faua6tMDarUg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@ -1226,7 +1226,7 @@ packages:
'@babel/helper-validator-option': 7.21.0
'@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.22.1)
'@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.3(@babel/core@7.22.1)
'@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.22.1)
'@babel/plugin-proposal-private-property-in-object': 7.21.10(@babel/core@7.22.1)
'@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.1)
'@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.1)
'@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.1)
@ -1725,53 +1725,53 @@ packages:
use-sync-external-store: 1.2.0(react@18.2.0)
dev: false
/@trpc/client@10.29.0(@trpc/server@10.29.0):
resolution: {integrity: sha512-2a5+xJarQaQNnmMHP73LdShNPFoXwQhUBKEK7zs/Fqy75kYKtwkBnbPPef4nJpAdG3JW0kbm8vbZcQ8T91oG1A==}
/@trpc/client@10.29.1(@trpc/server@10.29.1):
resolution: {integrity: sha512-+9Tifg6dtKsYLsqOW0wizqc3iILAkXxn16pyYAeMDPlulPEqNvnI85GDJ0zJOJLIkQnQefkRbtCmtDxLNtV9Eg==}
peerDependencies:
'@trpc/server': 10.29.0
'@trpc/server': 10.29.1
dependencies:
'@trpc/server': 10.29.0
'@trpc/server': 10.29.1
dev: false
/@trpc/next@10.29.0(@tanstack/react-query@4.29.12)(@trpc/client@10.29.0)(@trpc/react-query@10.29.0)(@trpc/server@10.29.0)(next@13.4.4)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-z1ONRx522QnDdy0ejBnwB7MiTMQ7CGN4CYDi7KJmmkhk+g7xf3H3gttgN1dYR//faFHEwAtRKBwbiUSbRguQYA==}
/@trpc/next@10.29.1(@tanstack/react-query@4.29.12)(@trpc/client@10.29.1)(@trpc/react-query@10.29.1)(@trpc/server@10.29.1)(next@13.4.4)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-2RNnct2T+k5yExSy748Lv5IDPAKEvx/QKoAJIBo8FqRem3ypW6ZpRTxillyE+vyD8QVRtMaD4v0dnPaFeRhJ3g==}
peerDependencies:
'@tanstack/react-query': ^4.18.0
'@trpc/client': 10.29.0
'@trpc/react-query': 10.29.0
'@trpc/server': 10.29.0
'@trpc/client': 10.29.1
'@trpc/react-query': 10.29.1
'@trpc/server': 10.29.1
next: '*'
react: '>=16.8.0'
react-dom: '>=16.8.0'
dependencies:
'@tanstack/react-query': 4.29.12(react-dom@18.2.0)(react@18.2.0)
'@trpc/client': 10.29.0(@trpc/server@10.29.0)
'@trpc/react-query': 10.29.0(@tanstack/react-query@4.29.12)(@trpc/client@10.29.0)(@trpc/server@10.29.0)(react-dom@18.2.0)(react@18.2.0)
'@trpc/server': 10.29.0
'@trpc/client': 10.29.1(@trpc/server@10.29.1)
'@trpc/react-query': 10.29.1(@tanstack/react-query@4.29.12)(@trpc/client@10.29.1)(@trpc/server@10.29.1)(react-dom@18.2.0)(react@18.2.0)
'@trpc/server': 10.29.1
next: 13.4.4(@babel/core@7.22.1)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
react-ssr-prepass: 1.5.0(react@18.2.0)
dev: false
/@trpc/react-query@10.29.0(@tanstack/react-query@4.29.12)(@trpc/client@10.29.0)(@trpc/server@10.29.0)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-VwzPf8PX8aUexPVgS7KJd2f4jsQXCxz9E60Zn55UpCRe5nwmVK5jQfJAcMbHyPDmC+3D5lzM7+iQoIkw+mMcmA==}
/@trpc/react-query@10.29.1(@tanstack/react-query@4.29.12)(@trpc/client@10.29.1)(@trpc/server@10.29.1)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-yWsce8euPSVtn3SeBKXxLmq607/sqyIez7pgMOhMBKehRNdZzrGp3MhjmRwim+IUKLrw71kUgsw7w6uT5FPB0g==}
peerDependencies:
'@tanstack/react-query': ^4.18.0
'@trpc/client': 10.29.0
'@trpc/server': 10.29.0
'@trpc/client': 10.29.1
'@trpc/server': 10.29.1
react: '>=16.8.0'
react-dom: '>=16.8.0'
dependencies:
'@tanstack/react-query': 4.29.12(react-dom@18.2.0)(react@18.2.0)
'@trpc/client': 10.29.0(@trpc/server@10.29.0)
'@trpc/server': 10.29.0
'@trpc/client': 10.29.1(@trpc/server@10.29.1)
'@trpc/server': 10.29.1
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@trpc/server@10.29.0:
resolution: {integrity: sha512-a/ZAc/TT6Cz0L/Ii4asJrgyclnNl/SiNeN+dZPVYJZlw7okeTdbHI1vePcQb/3+0GpwVQeSEkZpVpSgekH9YZQ==}
/@trpc/server@10.29.1:
resolution: {integrity: sha512-kNXgMh5ya+awuz2tB4eIyVrRs7nVtqGXwSGabzH3l5ZLWz7rbKJquOJ7h6bjvIfWUpaFG62HJNWxxGUtXCRgRw==}
dev: false
/@types/cacheable-request@6.0.3:
@ -2338,7 +2338,7 @@ packages:
postcss: ^8.1.0
dependencies:
browserslist: 4.21.7
caniuse-lite: 1.0.30001492
caniuse-lite: 1.0.30001494
fraction.js: 4.2.0
normalize-range: 0.1.2
picocolors: 1.0.0
@ -2483,7 +2483,7 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001492
caniuse-lite: 1.0.30001494
electron-to-chromium: 1.4.419
node-releases: 2.0.12
update-browserslist-db: 1.0.11(browserslist@4.21.7)
@ -2551,8 +2551,8 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
/caniuse-lite@1.0.30001492:
resolution: {integrity: sha512-2efF8SAZwgAX1FJr87KWhvuJxnGJKOnctQa8xLOskAXNXq8oiuqgl6u1kk3fFpsp3GgvzlRjiK1sl63hNtFADw==}
/caniuse-lite@1.0.30001494:
resolution: {integrity: sha512-sY2B5Qyl46ZzfYDegrl8GBCzdawSLT4ThM9b9F+aDYUrAG2zCOyMbd2Tq34mS1g4ZKBfjRlzOohQMxx28x6wJg==}
/chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
@ -2690,7 +2690,7 @@ packages:
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
engines: {node: '>=12.13'}
dependencies:
is-what: 4.1.12
is-what: 4.1.13
dev: false
/core-js-compat@3.30.2:
@ -2729,8 +2729,8 @@ packages:
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
dev: true
/daisyui@3.0.1(postcss@8.4.24):
resolution: {integrity: sha512-UJQ90ffDRgIEsDYdYpsFuEwc1fDXejm64oK2JFNNgmUyxbOgYveM1EphCLhxPj85nNGybBoHWx87Kua+24iT8w==}
/daisyui@3.0.3(postcss@8.4.24):
resolution: {integrity: sha512-RSbXsEBj2LonvjOKEI0I64F5xFJrFrthPgxRNeAZKmACQ3NoIoP45lO6UXLW3bm8PVOUGpKf1Br2SWwc1NqnHQ==}
peerDependencies:
postcss: ^8
dependencies:
@ -4027,8 +4027,8 @@ packages:
get-intrinsic: 1.2.1
dev: true
/is-what@4.1.12:
resolution: {integrity: sha512-w7JwFt3gIzbzpp+I//2Ov2UeTGgKM10PxJRD6yf7yGruT3415CdT8TDR6F9/mBAakZKsIaysQVVvxryctQUbnw==}
/is-what@4.1.13:
resolution: {integrity: sha512-Aoe8pT24sWzyoO0S2PTDyutGp9l7qYHyFtzYlC8hMLshyqV/minljBANT4f2hiS5OxnWvcKMiA5io+VaLMJ1oA==}
engines: {node: '>=12.13'}
dev: false
@ -4474,7 +4474,7 @@ packages:
'@next/env': 13.4.4
'@swc/helpers': 0.5.1
busboy: 1.6.0
caniuse-lite: 1.0.30001492
caniuse-lite: 1.0.30001494
postcss: 8.4.14
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)

View file

@ -1,7 +1,7 @@
const Loading: React.FC = () => {
return (
<div
className="inline-block h-12 w-12 rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]"
className="inline-block h-12 w-12 animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]"
role="status"
>
<span className="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]">

View file

@ -20,7 +20,6 @@ import {
IoDownloadOutline,
} from "react-icons/io5";
import type { Prisma, Vote } from "@prisma/client";
import { configureAbly, useChannel, usePresence } from "@ably-labs/react-hooks";
import type { PresenceItem } from "~/utils/types";
import { env } from "~/env.mjs";
@ -49,18 +48,17 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
};
};
interface ExtendedVote extends Vote {
id: string;
userId: string;
roomId: string;
owner: {
image: string | null;
_count: Prisma.UserCountOutputType;
name: string | null;
email: string | null;
};
value: string;
}
// interface ExtendedVote extends Vote {
// value: string;
// room: typeof Room;
// id: string;
// createdAt: Date;
// userId: string;
// owner: {
// name: string | null;
// };
// roomId: string;
// }
const Room: NextPage = () => {
return (
@ -89,6 +87,9 @@ const RoomBody: React.FC = () => {
const { data: roomFromDb, refetch: refetchRoomFromDb } =
api.room.get.useQuery({ id: roomId });
const { data: votesFromDb, refetch: refetchVotesFromDb } =
api.vote.getAllByRoomId.useQuery({ roomId });
const setVoteInDb = api.vote.set.useMutation({});
const setRoomInDb = api.room.set.useMutation({});
@ -104,7 +105,14 @@ const RoomBody: React.FC = () => {
{
channelName: `${env.NEXT_PUBLIC_APP_ENV}-${roomId}`,
},
() => void refetchRoomFromDb()
({ name }) => {
if (name === "ROOM_UPDATE") {
void refetchVotesFromDb();
void refetchRoomFromDb();
} else if (name === "VOTE_UPDATE") {
void refetchVotesFromDb();
}
}
);
const [presenceData] = usePresence<PresenceItem>(
@ -148,8 +156,8 @@ const RoomBody: React.FC = () => {
const getVoteForCurrentUser = () => {
if (roomFromDb && sessionData) {
return (
roomFromDb &&
roomFromDb.votes.find((vote) => vote.userId === sessionData.user.id)
votesFromDb &&
votesFromDb.find((vote) => vote.userId === sessionData.user.id)
);
} else {
return null;
@ -179,7 +187,7 @@ const RoomBody: React.FC = () => {
};
const downloadLogs = () => {
if (roomFromDb) {
if (roomFromDb && votesFromDb) {
// const element = document.createElement("a");
const jsonObject = roomFromDb?.logs
.map((item) => {
@ -197,7 +205,7 @@ const RoomBody: React.FC = () => {
userId: roomFromDb.owner.id,
roomId: roomFromDb.id,
scale: roomScale,
votes: roomFromDb.votes.map((vote) => {
votes: votesFromDb.map((vote) => {
return {
name: vote.owner.name,
value: vote.value,
@ -224,10 +232,10 @@ const RoomBody: React.FC = () => {
const voteString = (
visible: boolean,
votes: ExtendedVote[],
votes: typeof votesFromDb,
presenceItem: PresenceItem
) => {
const matchedVote = votes.find(
const matchedVote = votes?.find(
(vote) => vote.userId === presenceItem.client_id
);
@ -327,9 +335,10 @@ const RoomBody: React.FC = () => {
</p>
{roomFromDb &&
votesFromDb &&
voteString(
roomFromDb.visible,
roomFromDb.votes,
votesFromDb,
presenceItem.data
)}
</li>
@ -427,7 +436,7 @@ const RoomBody: React.FC = () => {
false,
true,
roomFromDb.storyName === storyNameText ||
roomFromDb.votes.length === 0
votesFromDb?.length === 0
? false
: true
)
@ -440,7 +449,7 @@ const RoomBody: React.FC = () => {
}
>
{roomFromDb.storyName === storyNameText ||
roomFromDb.votes.length === 0 ? (
votesFromDb?.length === 0 ? (
<>
<IoReloadOutline className="text-xl mr-1" /> Reset
</>
@ -452,19 +461,20 @@ const RoomBody: React.FC = () => {
</button>
</div>
{(roomFromDb.logs.length > 0 ||
roomFromDb.votes.length > 0) && (
<div>
<button
onClick={() => downloadLogs()}
className="btn btn-primary inline-flex hover:animate-pulse"
>
<>
<IoDownloadOutline className="text-xl" />
</>
</button>
</div>
)}
{votesFromDb &&
(roomFromDb.logs.length > 0 ||
votesFromDb.length > 0) && (
<div>
<button
onClick={() => downloadLogs()}
className="btn btn-primary inline-flex hover:animate-pulse"
>
<>
<IoDownloadOutline className="text-xl" />
</>
</button>
</div>
)}
</div>
</div>
</div>

View file

@ -74,23 +74,6 @@ export const roomRouter = createTRPCRouter({
storyName: true,
visible: true,
scale: true,
votes: {
select: {
id: true,
value: true,
roomId: true,
userId: true,
createdAt: true,
owner: {
select: {
_count: true,
name: true,
image: true,
email: true,
},
},
},
},
owner: true,
},
});

View file

@ -9,7 +9,7 @@ import {
deleteFromCache,
} from "redicache-ts";
import { env } from "~/env.mjs";
import type { Vote } from "@prisma/client";
import type { Room } from "@prisma/client";
const client = cacheClient(env.REDIS_URL);
@ -40,11 +40,19 @@ export const voteRouter = createTRPCRouter({
getAllByRoomId: protectedProcedure
.input(z.object({ roomId: z.string() }))
.query(async ({ ctx, input }) => {
const cachedResult = await fetchFromCache<Vote[]>(
client,
env.APP_ENV,
`kv_votes_${input.roomId}`
);
const cachedResult = await fetchFromCache<
{
value: string;
room: Room;
id: string;
createdAt: Date;
userId: string;
owner: {
name: string | null;
};
roomId: string;
}[]
>(client, env.APP_ENV, `kv_votes_${input.roomId}`);
if (cachedResult) {
return cachedResult;
@ -53,6 +61,19 @@ export const voteRouter = createTRPCRouter({
where: {
roomId: input.roomId,
},
select: {
id: true,
createdAt: true,
owner: {
select: {
name: true,
},
},
room: true,
roomId: true,
userId: true,
value: true,
},
});
await writeToCache(