Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7dea09f
"feat: create docker env for server"
TOMOFUMI-KONDO Jan 4, 2022
a3cf165
Merge branch 'main' into feature/dockerize-server
TOMOFUMI-KONDO Jan 12, 2022
7f85eb3
Merge branch 'main' into feature/dockerize-server
TOMOFUMI-KONDO Jan 12, 2022
3110fe1
fix: pass PoolClient from RoomRepository to other repositories to get…
TOMOFUMI-KONDO Feb 22, 2022
3c5f741
fix: put it back to retrive all rooms
TOMOFUMI-KONDO Feb 22, 2022
ba34b32
test: update test to guarantee that test passes when there are a lot …
TOMOFUMI-KONDO Feb 22, 2022
ad5b382
refactor
TOMOFUMI-KONDO Feb 22, 2022
7c82b48
refactor: AdminService
TOMOFUMI-KONDO Feb 22, 2022
60c1388
fix: fix arg name
TOMOFUMI-KONDO Mar 4, 2022
1a59c49
feat: create method fetch all managed rooms to avoid N+1 query
TOMOFUMI-KONDO Mar 4, 2022
b309ce7
feat: introduced ECS and modulize terraform stacks
TOMOFUMI-KONDO Mar 12, 2022
8fc52cd
feat: create Nginx Dockerfile and conf template
TOMOFUMI-KONDO Mar 12, 2022
5f52d44
feat: add CI/CD config files and remove unused config files
TOMOFUMI-KONDO Mar 12, 2022
06f2171
fix: fix module source path and args
TOMOFUMI-KONDO Mar 12, 2022
e2bf06d
fix: fix wrong field name
TOMOFUMI-KONDO Mar 12, 2022
ea9ec00
fix: don't use envfile on applicatoin code side but use on docker side
TOMOFUMI-KONDO Mar 12, 2022
ff53ecc
feat: enable host reload on docker-compose server
TOMOFUMI-KONDO Mar 12, 2022
13becc2
chore: setup test with docker and update document
TOMOFUMI-KONDO Mar 12, 2022
b28c14e
Merge branch 'main' into feature/dockerize-server
TOMOFUMI-KONDO Mar 12, 2022
668a0d7
fix: M1 Mac support
TOMOFUMI-KONDO Mar 13, 2022
a2edf88
feat: specify github branch at run time
TOMOFUMI-KONDO Mar 13, 2022
fd765a4
fix: change code deploy role
TOMOFUMI-KONDO Mar 13, 2022
5982d8b
feat: use appspec.yaml from build output
TOMOFUMI-KONDO Mar 13, 2022
9b330b1
fix: input artifacts
TOMOFUMI-KONDO Mar 13, 2022
bc694b6
feat: continue on ready deployment
TOMOFUMI-KONDO Mar 13, 2022
ccb5291
trivial fix
yuta-ike Mar 16, 2022
0ba066a
Merge pull request #683 from osushi-academy/hotfix/get-managed-rooms
yuta-ike Mar 16, 2022
7c661ab
chore: remove docker-compose stop of setup.sh
TOMOFUMI-KONDO Apr 1, 2022
b681ebb
fix: add ignore_change metadata to ignore changes created by CI/CD pr…
TOMOFUMI-KONDO Apr 1, 2022
838615f
feat: update RDS Engine version
TOMOFUMI-KONDO Apr 1, 2022
ae1a2f6
feat: terraform lock file was updasted on execution of 'terraform ini…
TOMOFUMI-KONDO Apr 1, 2022
bc6b212
Merge pull request #688 from osushi-academy/feature/dockerize-server
TOMOFUMI-KONDO Apr 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ jobs:
- name: build shared package
run: yarn build:shared
- name: Run test
run: yarn workspace sushi-chat-server test
run: yarn test:server
31 changes: 0 additions & 31 deletions .github/workflows/deploy-aws.yml

This file was deleted.

