This is the backend for the messaging app for the NGINX Microservices March demo architecture.
Creating conversations, saving and storing messages. Providing access to messages and conversations.
This service notifies the system at large when a message is sent but does not take any action on message send other than saving the message.
This project requires either NodeJS
or Docker
to run. Using NodeJS
will recreate a local development environment. Using Docker
will let you recreate a pseudo production environment.
This project uses NodeJS
. The current version is specified in .tool-versions
. NodeJS
is a rapidly evolving language which makes it critical to explicitly define which version is being used to avoid any potential errors due to mismatched versions.
We recommended that you use asdf to manage your local NodeJS
installation. Once you have asdf
installed, you can run asdf install
to automatically install the version of NodeJS
specified in .tool-versions
.
In a microservices environment, you may have to work on projects that use different versions of a runtime like `NodeJS`, or use a different language altogether!
asdf is a single tool that lets you manage multiple versions of different languages in isolation and will automatically install and/or switch to the required runtime/version in any directory that has a .tool-versions
file.
This is helpful in getting closer to dev/prod parity in a microservices environment. As you can see in this project, the GitHub action workflow uses the same version called out in .tool-versions
to test the codebase and build a Docker image.
This way, if we use asdf
we're guaranteed to be developing, testing, and releasing to a consistent version of NodeJS.
You can also install NodeJS
by other means - just reference the version number in the .tool-versions
file.
You can run this project on a container using Docker
together with Docker Compose
. This will let you build a simple reproducible image and forget about setting up your local environment. Instructions on how to install Docker
can be found in the Docker
website. (Docker Compose
is included as part of the recommended Docker
installation instructions.)
Note: Instructions marked as (NodeJS - Dev) are only necessary if you want to recreate a local development environment. Instructions marked as (Docker - Prod) are only necessary if you want to recreate a pseudo production environment (careful, it's not actually production ready!).
-
Clone this repo:
git clone https://github.com/microservices-march/messenger
-
Start the
messenger
service PostgreSQL database:docker-compose up -d
-
(Docker - Prod) From the root directory of this repository, build the
messenger
Docker image:# in ./app docker build -t messenger .
-
(Docker - Prod) Start the
messenger
service in a container:docker run --rm -d -p 4000:4000 --name messenger -e PGPASSWORD=postgres -e CREATE_DB_NAME=messenger -e PGHOST=messenger-db -e AMQPHOST=rabbitmq -e AMQPPORT=5672 -e PORT=4000 --network mm_2023 messenger
-
(Docker - Prod) SSH into the container to set up the PostgreSQL DB:
docker exec -it messenger /bin/bash
-
(NodeJS - Dev) Install NodeJS modules:
# in ./app npm install
-
Create the PostgreSQL DB:
# in ./app PGDATABASE=postgres node scripts/create-db.mjs
-
Create the PostgreSQL DB tables:
# in ./app node scripts/create-schema.mjs
-
Create some PostgreSQL DB seed data:
# in ./app node scripts/create-seed-data.mjs
-
(NodeJS - Dev) Start the service:
# in ./app node index.mjs
Once the messenger service is running:
-
Create a conversation:
curl -d '{"participant_ids": [1, 2]}' -H "Content-Type: application/json" -X POST http://localhost:4000/conversations
-
Send a message to the conversation from a user (user 1):
curl -d '{"content": "This is the first message"}' -H "User-Id: 1" -H "Content-Type: application/json" -X POST 'http://localhost:4000/conversations/1/messages'
-
Reply with a message from a different user (user 2):
curl -d '{"content": "This is the second message"}' -H "User-Id: 2" -H "Content-Type: application/json" -X POST 'http://localhost:4000/conversations/1/messages'
-
Fetch the messages:
curl -X GET http://localhost:4000/conversations/1/messages
-
Set the "view horizon" for the first user:
curl -i -d '{"index": 2}' -H "User-Id: 1" -H "Content-Type: application/json" -X POST 'http://localhost:4000/conversations/1/view_horizon'
The configuration data for this application can be seen in the configuration schema.
This application serves as a simple example of a service handling messages that are durably stored. However, it intentionally does not do a few things for the sake of simplicity:
- No effort has been made to be sure that administrators cannot view messages
- Pagination is not implemented on any endpoints
- Message storage is being done in a simple relational database. No design has been done to handle fast retrieval of newer messages and other performance concerns.
- The message insertion SQL has not been optimized to handle high write volumes
The application assigns a monotonically increasing index
to each message within a conversation. This index is used to determine whether a member of a conversation has seen a message or not. In the users_channels
table, we store the index of the last message the user has seen in that conversation.
Any messages with an index
higher than than index
are said not to have been seen by the user.
The code for this example is written in a style that not in line with application development best practices.
Instead, it is optimized to be quickly understood by those seeking to understand the Microservices March Demo Architecture without assuming special familiarity with:
- Javascript
- NodeJS
- Express
Therefore, we've opted to:
- Avoid frameworks that have domain specific languages (ie, database libraries)
- Avoid splitting up code into many different files
If you want to cleanup any artifacts resulting from running this project, run:
-
If you used
NodeJS
to run the project:rm -rf node_modules
-
If you used
Docker
to run the project:docker rmi messenger
Read the CONTRIBUTING.md
file for instructions on how to best contribute to this repository.
© F5 Networks, Inc. 2023