Merge pull request #57 from atridadl/dev

3.1.8
🐛 Fixed a bug where toggling vote visibility would also set any unsaved changes to the room name and scale
🚧 Optimized real-time message passing
This commit is contained in:
Atridad Lahiji 2023-10-22 23:15:04 -06:00 committed by GitHub
commit eec5e61d03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 69 deletions

View file

@ -39,10 +39,7 @@ const VoteUI = () => {
const queryClient = useQueryClient();
const {
data: roomFromDb,
isLoading: roomFromDbLoading,
} = useQuery({
const { data: roomFromDb, isLoading: roomFromDbLoading } = useQuery({
queryKey: ["room"],
queryFn: getRoomHandler,
retry: false,
@ -83,7 +80,7 @@ const VoteUI = () => {
},
// If the mutation fails,
// use the context returned from onMutate to roll back
onError: (err, newTodo, context) => {
onError: (err, newVote, context) => {
queryClient.setQueryData(["votes"], context?.previousVotes);
},
// Always refetch after error or success:
@ -116,9 +113,9 @@ const VoteUI = () => {
id: old?.id,
userId: old?.userId,
logs: old?.logs,
storyName: storyNameText,
storyName: data.reset ? storyNameText : old.storyName,
visible: data.visible,
scale: roomScale,
scale: data.reset ? roomScale : old.scale,
reset: data.reset,
log: data.log,
}
@ -130,7 +127,7 @@ const VoteUI = () => {
},
// If the mutation fails,
// use the context returned from onMutate to roll back
onError: (err, newTodo, context) => {
onError: (err, newRoom, context) => {
queryClient.setQueryData(["room"], context?.previousRoom);
},
// Always refetch after error or success:
@ -307,11 +304,8 @@ const VoteUI = () => {
if (roomFromDb) {
setStoryNameText(roomFromDb.storyName || "");
setRoomScale(roomFromDb.scale || "ERROR");
} else {
void getRoomHandler();
void getVotesHandler();
}
}, [roomFromDb, roomId, user]);
}, [roomFromDb]);
// UI
// =================================

View file

@ -21,3 +21,26 @@ export const publishToChannel = async (
}
);
};
export const publishToMultipleChannels = async (
channels: string[],
events: EventType[],
message: string
) => {
await fetch(`https://rest.ably.io/messages`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${btoa(env.ABLY_API_KEY)}`,
},
body: JSON.stringify({
channels: channels.map((channel) => `${env.APP_ENV}-${channel}`),
messages: events.map((event) => {
return {
name: event,
data: message,
};
}),
}),
});
};

View file

@ -1,6 +1,6 @@
import { NextResponse, type NextRequest } from "next/server";
import { publishToChannel } from "@/_lib/ably";
import { publishToChannel, publishToMultipleChannels } from "@/_lib/ably";
import { db } from "@/_lib/db";
import { invalidateCache } from "@/_lib/redis";
import { logs, rooms, votes } from "@/_lib/schema";
@ -63,23 +63,11 @@ export async function DELETE(
const success = deletedRoom.length > 0;
if (success) {
await publishToChannel(
`${userId}`,
EventTypes.ROOM_LIST_UPDATE,
JSON.stringify(deletedRoom)
);
await publishToChannel(
`${params.roomId}`,
EventTypes.ROOM_UPDATE,
JSON.stringify(deletedRoom)
);
await invalidateCache(`kv_roomlist_${userId}`);
await publishToChannel(
`${userId}`,
EventTypes.ROOM_LIST_UPDATE,
await publishToMultipleChannels(
[`${userId}`, `${params.roomId}`],
[EventTypes.ROOM_LIST_UPDATE, EventTypes.ROOM_UPDATE],
JSON.stringify(deletedRoom)
);
@ -119,50 +107,58 @@ export async function PUT(
});
}
if (reqBody.log) {
const oldRoom = await db.query.rooms.findFirst({
where: eq(rooms.id, params.roomId),
with: {
votes: true,
logs: true,
},
});
oldRoom &&
(await db.insert(logs).values({
id: `log_${createId()}`,
created_at: Date.now().toString(),
userId: userId || "",
roomId: params.roomId,
scale: oldRoom.scale,
votes: JSON.stringify(
oldRoom.votes.map((vote) => {
return {
name: vote.userId,
value: vote.value,
};
})
),
roomName: oldRoom.roomName,
storyName: oldRoom.storyName,
}));
}
if (reqBody.reset) {
if (reqBody.log) {
const oldRoom = await db.query.rooms.findFirst({
where: eq(rooms.id, params.roomId),
with: {
votes: true,
logs: true,
},
});
oldRoom &&
(await db.insert(logs).values({
id: `log_${createId()}`,
created_at: Date.now().toString(),
userId: userId || "",
roomId: params.roomId,
scale: oldRoom.scale,
votes: JSON.stringify(
oldRoom.votes.map((vote) => {
return {
name: vote.userId,
value: vote.value,
};
})
),
roomName: oldRoom.roomName,
storyName: oldRoom.storyName,
}));
}
await db.delete(votes).where(eq(votes.roomId, params.roomId));
}
const newRoom = await db
.update(rooms)
.set({
storyName: reqBody.name,
visible: reqBody.visible,
scale: [...new Set(reqBody.scale.split(","))]
.filter((item) => item !== "")
.toString(),
})
.where(eq(rooms.id, params.roomId))
.returning();
const newRoom = reqBody.reset
? await db
.update(rooms)
.set({
storyName: reqBody.name,
visible: reqBody.visible,
scale: [...new Set(reqBody.scale.split(","))]
.filter((item) => item !== "")
.toString(),
})
.where(eq(rooms.id, params.roomId))
.returning()
: await db
.update(rooms)
.set({
visible: reqBody.visible,
})
.where(eq(rooms.id, params.roomId))
.returning();
const success = newRoom.length > 0;

View file

@ -1,6 +1,6 @@
{
"name": "sprintpadawan",
"version": "3.1.7",
"version": "3.1.8",
"description": "Plan. Sprint. Repeat.",
"private": true,
"scripts": {