2 changes: 1 addition & 1 deletion app/Dockerfile → app/front/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ EXPOSE 3000
# 開発サーバー立ち上げ(installの差分がある場合実行に時間がかかる)
CMD sh -c "cd app/front && yarn install && yarn run dev"

ENV CHOKIDAR_USEPOLLING=true
ENV CHOKIDAR_USEPOLLING=true
3 changes: 0 additions & 3 deletions app/server/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
DB_SSL=
DATABASE_URL=

FIREBASE_ADMIN_PROJECT_ID=
FIREBASE_ADMIN_CLIENT_EMAIL=
FIREBASE_ADMIN_PRIVATE_KEY=
23 changes: 23 additions & 0 deletions app/server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM node:14.18.2-alpine3.14

WORKDIR /src

COPY package.json ./
COPY yarn.lock ./
RUN mkdir -p ./app/server ./app/shared
COPY app/server/package.json ./app/server/
COPY app/shared/package.json ./app/shared/

RUN yarn install

COPY tsconfig.json ./
COPY app/server ./app/server/
COPY app/shared ./app/shared/

RUN yarn build:shared && yarn build:server

ENV NODE_ENV=production

EXPOSE 7000

CMD ["yarn", "start:server"]
97 changes: 27 additions & 70 deletions app/server/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
# サーバー

## 前提条件
- dockerが起動している
- docker-composeコマンドをインストール済
- psqlコマンドをインストール済

## 事前準備

### 1. DBの準備

