Fakultas Ilmu Komputer UI

Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.

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:

  1. controller: this module contains handler functions used to receive request and send responses. In Model-View-Controller (MVC) pattern, this is the Controller part.
  2. model: this module contains structs that serve as data containers. In MVC pattern, this is the Model part.
  3. service: this module contains structs with business logic methods. In MVC pattern, this is also the Model part.
  4. 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 Products. 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

  1. Set up environment variables first by creating .env file. Here is the example of .env file:
    APP_INSTANCE_ROOT_URL="http://localhost:8000"
    Here are the details of each environment variable:
    variable type description
    APP_INSTANCE_ROOT_URL string URL address where this publisher instance can be accessed.
  2. Use cargo run to run this app. (You might want to use cargo 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.
  • 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.
  • 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.

Your Reflections

This is the place for you to write reflections:

Mandatory (Publisher) Reflections

Reflection Publisher-1

Interface vs Struct in Observer Pattern

According to the Head First Design Patterns' description on Observer pattern, the observer (which in this case, Subscriber) is defined as an interface. However, in our implementation of Bambangshop, Subscriber is defined as a concrete struct rather than a trait.

The need to use trait depends on our requirements:

  • Struct - This implementation works well if the subscribers are designed to have the same behaviour and properties.

  • Trait - This implementation works well if several types subscriber are made and each have different implementations.

Bambangshop's notification system is rather simple, all subscribers have a URL which acts as a media for them to receive notifications through HTTP requests. Therefore, the use of a singgle struct is considered sufficient.

Vec vs DashMap for Storing Subscribers

Bambangshop implementation's uses DashMap to store subscribers with their URLs as keys. It's possible to utilize Vec instead of DashMap, however it adds more work as we need to ensure the URLs are unique before storing it into the Vec. DashMap, like other dictionaries, enforce uniqueness, and the keys of DashMap required to be unique. In conclusion, it's possible to use Vec, however it's best to use DashMap.

Thread Safety with DashMap vs Singleton Pattern

This implementation utilizes both DashMap and Singleton pattern (lazy_static). Both plays an important role in this case, where DashMap allows thread-safe, optimal performance, access to the database and the singleton pattern allows the creation of an instance only when it's requested.

Reflection Publisher-2

Separation of Service and repository from a Model

The separation of "Service" and "Repository" is done to fit the Single Responsibility Principle which states that each component should have only one responsibility and only one reason to change. In this case, model focuses on data structure, repository to hand data access and service contains the business logic.

Without Separation

Using models only to handle everything in BambangShop would impact the codebase and future maintenance negatively. It would cause complex dependencies which in result would stray from Open/Close Principle due to the need of refactoring multiple codes for one small update.

Postman

Personally, this has helped me alot in API testing. It allows me to make repeated requests quickly, which gives me more time to analyze and debug where my program went wrong. The environment variable interests me alot, as this feature lets us define certain variable such as BASE_URL and PORT which then can be used in the request creation.

Reflection Publisher-3

Push vs Pull model

In this tutorial, we use the Push Model variation of the Observer pattern. This can be seen from the following facts:

  • The publisher actively sends the complete product data to all subscriber
  • The subscriber receive HTTP POST request
  • The subscriber don't need to make additional request to receive notifications
Advantages/Disadvantage of using a Pull Model

Advantages

  1. Better Error Handling: if a data retrieval fails, it can be retried.
  2. More Control for Subscribers: They have the option to pick when to fetch data.

Disadvantages

  1. Complex: requires two separate endpoints
  2. High Latency: 2 round-trips to get updated information
  3. Increased Server Load: Publisher must handle individual data retrieval requests
Impact of Single-Threading Notifications

The usage of single-threading notifications would impact the program negatively. The notificaitons will be sent sequentially, after one another. If there's an unresponsive or slow subscriber, it'll delay the following subscribers to receive the notifications. As the program increase in users, the delay would increase proportionally.