Skip to content

Commit d6c5e92

Browse files
committed
Merge branch 'main' of github.com:CS3219-AY2425S1/cs3219-ay2425s1-project-g16 into PEER-232-Match-Initiation-UI
Signed-off-by: SeeuSim <[email protected]>
2 parents 1747c76 + 5ad131a commit d6c5e92

File tree

8 files changed

+253
-3
lines changed

8 files changed

+253
-3
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
name: Build & publish PeerPrep images
2+
on:
3+
pull_request:
4+
types: [review_requested, ready_for_review]
5+
push:
6+
branches:
7+
- main
8+
9+
env:
10+
DOCKER_REGISTRY_USN: ay2425s1cs3219g16
11+
USER_EXPRESS_PORT: 9001
12+
QUESTION_EXPRESS_PORT: 9002
13+
COLLAB_EXPRESS_PORT: 9003
14+
MATCH_EXPRESS_PORT: 9004
15+
FRONTEND_PORT: 3000
16+
17+
jobs:
18+
changes:
19+
runs-on: ubuntu-latest
20+
# Required permissions
21+
permissions:
22+
pull-requests: read
23+
# Set job outputs to values from filter step
24+
outputs:
25+
matrix: ${{ steps.set-matrix.outputs.matrix }} # Output the matrix as a JSON string
26+
steps:
27+
- uses: actions/checkout@v4
28+
if: contains(github.ref, 'main')
29+
# For pull requests it's not necessary to checkout the code
30+
- uses: dorny/paths-filter@v3
31+
id: filter
32+
with:
33+
filters: |
34+
user:
35+
- 'backend/user/**'
36+
question:
37+
- 'backend/question/**'
38+
collaboration:
39+
- 'backend/collaboration/**'
40+
matching:
41+
- 'backend/matching/**'
42+
frontend:
43+
- 'frontend/**'
44+
- name: output-job-matrix
45+
id: set-matrix
46+
run: |
47+
is_main=${{ contains(github.ref, 'main') }}
48+
matrix=()
49+
if [[ "${{ steps.filter.outputs.user }}" == "true" || "$is_main" == "true" ]]; then
50+
config=$(jq -n \
51+
--arg pkg "user" \
52+
--arg img "$DOCKER_REGISTRY_USN/user-express" \
53+
--arg ctx "./backend/user" \
54+
--arg dkr "./backend/user/express.Dockerfile" \
55+
--arg bag "port=$USER_EXPRESS_PORT" \
56+
'{package: $pkg, image: $img, context: $ctx, dockerfile: $dkr, "build-args": $bag}')
57+
matrix+=("$config")
58+
fi
59+
if [[ "${{ steps.filter.outputs.question }}" == "true" || "$is_main" == "true" ]]; then
60+
config=$(jq -n \
61+
--arg pkg "question" \
62+
--arg img "$DOCKER_REGISTRY_USN/question-express" \
63+
--arg ctx "./backend/question" \
64+
--arg dkr "./backend/question/express.Dockerfile" \
65+
--arg bag "port=$QUESTION_EXPRESS_PORT" \
66+
'{package: $pkg, image: $img, context: $ctx, dockerfile: $dkr, "build-args": $bag}')
67+
matrix+=("$config")
68+
fi
69+
if [[ "${{ steps.filter.outputs.collaboration }}" == "true" || "$is_main" == "true" ]]; then
70+
config=$(jq -n \
71+
--arg pkg "collaboration" \
72+
--arg img "$DOCKER_REGISTRY_USN/collab-express" \
73+
--arg ctx "./backend/collaboration" \
74+
--arg dkr "./backend/collaboration/express.Dockerfile" \
75+
--arg bag "port=$COLLAB_EXPRESS_PORT" \
76+
'{package: $pkg, image: $img, context: $ctx, dockerfile: $dkr, "build-args": $bag}')
77+
matrix+=("$config")
78+
fi
79+
if [[ "${{ steps.filter.outputs.matching }}" == "true" || "$is_main" == "true" ]]; then
80+
config=$(jq -n \
81+
--arg pkg "matching" \
82+
--arg img "$DOCKER_REGISTRY_USN/match-express" \
83+
--arg ctx "./backend/matching" \
84+
--arg dkr "./backend/matching/express.Dockerfile" \
85+
--arg bag "port=$MATCH_EXPRESS_PORT" \
86+
'{package: $pkg, image: $img, context: $ctx, dockerfile: $dkr, "build-args": $bag}')
87+
matrix+=("$config")
88+
fi
89+
if [[ "${{ steps.filter.outputs.frontend }}" == "true" || "$is_main" == "true" ]]; then
90+
config=$(jq -n \
91+
--arg pkg "frontend" \
92+
--arg img "$DOCKER_REGISTRY_USN/frontend" \
93+
--arg ctx "./frontend" \
94+
--arg dkr "./frontend/frontend.Dockerfile" \
95+
--arg bag "port=$FRONTEND_PORT" \
96+
'{package: $pkg, image: $img, context: $ctx, dockerfile: $dkr, "build-args": $bag}')
97+
matrix+=("$config")
98+
fi
99+
formatted_matrix=$(echo "${matrix[@]}" | jq -cs .)
100+
echo "Outputs Generated: $formatted_matrix"
101+
echo "matrix=$formatted_matrix" >> $GITHUB_OUTPUT
102+
103+
build-and-push-image:
104+
needs: changes
105+
if: ${{ fromJson(needs.changes.outputs.matrix)[0] != null }}
106+
runs-on: ubuntu-latest
107+
strategy:
108+
fail-fast: false
109+
matrix:
110+
include: ${{ fromJson(needs.changes.outputs.matrix) }} # Use the matrix from the first job
111+
# - package: user
112+
# image: ay2425s1cs3219g16/user-express
113+
# context: ./backend/user
114+
# dockerfile: ./backend/user/express.Dockerfile
115+
# build-args: |
116+
# port=9001
117+
# - package: question
118+
# image: ay2425s1cs3219g16/question-express
119+
# context: ./backend/question
120+
# dockerfile: ./backend/question/express.Dockerfile
121+
# build-args: |
122+
# port=9002
123+
# - package: collaboration
124+
# image: ay2425s1cs3219g16/collab-express
125+
# context: ./backend/collaboration
126+
# dockerfile: ./backend/collaboration/express.Dockerfile
127+
# build-args: |
128+
# port=9003
129+
# - package: matching
130+
# image: ay2425s1cs3219g16/match-express
131+
# context: ./backend/matching
132+
# dockerfile: ./backend/matching/express.Dockerfile
133+
# build-args: |
134+
# port=9004
135+
# - package: frontend
136+
# image: ay2425s1cs3219g16/frontend
137+
# context: ./frontend
138+
# dockerfile: ./frontend/frontend.Dockerfile
139+
# build-args: |
140+
# port=3000
141+
permissions:
142+
contents: read
143+
packages: write
144+
145+
steps:
146+
- name: Checkout repository
147+
uses: actions/checkout@v4
148+
149+
- name: Set up QEMU
150+
uses: docker/setup-qemu-action@v3
151+
152+
- name: Set up Docker Buildx
153+
uses: docker/setup-buildx-action@v3
154+
155+
- name: Log in to the Container registry
156+
uses: docker/login-action@v3
157+
with:
158+
username: ${{ secrets.DOCKER_USERNAME }}
159+
password: ${{ secrets.DOCKER_PASSWORD }}
160+
161+
- name: Extract metadata (tags, labels) for Docker
162+
id: meta
163+
uses: docker/metadata-action@v5
164+
with:
165+
images: ${{ matrix.image }}
166+
167+
- name: Build and push Docker images for PeerPrep Services
168+
uses: docker/build-push-action@v6
169+
with:
170+
platforms: linux/amd64,linux/arm64
171+
context: ${{ matrix.context }}
172+
file: ${{ matrix.dockerfile }}
173+
build-args: ${{ matrix.build-args }}
174+
push: true
175+
tags: ${{ steps.meta.outputs.tags }}
176+
labels: ${{ steps.meta.outputs.labels }}
177+
cache-from: type=gha
178+
cache-to: type=gha,mode=max