1. ローカルでPostgreSQLのサーバーが起動していることを確認する
- ない場合はインストールして起動する(https://www.postgresql.org/download/)
2. 起動しているPostgreSQLのサーバーのURIを控えておく
- 例:`postgres://<user>:<password>@<host>:<port>/<database>`
3. 2の手順でで確認したユーザーでPostgreSQLに接続し、`server/src/database/ini.sql`のCREATE TABLEを実行する
- 例:`psql -f app/server/src/database/ini.sql <PostgreSQLのURI>`
4. 環境変数に`DB_SSL=OFF DATABASE_URL=<PostgreSQLのURI>`を設定しておく(サーバーの起動時やテストの実行時に渡してもよい)
DockerのPostgreSQLコンテナを使う。

```
./app/server/setup.sh
```

を実行すればDBコンテナを立ち上げて初期設定をしてくれる。

### 2. Redisの準備
※ローカル環境で複数サーバーを立てるときのみ必要な設定です
Expand All @@ -37,82 +42,34 @@ yarn install
## ローカルでの起動方法

```
yarn dev:server
docker-compose --env-file app/server/.env up server nginx db
```

または

```
cd app/server/
yarn dev
```

必要に応じて以下の環境変数を設定してください

| 環境変数名 | 内容 | 例 |
| --- | --- | --- |
| SOCKET_IO_ADAPTER | Socket.IOのadapterを指定 | redis |
| PORT | listenするport | 7000 |
| CORS_ORIGIN| サーバーに接続するフロントのURL | http://localhost:3000 |
| DB_SSL | DB接続にSSLを使用するか | OFF |
| DATABASE_URL | DBの接続先 | postgres://sushi:chat@localhost:5432/db
| 環境変数名 | 内容 | 例 |
|-------------------|----------------------|-----------------------------------------|
| SOCKET_IO_ADAPTER | Socket.IOのadapterを指定 | redis |
| PORT | listenするport | 7000 |
| CORS_ORIGIN | サーバーに接続するフロントのURL | http://localhost:3000 |
| DB_SSL | DB接続にSSLを使用するか | OFF |
| DATABASE_URL | DBの接続先 | postgres://sushi:chat@localhost:5432/db |

※サーバー側のlistenするportをデフォルトの7000以外にした場合は、frontを起動するときに`API_BASE_URL`の環境変数を指定して接続先のサーバーを指定する必要があります

### 複数サーバーを立てる場合のコマンド例
```
PORT=7000 DB_SSL=OFF DATABASE_URL=postgres://<username>@localhost:5432/<dbname> SOCKET_IO_ADAPTER=redis yarn dev:server
PORT=7001 DB_SSL=OFF DATABASE_URL=postgres://<username>@localhost:5432/<dbname> SOCKET_IO_ADAPTER=redis yarn dev:server
PORT=3000 API_BASE_URL=http://localhost:7000 yarn dev:front
PORT=3001 API_BASE_URL=http://localhost:7001 yarn dev:front
```

## ビルド

0. ディレクトリに移動
```
cd app/server/
```
1. ビルド

```
yarn build
```

2. ビルドファイルを実行
```
yarn start
```
```
docker-compose build
```

## テスト

0. ディレクトリに移動
```
cd app/server/
```
1. 全てのテストを実行する

```
yarn test
```

2. 部分的にテストを実行する
```
yarn test -- ./path/to/testfile.ts
```
```
yarn test -- ./src/__test__/chat.ts
```
```
docker-compose up server_test db_test
```

## デプロイ

main に pull-request すれば以下にデプロイされるはず

<https://sushi-chat-server.herokuapp.com>

手動のデプロイは一番上のディレクトリで

```
git subtree --prefix server push heroku main
```
mainブランチにマージされると<https://api.sushi-chat.com>にデプロイされる。
11 changes: 5 additions & 6 deletions app/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"description": "server of sushi chat",
"main": "app.js",
"scripts": {
"start": "node --require dotenv/config ./dist/src/app.js",
"start": "node ./dist/src/app.js",
"build": "tsc -p .",
"dev": "ts-node-dev --require dotenv/config --transpile-only --rs ./src/app.ts",
"test": "jest --setupFiles dotenv/config",
"test:watch": "jest --watch --setupFiles dotenv/config",
"dev": "ts-node-dev --transpile-only --rs ./src/app.ts",
"test": "jest",
"test:watch": "jest --watch",
"lint": "eslint ./src",
"fix": "prettier --write \"**/*.{js,ts}\" --ignore-path .gitignore .",
"fix:dry-run": "prettier --check \"**/*.{js,ts}\" --ignore-path .gitignore ."
Expand All @@ -20,7 +20,6 @@
"@socket.io/redis-adapter": "^7.0.0",
"@types/express": "^4.17.11",
"bcrypt": "^5.0.1",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"firebase-admin": "^9.11.1",
"node-uuid": "^1.4.8",
Expand Down Expand Up @@ -48,4 +47,4 @@
"ts-node-dev": "^1.1.6",
"typescript": "^4.2.4"
}
}
}
13 changes: 13 additions & 0 deletions app/server/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

docker-compose up -d db db_test
sleep 10

