See branch socket-connection
Some key points to keep in mind:
next-auth
allows authentication with many different providersnext-auth
supports different session strategies (e.g. "jwt" | "database)- We implement the
database
strategy.
To stick with conventions, keep the isolations of full-stack web app and external game server, and avoid creating new data we'll proceed with the database
strategy and build around it.
- Client requests server route /api/auth/signin
Session
created in database withuserId
andexpires
timestamp- Client side request to Socket-Server
- Socket-Server middleware validates requesting
User
'sSession
Implemented context for requesting and listening to pool conneciton count via acknowledgements.
Uses our preexisting channel which requires authentication.
Connection isn't protected, so we should implement 2 namespaces. A public channel with no middleware, and an authenticated channel with our previously added session token method.
Isolates public and protected socket information and allows realtime data flow for any client.
Data like the number of connections should be emitted to any client irrespective of session information. Therefore we establish two namespaces for authenticated and public data flow.
- Public and private namespaces added to socket server
- Refactored client connection to connect to and disconnect from the appropriate namespace.
- Refactored context to cleanly apply and remove listers for socket events
- Implemented use of useConnectionCount hook
- Implement same functionality for pool connections (private connections)
- Implement User Credits functionality, add to middleware checks performed by socket server
User credits are...user specific. Meaning we should implement client-cide data-fetching.
Reasons for this are as follows:
- Server side props unnecessary and cumbersome to add to every page
- Credits are mounted only for signed in users, meaning we should implement at the component level.
- TRPC router handlers handle authentication validation and query for token on the server side. Handles database operations (controller) away from the client and simply returns a count.
- Added protected TRPC for obtaining credit amount for signed in users.
- Procedure queries Postgres database using PK in session information for scalar balance value.
- Rendering of component handled by parent to avoid inequal renders of useQuery hook.
- Stripe payment required for writing to balance column.
- Protected room and root account paths.
- Added socket events action:create-room & ack:create-room.
- Created hook for creating room and updating a component similar to clash of codes starter match .
- Add persistence to client component
CreateRoom
, when the user changes routes, the room is still created but the component remounts itself to it's original state, allowing user to create more than one active room at a time, not good :(. - Isolate member component for re-use across app, specifically for
CreateRoom
andJoinLink
components. - Create JoinLink component displaying users in a room and a button to join it
- Add server logic to ack the information about the users in client's current room
- Add server logic to ack information about atleast 10 rooms (leave room for pagination)
- Room Context for room information persistence.
- Leave room action and acknowledgement events
- Room Context
- Update room context on edge case events like force refresh
- Added Typescript to server for more stable module development.
- Refactored events into more general, reusable events that update a changer, and the affected in real time.
- Refactored events on client side in
RoomContext
. - Added conditional room panel to create & join rooms, view members once joined.
- Redis provides a more robust, best practice way to store potentially 1 million JSON formatted records than storing in program locally as a Map.
- Acts as single source of truth for all rooms and their respective connected members.
- Memory Efficiency: Redis is designed to efficiently manage data in memory, making it more optimized for storing large datasets compared to keeping them in the memory of a running program.
- Persistence: Redis provides options for persisting data on disk, allowing you to maintain the dataset even after restarting the server or in case of system failures.
- Scalability: Redis is designed to handle large datasets and can be easily scaled horizontally through mechanisms like clustering and replication.
- Performance: Redis is known for its fast read and write operations, thanks to its in-memory nature and optimized data structures. (realtime application, data should be gathered faster than querying a DB)
- Simiplicity: Redis offers a straightforward and consistent API, making it easier to integrate with Node.js in this case.
- ETC & K.I.S.S.!
Keep in mind this Redis implementation should not be exposed to the internet, and should only accept connections from the socket-server instance the 2 are running on. Consider adding requirepass
and bind
in the deployed instances' redis.conf
file. See more information here.
Run the Redis server for development purposes with
cd server
redis-server
Test the client connection (socket-server) to Redis server.
cd server
redis-cli
Add dependency to Node
npm install redis
- Major refactor to socket server code, reusability, clarity, and harnessing the power of events to distribute data in real time to many different clients.
- Replaced local JS map with Redis key-value pairs.
- Records created, updated, and deleted based on rooms events of same names.
- Refactored client side room context. Established clear seperation of pool and room count logic while using the same event
update:room-count
.- Changes to the pool are emitted to all authenticated connections, irrespective of whether they are in the pool or not.
- Room updates with the
roomID
"pool" are handled byusePoolCount
hook. RoomContext
foundational state likeroomID
androomData
can only be changed by an ACK made by the socket server for the eventsack:create-room
,ack:update-room
,ack:delete-room
as these explcitally imply the room the client is in. Whereas updates only inform us of changes made to any rooms we made be in, have left, or have altered.
- Continue to refactor and remove repititions in the server code.
- Do major cleanup on client side code and ensure type safety for all contexts.
- Implement Admin functionality and handling.
- Joinable rooms pagination.
- Restyle
RoomPanel
- Stronger error messages on ack events from the server.
- Refactored client side code
- Fixed some edge cases on server side
- Added some styles for the room page
- Handle socket disconnections, when the server abruptly shuts down the rooms in progress should be