.github/workflows/clear-cache.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Cleanup caches after merge
2+
on:
3+
pull_request:
4+
types:
5+
- closed
6+
workflow_dispatch:
7+
8+
jobs:
9+
cleanup:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
# `actions:write` permission is required to delete caches
13+
# See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id
14+
actions: write
15+
contents: read
16+
17+
steps:
18+
- name: Check out code
19+
uses: actions/checkout@v4
20+
21+
- name: Cleanup cache
22+
run: |
23+
gh extension install actions/gh-actions-cache
24+
25+
REPO=${{ github.repository }}
26+
BRANCH=refs/pull/${{ github.event.pull_request.number }}/merge
27+
28+
echo "Fetching list of cache key"
29+
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH --limit 100 --sort size | cut -f 1 )
30+
31+
## Setting this to not fail the workflow while deleting cache keys.
32+
set +e
33+
echo "Deleting caches..."
34+
for cacheKey in $cacheKeysForPR
35+
do
36+
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
37+
done
38+
echo "Done"
39+
env:
40+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

backend/matching/src/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ export const DB_URL = `redis://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOSTNAME}:${DB
1212
// export const DB_URL = `redis://${DB_HOSTNAME}:${DB_PORT}`;
1313

1414
export const NODE_ENV = process.env.NODE_ENV;
15+
16+
export const IS_MILESTONE_D4 = true;