db_urls=(
"postgres://sushi:chat@localhost:54320/sushi_chat"
"postgres://sushi_test:chat@localhost:54321/sushi_chat_test"
)
for db_url in "${db_urls[@]}"; do
psql -f app/server/src/database/ini.sql "$db_url"
cat app/server/src/database/seed/* | psql -f - "$db_url"
done
24 changes: 20 additions & 4 deletions app/server/src/__test__/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,30 @@ describe("機能テスト", () => {
})

describe("room一覧取得", () => {
// NOTE: ルームがコネクションプールの上限数以上ある時に怒るバグが存在したため、それが起こらないことを保証するために
// たくさんルームを作る
beforeAll(async () => {
await Promise.all(
ArrayRange(10).map((n) =>
client
.post("/room")
.send({
title: `かさ増し用ルーム${n + 1}`,
topics: [{ title: "トピック" }],
description: "ルームの説明",
})
.set("Authorization", "Bearer Token"),
),
)
})

test("正常系_管理者がroom一覧を取得", async () => {
const res = await client.get("/room").set("Authorization", "Bearer token")

expect(res.statusCode).toBe(200)
expect(res.body).toStrictEqual<SuccessResponse<RoomModel[]>>({
result: "success",
data: [roomData],
})
expect(res.body.result).toBe("success")
// 新しい順に取得されるので、ダミーでないデータは最後に来る
expect(res.body.data[res.body.data.length - 1]).toStrictEqual(roomData)
})
})

Expand Down
7 changes: 6 additions & 1 deletion app/server/src/domain/admin/IAdminRepository.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import Admin from "./admin"
import { PoolClient } from "pg"

interface IAdminRepository {
createIfNotExist(admin: Admin): void
find(adminId: string): Promise<Admin | null>
selectIdsByRoomId(roomId: string): Promise<string[]>
selectIdsByRoomId(roomId: string, pgClient: PoolClient): Promise<string[]>
selectIdsByRoomIds(
roomIds: string[],
pgClient?: PoolClient, // TODO: remove this arg to avoid appearing of implementation detail in interface
): Promise<Record<string, string[]>> // adminIds per room
}

export default IAdminRepository
7 changes: 6 additions & 1 deletion app/server/src/domain/chatItem/IChatItemRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ import Reaction from "./Reaction"
import Question from "./Question"
import Answer from "./Answer"
import ChatItem from "./ChatItem"
import { PoolClient } from "pg"

interface IChatItemRepository {
saveMessage(message: Message): void
saveReaction(reaction: Reaction): void
saveQuestion(question: Question): void
saveAnswer(answer: Answer): void
find(chatItemId: string): Promise<ChatItem | null>
selectByRoomId(roomId: string): Promise<ChatItem[]>
selectByRoomId(roomId: string, pgClient: PoolClient): Promise<ChatItem[]>
selectByRoomIds(
roomIds: string[],
pgClient?: PoolClient, // TODO: remove this arg to avoid appearing of implementation detail in interface
): Promise<Record<string, ChatItem[]>> // chatItems per room
pinChatItem(chatItem: ChatItem): void
}

Expand Down
1 change: 1 addition & 0 deletions app/server/src/domain/room/IRoomRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import RoomClass from "./Room"

interface IRoomRepository {
find(roomId: string): Promise<RoomClass | null>
findRooms(roomId: string[]): Promise<RoomClass[]>
build(room: RoomClass): void
update(room: RoomClass): void
}
Expand Down
7 changes: 6 additions & 1 deletion app/server/src/domain/stamp/IStampRepository.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import Stamp from "./Stamp"
import { PoolClient } from "pg"

interface IStampRepository {
store(stamp: Stamp): void
count(roomId: string, topicId?: number, userId?: string): Promise<number>
selectByRoomId(roomId: string): Promise<Stamp[]>
selectByRoomId(roomId: string, pgClient: PoolClient): Promise<Stamp[]>
selectByRoomIds(
roomIds: string[],
pgClient?: PoolClient, // TODO: remove this arg to avoid appearing of implementation detail in interface
): Promise<Record<string, Stamp[]>> // stamps per room
}

export default IStampRepository
7 changes: 6 additions & 1 deletion app/server/src/domain/user/IUserRepository.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import User from "./User"
import { PoolClient } from "pg"

interface IUserRepository {
create(user: User): void
find(userId: string): Promise<User | null>
selectByRoomId(roomId: string): Promise<User[]>
selectByRoomId(roomId: string, pgClient: PoolClient): Promise<User[]>
selectByRoomIds(
roomIds: string[],
pgClient?: PoolClient, // TODO: remove this arg to avoid appearing of implementation detail in interface
): Promise<Record<string, User[]>> // users per room
leaveRoom(user: User): void
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ class EphemeralUserRepository implements IUserRepository {
public leaveRoom(user: User): void {
this.users = this.users.filter((u) => u.id !== user.id)
}

public selectByRoomIds(roomIds: string[]): Promise<Record<string, User[]>> {
return Promise.resolve(
roomIds.reduce<Record<string, User[]>>((acc, cur) => {
acc[cur] = this.users.filter((u) => u.roomId === cur)
return acc
}, {}),
)
}
}

export default EphemeralUserRepository
Loading