Functional:
API design
Here's a breakdown of the essential REST
API for our Employee Swap System.
User service:
PUT /auth/v1/login - authenticate a user
PUT /auth/v1/logout - log out user
POST /auth/v1/register - register new user:
{
"employee_id":
"name": "name1"
"email":....
"phone": ...
"employe_id":
"position":
"department":
"manager_id"
}
GET /user/v1/manager/{employee_id}
Returns the manager information:
{
'employee_id':
'name':
'email':
}
Employee shift matching service:
PUT /shift_matching/v1/swap/{employee_id}/{shift_id} - try to confirm the shift swap for the {shift_id} by an employee {empoloyee_id} Return:
{ "swap_id"....
"status": IN_PROGRESS,APPROVED_BY_MANAGER,APPROVED_BY_OTHER_EMPLOYEE,CANCELED
"createdAt": ....
}
GET /shift_matching/v1/swap/{employee_id}/status/{swap_id} - return the swap status:
{ "swap_id"....
"status": IN_PROGRESS,APPROVED_BY_MANAGER,APPROVED_BY_EMPLOYEE,CANCELED
"createdAt": ....
}
GET /shift_matching/v1/shift/{employee_id}
return the available shifts for an employee
{[.
'shift_id':
'employee_id':
'start_time':
'end_time':
'last_swap_date':
'status':
]}
PUT /shift_matching/swap/manager/{manager_id}/approve/{swap_id} - a manager approves the suggested shift if both employees agree.
Employee Shift service:
GET /employee_shift/v1/shift/{employee_id}/shifts?startDate=..&endDate=..&offset=..&pageSize=.. - get the list of the shifts belonging to the employee:
{ "employee_id":...
"shifts":[
{ "shift_id":....
"startFrom":
"endTo":
'status':
'last_swap_date'
},
....
]
POST /employee_shift/v1/shift/{employee_id}
Persist new shift for an employee.
body:
{ 'shift_id'
'employee_id'
'start_date':
'end_date':
'status':
'last_swap_date':
}
PUT /employee_shift/v1/shift/{employee_id}
Update the shift information for an employee.
Notification Service:
Uses the WebSocket to send updates to the client application.
PUT /notification/v1/notify
{
'employee_id':
'message':
'url':
'expired_at':
}
See the diagram from the high-level architecture.
API Gateway provides DDoS protection and TLS termination, and routes the requests to the right service nodes.
The user service:
Employee shift matching service:
IN_PROGRESS,APPROVED_BY_MANAGER,APPROVED_BY_OTHER_EMPLOYEE,CANCELED
Employee shift service:
The client application:
Kafka:
Postgres:
Redis:
The notification service:
All the services can be deployed to AWS EKS and would be managed by Kubernetes.
API Gateway: Distributes the user requests evenly and hides API behind the API Gateway, also it routes the request by usingthe lsito service mesh to build the Microservice architecture. The employee_id may be used as sharding key to distribute the user request evenly.
Employee shift matching service:
This is an essential service, and it's used to match the given employee shift. The service prepared the possible shift swap using the Hungarian algorithms and returns the list of shifts to the user. This service returns the swap status update to the client application by using long-polling. It's overkill to use the WebSocket because the swap frequency is low. The service asks the User service to get employee's manage_id. This service is stateless, and if it's down, this service just reads the necessary information from the Employee Shift service and the client application and puts them into Redis. This service is orchestrated by Kubernetes, which cares about the service health and availability. We can use the Kubernetes autoscaling mechanism to regulate the resources to process the user requests efficiently. It cares if some shift swap is hanging over 1 day; it would be evicted from Redis as outdated.
If the employee proposes the shift swap, this service sends the message to the Notification service to notify other employees to consider the swap propositions.
The Redis cluster is isolated from the Employee shift matching service. The Redis cluster is a highly available and fault-tolerant solution.
The client application is developed to have a comfortable and simple interface for employees. It shows the possible shifts, requests the swap status from the Employee shift matching service. Also, if the Employee shift service is down, it may resend the last information about the swap shift. The client application connects with the Notification service to get the shift swap notification.
Notification service:
Connects to the client application to notify the employees in the client application about the shift swap to approve. Hold the network websocket connection information in Redis. The notification service is statefull and would be managed by Kubernetes. It uses the lstio to build the consistent hashing by emploee_id to process the request efficiently. It duplicates and sends the notification using email.
User service:
Uses Postgres to hold the user information because we need to support the strong consistency in SQL storage:
The user table:
employee_id : the unique key string 128 bytes
name: string 128 bytes
email: string 256 bytes
role: string 'employee' or 'manager'
manager_id: string 128 bytes
createAt: timestamp 4 bytes
loggedIn: boolean 1 bytes
LastLogin: timestamp 4 bytes
The employee shift service:
Utilizes Postgres to store the shift information.
The shift table:
shift_id: string 128 bytes, the unique key
the employee_id: string 128 bytes
start_date: timestamp
end_date: timestamp
status: byte
The shift_swap_history table:
swap_id: string 128 bytes
src_emploee_id1: string 128 bytes
src_shift_id: string
target_ employee_id: string 128 bytes
target_shift_id: string 128 bytes
created_at: timestamp 4 bytes
So it takes 2 kbytes to store all tables, and it takes 80 megabytes for 1 year, it takes 1 Gigabytes for 5 years. (we're going to hold one replication copy)