BambangShop Publisher App
Tutorial and Example for Advanced Programming 2024 - Faculty of Computer Science, Universitas Indonesia
About this Project
In this repository, we have provided you a REST (REpresentational State Transfer) API project using Rocket web framework.
This project consists of four modules:
-
controller
: this module contains handler functions used to receive request and send responses. In Model-View-Controller (MVC) pattern, this is the Controller part. -
model
: this module contains structs that serve as data containers. In MVC pattern, this is the Model part. -
service
: this module contains structs with business logic methods. In MVC pattern, this is also the Model part. -
repository
: this module contains structs that serve as databases and methods to access the databases. You can use methods of the struct to get list of objects, or operating an object (create, read, update, delete).
This repository provides a basic functionality that makes BambangShop work: ability to create, read, and delete Product
s.
This repository already contains a functioning Product
model, repository, service, and controllers that you can try right away.
As this is an Observer Design Pattern tutorial repository, you need to implement another feature: Notification
.
This feature will notify creation, promotion, and deletion of a product, to external subscribers that are interested of a certain product type.
The subscribers are another Rocket instances, so the notification will be sent using HTTP POST request to each subscriber's receive notification
address.
API Documentations
You can download the Postman Collection JSON here: https://ristek.link/AdvProgWeek7Postman
After you download the Postman Collection, you can try the endpoints inside "BambangShop Publisher" folder.
This Postman collection also contains endpoints that you need to implement later on (the Notification
feature).
Postman is an installable client that you can use to test web endpoints using HTTP request. You can also make automated functional testing scripts for REST API projects using this client. You can install Postman via this website: https://www.postman.com/downloads/
How to Run in Development Environment
- Set up environment variables first by creating
.env
file. Here is the example of.env
file:APP_INSTANCE_ROOT_URL="http://localhost:8000"
variable type description APP_INSTANCE_ROOT_URL string URL address where this publisher instance can be accessed. - Use
cargo run
to run this app. (You might want to usecargo check
if you only need to verify your work without running the app.)
Mandatory Checklists (Publisher)
- Clone https://gitlab.com/ichlaffterlalu/bambangshop to a new repository.
-
STAGE 1: Implement models and repositories
-
Commit:
Create Subscriber model struct.
-
Commit:
Create Notification model struct.
-
Commit:
Create Subscriber database and Subscriber repository struct skeleton.
-
Commit:
Implement add function in Subscriber repository.
-
Commit:
Implement list_all function in Subscriber repository.
-
Commit:
Implement delete function in Subscriber repository.
- Write answers of your learning module's "Reflection Publisher-1" questions in this README.
-
Commit:
-
STAGE 2: Implement services and controllers
-
Commit:
Create Notification service struct skeleton.
-
Commit:
Implement subscribe function in Notification service.
-
Commit:
Implement subscribe function in Notification controller.
-
Commit:
Implement unsubscribe function in Notification service.
-
Commit:
Implement unsubscribe function in Notification controller.
- Write answers of your learning module's "Reflection Publisher-2" questions in this README.
-
Commit:
-
STAGE 3: Implement notification mechanism
-
Commit:
Implement update method in Subscriber model to send notification HTTP requests.
-
Commit:
Implement notify function in Notification service to notify each Subscriber.
-
Commit:
Implement publish function in Program service and Program controller.
-
Commit:
Edit Product service methods to call notify after create/delete.
- Write answers of your learning module's "Reflection Publisher-3" questions in this README.
-
Commit:
Your Reflections
This is the place for you to write reflections:
Mandatory (Publisher) Reflections
Reflection Publisher-1
1. Do we still need an interface (or trait in Rust) for the Subscriber in the BambangShop case?
In the Observer design pattern, the Subscriber
(or Observer
) is typically an interface (trait in Rust) that allows different concrete implementations of subscribers to be notified when a state change occurs in the Subject
. This abstraction enables flexibility, as multiple types of subscribers can exist with different behaviors. However, in the BambangShop case, if all subscribers share the same structure and behavior meaning they only store information and do not require different implementations then using a single Subscriber
struct is sufficient, and a trait is unnecessary. If, in the future, different types of subscribers with distinct behaviors (e.g., logging subscribers, email subscribers, etc.) are needed, then defining a Subscriber
trait would make sense. Otherwise, keeping it as a single struct simplifies the design without unnecessary abstraction.
Vec
sufficient, or is DashMap
necessary for unique id
in Program
and url
in Subscriber
?
2. Is using Using a Vec
(list) would not be an efficient solution for ensuring uniqueness of id
in Program
and url
in Subscriber
, because checking for uniqueness in a Vec
requires iterating through all elements, making insertions and lookups have a time complexity of O(n)
. In contrast, DashMap
(or a HashMap
in a single-threaded context) provides constant-time O(1)
average complexity for insertions and lookups, ensuring uniqueness efficiently. Since the requirement is to enforce unique id
and url
, a map-based structure like DashMap
is necessary. Additionally, DashMap
allows for concurrent read and write operations, making it more suitable in a multi-threaded environment where multiple threads may access or modify the subscriber list simultaneously.
DashMap
, or can we use the Singleton pattern instead?
3. Do we still need The Singleton pattern ensures that only one instance of a structure exists throughout the program, which is useful for maintaining a global state, such as the SUBSCRIBERS
list. However, in Rust, simply using the Singleton pattern with a Mutex<HashMap>
or RwLock<HashMap>
would introduce locking overhead, which can degrade performance when multiple threads try to read or write simultaneously. DashMap
is designed to provide fine-grained locking, allowing multiple threads to access different parts of the map concurrently without blocking each other. This makes DashMap
a more efficient and scalable solution for a globally shared, thread-safe HashMap
. While the Singleton pattern could be used, it would require additional synchronization mechanisms, making DashMap
the better choice for managing concurrent access to subscribers in a high-performance application.