Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# Problem 2: Actors
## Setup
Use the following commands to make a fresh clone of your repository:
```
git clone -b concpar21final02 git@gitlab.epfl.ch:lamp/student-repositories-s22/cs206-GASPAR.git concpar21final02
```
If you have issues with the IDE, try [reimporting the
build](https://gitlab.epfl.ch/lamp/cs206/-/blob/master/labs/example-lab.md#troubleshooting),
if you still have problems, use `compile` in sbt instead.
## Useful links
* [A guide to the Scala parallel collections](https://docs.scala-lang.org/overviews/parallel-collections/overview.html)
* [The API documentation of the Scala parallel collections](https://www.javadoc.io/doc/org.scala-lang.modules/scala-parallel-collections_2.13/latest/scala/collection/index.html)
* [The API documentation of the Scala standard library](https://www.scala-lang.org/files/archive/api/2.13.4)
* [The API documentation of the Java standard library](https://docs.oracle.com/en/java/javase/15/docs/api/index.html)
## Exercise
Your task is to implement a couple of actors in Discord like service. You will only focus on two actors in the system: (1) the `NotificationService` and (2) and a `DiscordChannel`.
A user will be able to post messages on the channel and retrieve the messages from the channel.
A user also has the ability to (un)register from the notifications.
Before it can receive requests, each channel is initialized with a notification service.
When a message is posted to the channel, it tells its notification service to notify the users.
The following diagram shows how the communication between actors works. Requests are within `()` and responses are within `[]`.
```none
(Post) [Active]
(GetLastPosts) ┏━━━━━━━━━━━━━━━━━━┓ [AlreadyActive] ┏━━━━━━━━━┓
┌──────────────────────>┃ ┃──────────────────►┃ ┃
│ ┃ DiscordChannel ┃ ┃ System ┃
│ ┃ ┃◄──────────────────┨ ┃
│ [Posts] ┗━┯━━━━━━━━━━━━━━━┯┛ (Init) ┗━━━━━━━━━┛
┏━━┷━━━┓ [NotActive] │ │
┃ ┃◄────────────────────┘ │
┃ User ┃ │
┃ ┃◄────────────────┐ │
┗━━┯━━━┛ [Registered] │ │ (NotifyAll)
│ [Notification] │ │
│ │ │
│ ┏━━━━┷━━━━━━━━━━━━━━━━┓ │
└───────────────►┃ ┃ │
(Register) ┃ NotificationService ┃◄─┘
(UnRegister) ┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━┛
```
Your tasks in the exercise will be to:
TASK 1: Complete the implementation of the `NotificationService` by implementing method `receive` to handle messages from `NotificationService.Protocol`:
```scala
def receive: Receive = ???
```
TASK 2: Complete the implementation of the `DiscordChannel` by implementing methods `nonActive` and `active` to handle messages from `DiscordChannel.Protocol`:
```scala
def nonActive: Receive = ???
def active(notificationService: ActorRef): Receive = ???
```
### NotificationService protocol
* __Register__: Registers the user for notifications and responds with a `Registered(true)`.
* __UnRegister__: Un-registers the user for notifications and responds with a `Registered(false)`.
* __NotifyAll__: Sends a `Notification` to all registered users.
### DiscordService protocol
The channel can be in one of two states: _non-active_ or _active_.
* __Init__: When _non-active_, responds with `Active` and the state becomes _active_. Otherwise responds `AlreadyActive`.
* __Post__: When _active_, stores the message and sends `NotifyAll` to its `NotificationService`. Otherwise responds `NotActive`.
* __GetLastPosts__: When _active_, responds with `Posts` containing the latest messages (ordered from most to least recent). Otherwise responds `NotActive`.
### Running the code
Apart from the grading tests, we include a `@main def debug` method, where you can write your own tests to help you debug your implementation. This method is __not__ graded. It can be executed using `run` within SBT.