I can pair users with similar level to me to play a chess.
In a chess game, I can review all the steps I have gone through.
List non-functional requirements for the system...
Estimate the scale of the system you are going to design...
match()
stop_search()
play(x, y)
surrender()
UserTable
user_id
user_name
avatar
level
last_active_timestamp
num_matches
num_win
MatchTable
match_id
server_id
status
start_time
duration
num_steps
log_id:
UserMatchTable
user_id:
match_id
win: boolean
server_id:
Distributed FileSystem Table
file_id:
chunk_server:
path:
When
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
The users will connect to the server via socket. The server will maintain a cache for users that are seeking game matching. The cache will be a hashmap. The key is the user level and value is a deque of user_ids. We will also maintain a hashmap from user_id to the memory in the deque. When user is active (through socket) and the enabled searching, the user_id will be added to user_id cache. When user is no longer active, the socket has been broken, the user will be kicked from the queue.
If there are existing users waiting for matching, a match will be paired. Now, it will write an entry in match table and write two entries in user_match_table user match table.
Now, the users will be directed to Game Service. The Game Service could have multiple machines as the game could last long. The table could be using consistent hashing using match_id.
For each game, the game server will cache user_id and color in cache. It will write logs to ensure all the steps are captured. Each player should play by sequence. Once the game is finished, the Game Server will update user_match table and match_table. The logs could be asynchronously dump to the disk for persistence.
When interruption happens, the GameServer will pause the game with a TTL in cache. If the user does not connect within time limit, GameServer will stop the game and announce the other user as winner.
If the user reconnects, it should first go to server and check if any active match in UserMatchTable. If there is, it will forward the user to GameServer to continue the game. The user client will download latest data from GameServer through logs.
We also need to validate the chess movement.
The game server will close the game if anyone calls surrender or the king is taken down. It will write the record in UserMatchTable and MatchTable. Also updates the log.
The log will also be stored in a distributed file system with backup so that in the future, it can be recovered in the future.
User service will on the other hand, handle all match requests. It will monitor the Match Table. Once it is updated, it will update the user table (num match, win rate) and possibly leveling.
We can also choose to decouple User Analysis Table from UserTable as it is mutable part.
UserAnalysisTable
user_id:
win_rate:
num_matches:
leveling:
We can improve the system by upscale it. Server itself should be able to handle 100k if we just use Redis. We can still regionalize the service. Each region should have its own server and game server to reduce network latency. Game server could be hashed using match_id.