backend/matching/src/controllers/match-request.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { Request, Response } from 'express';
22
import { StatusCodes } from 'http-status-codes';
33

4-
import { client } from '@/lib/db';
4+
import { client, logQueueStatus } from '@/lib/db';
55
import type { IRedisClient, IRequestMatchPayload } from '@/types';
66
import { createNotifSocket, queueingService } from '@/services';
7+
import { logger } from '@/lib/utils';
78

89
let redisClient: IRedisClient;
910
export const matchRequestController = async (req: Request, res: Response) => {
@@ -38,4 +39,6 @@ export const matchRequestController = async (req: Request, res: Response) => {
3839
socketPort: socketRoom,
3940
timestamp,
4041
});
42+
43+
logQueueStatus(logger, redisClient, `Queue Status Before Matching: <PLACEHOLDER>`);
4144
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './client';
2+
export * from './log-queue-status';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { IS_MILESTONE_D4 } from '@/config';
2+
3+
import { client } from './client';
4+
import { STREAM_NAME } from './constants';
5+
6+
export const getQueueStatusLog = async (redisClient: typeof client) => {
7+
const queueStatus = await redisClient.xRange(STREAM_NAME, '-', '+');
8+
const messages = queueStatus.map((v) => v.message);
9+
return JSON.stringify(messages);
10+
};
11+
12+
export const logQueueStatus = async (
13+
// eslint-disable-next-line
14+
logger: { info: (...m: any[]) => void },
15+
redisClient: typeof client,
16+
message: string
17+
) => {
18+
if (!IS_MILESTONE_D4) {
19+
return;
20+
}
21+
const queueStatusLog = await getQueueStatusLog(redisClient);
22+
logger.info(message.replace('<PLACEHOLDER>', queueStatusLog));
23+
};

backend/matching/src/workers/cleaner.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { client } from '@/lib/db';
1+
import { client, logQueueStatus } from '@/lib/db';
22
import { STREAM_CLEANER, STREAM_GROUP, STREAM_NAME } from '@/lib/db/constants';
33
import { decodePoolTicket, getPoolKey } from '@/lib/utils';
44
import { MATCH_SVC_EVENT } from '@/ws';
@@ -64,6 +64,8 @@ async function clean() {
6464
sendNotif([socketRoom], MATCH_SVC_EVENT.FAILED);
6565
sendNotif([socketRoom], MATCH_SVC_EVENT.DISCONNECT);
6666
}
67+
68+
await logQueueStatus(logger, redisClient, `Queue Status after Expiring Request: <PLACEHOLDER>`);
6769
}
6870
}
6971

backend/matching/src/workers/matcher.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { client } from '@/lib/db';
1+
import { client, logQueueStatus } from '@/lib/db';
22
import { POOL_INDEX, STREAM_GROUP, STREAM_NAME, STREAM_WORKER } from '@/lib/db/constants';
33
import { decodePoolTicket, getPoolKey, getStreamId } from '@/lib/utils';
44
import { getMatchItems } from '@/services';
@@ -76,6 +76,7 @@ async function processMatch(
7676
setTimeout(() => {
7777
sendMatchLogic(requestorSocketPort);
7878
}, 1000);
79+
await logQueueStatus(logger, redisClient, `Queue Status After Matching: <PLACEHOLDER>`);
7980
return true;
8081
}
8182
}

0 commit comments

Comments
 (0)