Build an Kanban based on Typescript
Tags: Backend, System Design Interview, Typescript, Nodejs, Tutorial

Now, you can start to install all packages you need. This project will be based on Express .

In the scripts , I will enforce do the linting before the user build the project. You can remove this, if you think it takes time. What I hope is to make sure my code quality is good enough.

The following is my package.json .

Design

At first, you can create one directory architecture like this.

app.ts is the main entrance of this project.

Start to Design Database

Before I start this, what I want to do is something like trello . You also need to have one blueprint in your mind, when you start to think your design.

A trello may have users , kanbans , kanbans_statuses , tasks , and the relationship between each other.

Every deletion in the system should be soft delete, so I will add is_deleted in each table.

The following is all of the relationship.

One kanbans can have many users .

can have many . One users can have many kanbans .

can have many . One kanbans can have many kanbans_statuses .

can have many . One kanbans_statuses can have one kanban .

can have one . One kanbans can have many tasks .

can have many . One tasks can have one kanbans .

can have one . One users can have many tasks .

can have many . One tasks can have one users .

can have one . One tasks can have one kanbans_statuses .

can have one . One kanbans_statuses can have one tasks .

In the trello, it will show the latest editor, so it will have last_modified in tasks and kanbans_statuses . The detail log you can find in elasticsearch if you really need, but actually for current user stories, you do not need and of course do not over-designed.

Start to Design Flow by Stories

In the user story, it never mentions about how to retrieve kanbans and tasks, but if you do not create these api, your system cannot be check by interviewer. Thus, I try to add three more api about retrieve.

The following is the stories created by myself.

As a user, I can get the kanban name by the given kanban id.

As a user, I can get the kanban statuses by the given kanban id.

As a user, I can get all tasks which are categorized by the given kanban id.

You can check the flow by this diagram.

Develop

In this part, I will show part of code only. Just make sure you can know why to have this and how to use this.

Util

In the util directory, I will create env.util.ts .

In the env.util, it will use dotenv to read the environment variables, such as database password. If the given env does not exist, the syste, will throw exception and stop the whole system to avoid missing any env.

The exception must be throw when you are starting your http server; otherwise, you server may work when you just start, but when your user wants to use some API which need some env, they may encounter some problems. It is really not a good thing. I prefer to get error when I start the server.

In the constant directory, it will have env.constant.ts to manage all env, to make sure you can know every env you need. Please do not use EnvUitl.getEnv at everywhere.

Service

In the service directory, it will have db.service.ts to simply wrap your database library. Even if you use orm, I still highly recommend you to wrap. That is because you cannot know how will the other use that.

I use typeorm in this project. Just make sure all developer won’t create their own connection, and everyone should set config by this service.

In the route, I will user one main route to wrap all required api. This main route will call v[YOUR_VERSION].ts . In the future, you may have the other versions.

To control the format of all response. I will add one middleware which will manager all throughput.

You may also find it will have LoggerService before I send it. This is also an advantage for why to manage all output data. It can help you log all of your api results without any duplicated code.

Email the change of tasks.

In order to email the change, you should have the other daemon to send the email and your http server should be able to acknowledge about the change.

At there, I choose Rabbitmq as the message queue broker and use amqp as message queue protocol.

If you use mqtt which is more popular protocol in IOT, you will notify all of your consumer. It does not make sense. You just want to send the email one time only.

When you are developing, you can use cloudamqp or docker as your message queue service, it has some free plan.

Log

To log your activities, please do not write to local storage. That is because, in the virtual machine, local storage is not trustable, so I choose fluentd as the logger system which will help you write your log to the place you configured.

Deploy

I use docker to deploy. In order to reduce the image size, I use multi-stage builds

you will have your own start script in this image. That is because you do not need to build again when you start one container. Therefore, it will use npm run start:cloud instead of npm run start .

I use CircleCI as CI. In order to run all required components, such as database and fluentd , I will install all dependencies by myself. Just one bad thing is Rabbitmq cannot be stopped when the testing is finished. It means CI won't be stopped also, so I try to connect to the cloudamqp instead of localhost.

In the CI, whether to hide the password of database does not matter, because everything is hosted by CI. It won’t affect any environment set up in your virtual machine.