We will also add the SharedTasks type alias, which represents an IndexMap wrapped with Mutex and Arc. We will use this type to store all the tasks and statuses for them:
type SharedTasks = Arc<Mutex<IndexMap<String, Record>>>;
Record is a struct that contains the unique identifier of the task, and is used as the correlation ID for the message. It also has a timestamp that denotes when the task was posted, and a Status that represents the status of the task:
#[derive(Clone)]
struct Record {
task_id: TaskId,
timestamp: DateTime<Utc>,
status: Status,
}
Status is an enumeration that has two variants: InProgress, when a task is sent to a worker; and Done, when a worker returns a response as a QrResponse value:
#[derive(Clone)]
enum Status {
InProgress,
Done(QrResponse),
}
We need to implement the Display trait for Status, because we will use it to render the HTML template. Implement the trait:
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Status::InProgress => write!(f, "in progress"),
Status::Done(resp) => match resp {
QrResponse::Succeed(data) => write!(f, "done: {}", data),
QrResponse::Failed(err) => write!(f, "failed: {}", err),
},
}
}
}
We will show three statuses: in progress, succeed, and failed.
Our server needs a shared state. We will use the State struct with a map of tasks and an address of QueueActor and ServerHandler:
#[derive(Clone)]
struct State {
tasks: SharedTasks,
addr: Addr<QueueActor<ServerHandler>>,
}
Now, we can implement ServerHandler and spawn an actor with it.