Skip to content

Commit a69948d

Browse files
pyphiliaspaenleh
andauthored
feat: workers for export item as zip (import export refactor) (#1891)
* feat: initialize worker for export item as zip, import export refactor * refactor: fix lint * fix: set worker as class var and use logger in error * fix: add color to worker output on watch * chore: change name of server process * chore: ensure that localfile is accessible from inside and outside the server * fix: add export extension * build: docker file first version * fix: dockerfile for workers * fix: redis connection * chore: change building of core image * fix: changes to the compose file * fix: add workers build in build script * fix: make small adjustments * fix: update deps to fix issues and lint problems * fix: tests * fix: do not expose the bashboard when mode is not dev * fix: add tests to the worker using vitest * fix: move vitest to build * fix: cleanup code * fix: add more test cases * fix: make changes required by review * fix: build issue --------- Co-authored-by: spaenleh <spaenleh@gmail.com>
1 parent 81f8d4b commit a69948d

36 files changed

Lines changed: 2014 additions & 948 deletions

.devcontainer/docker-compose.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ services:
1818
# temporary storage for files inside the container
1919
FILE_STORAGE_ROOT_PATH: /tmp/graasp-file-item-storage
2020
# the localfile config host points to the static file server defined below
21-
FILE_STORAGE_HOST: http://localhost:1081
21+
FILE_STORAGE_HOST: http://localfile:1081
2222
# H5P local storage host used in local only
23-
H5P_FILE_STORAGE_HOST: http://localhost:1081
23+
H5P_FILE_STORAGE_HOST: http://localfile:1081
2424
# endpoint of the nudenet model
2525
IMAGE_CLASSIFIER_API: http://nudenet:8080/sync
2626
# the DB config is set by the "db" service below
@@ -156,12 +156,12 @@ services:
156156
environment:
157157
# Note: those envs are customizable but also optional
158158
# - SERVER_HOST=127.0.0.1
159-
- SERVER_PORT=80
159+
- SERVER_PORT=1081
160160
- SERVER_ROOT=/tmp/graasp-file-item-storage
161161
volumes:
162162
- ../tmp:/tmp/graasp-file-item-storage
163163
ports:
164-
- 1081:80
164+
- 1081:1081
165165

166166
# necessary for graasp-embedded-link-item
167167
iframely:

.eslintrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
"error",
2828
{
2929
"devDependencies": [
30+
"vitest.config.ts",
3031
"**/*.test.*",
32+
"**/*.spec.*",
3133
"**/test/*",
3234
"**/test/**/*"
3335
]

.github/workflows/deploy-prod.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
environment-variables: |
9898
DB_CONNECTION_POOL_SIZE=${{ vars.DB_CONNECTION_POOL_SIZE }}
9999
APPS_JWT_SECRET=${{ secrets.APPS_JWT_SECRET }}
100-
APPS_PUBLISHER_ID=${{ secrets.APPS_PUBLISHER_ID }}
100+
APPS_PUBLISHER_ID=${{ secrets.APPS_PUBLISHER_ID }}
101101
AUTH_TOKEN_JWT_SECRET=${{ secrets.AUTH_TOKEN_JWT_SECRET }}
102102
CLIENT_HOST=${{ vars.CLIENT_HOST }}
103103
COOKIE_DOMAIN=${{ vars.COOKIE_DOMAIN }}
@@ -118,22 +118,21 @@ jobs:
118118
H5P_PATH_PREFIX=${{ vars.H5P_PATH_PREFIX }}
119119
HOSTNAME=${{ vars.HOSTNAME }}
120120
IMAGE_CLASSIFIER_API=${{ vars.IMAGE_CLASSIFIER_API }}
121-
JOB_SCHEDULING=${{ vars.JOB_SCHEDULING || false }}
122121
JWT_SECRET=${{ secrets.JWT_SECRET }}
123122
PASSWORD_RESET_JWT_SECRET=${{ secrets.PASSWORD_RESET_JWT_SECRET }}
124123
EMAIL_CHANGE_JWT_SECRET=${{ secrets.EMAIL_CHANGE_JWT_SECRET }}
125124
LIBRARY_CLIENT_HOST=${{ vars.LIBRARY_CLIENT_HOST }}
126125
LOG_LEVEL=${{ vars.LOG_LEVEL }}
127126
MAILER_CONFIG_FROM_EMAIL=${{ secrets.MAILER_CONFIG_FROM_EMAIL }}
128-
MAILER_CONNECTION=${{ secrets.MAILER_CONNECTION }}
127+
MAILER_CONNECTION=${{ secrets.MAILER_CONNECTION }}
129128
MEILISEARCH_MASTER_KEY=${{ secrets.MEILISEARCH_MASTER_KEY }}
130129
MEILISEARCH_REBUILD_SECRET=${{ secrets.MEILISEARCH_REBUILD_SECRET }}
131130
MEILISEARCH_URL=${{ secrets.MEILISEARCH_URL }}
132131
NODE_ENV=${{ vars.NODE_ENV }}
133132
PORT=${{ vars.PORT }}
134133
PUBLIC_URL=${{ secrets.PUBLIC_URL }}
135134
RECAPTCHA_SECRET_ACCESS_KEY=${{ secrets.RECAPTCHA_SECRET_ACCESS_KEY }}
136-
REDIS_CONNECTION=${{ secrets.REDIS_CONNECTION }}
135+
REDIS_CONNECTION=${{ secrets.REDIS_CONNECTION }}
137136
REFRESH_TOKEN_JWT_SECRET=${{ secrets.REFRESH_TOKEN_JWT_SECRET }}
138137
S3_FILE_ITEM_ACCESS_KEY_ID=${{ secrets.S3_FILE_ITEM_ACCESS_KEY_ID }}
139138
S3_FILE_ITEM_BUCKET=${{ vars.S3_FILE_ITEM_BUCKET }}

.github/workflows/deploy-stage.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
environment-variables: |
9898
DB_CONNECTION_POOL_SIZE=${{ vars.DB_CONNECTION_POOL_SIZE }}
9999
APPS_JWT_SECRET=${{ secrets.APPS_JWT_SECRET }}
100-
APPS_PUBLISHER_ID=${{ secrets.APPS_PUBLISHER_ID }}
100+
APPS_PUBLISHER_ID=${{ secrets.APPS_PUBLISHER_ID }}
101101
AUTH_TOKEN_JWT_SECRET=${{ secrets.AUTH_TOKEN_JWT_SECRET }}
102102
CLIENT_HOST=${{ vars.CLIENT_HOST }}
103103
COOKIE_DOMAIN=${{ vars.COOKIE_DOMAIN }}
@@ -119,22 +119,21 @@ jobs:
119119
H5P_PATH_PREFIX=${{ vars.H5P_PATH_PREFIX }}
120120
HOSTNAME=${{ vars.HOSTNAME }}
121121
IMAGE_CLASSIFIER_API=${{ vars.IMAGE_CLASSIFIER_API }}
122-
JOB_SCHEDULING=${{ vars.JOB_SCHEDULING || false }}
123122
JWT_SECRET=${{ secrets.JWT_SECRET }}
124123
PASSWORD_RESET_JWT_SECRET=${{ secrets.PASSWORD_RESET_JWT_SECRET }}
125124
EMAIL_CHANGE_JWT_SECRET=${{ secrets.EMAIL_CHANGE_JWT_SECRET }}
126125
LIBRARY_CLIENT_HOST=${{ vars.LIBRARY_CLIENT_HOST }}
127126
LOG_LEVEL=${{ vars.LOG_LEVEL }}
128127
MAILER_CONFIG_FROM_EMAIL=${{ secrets.MAILER_CONFIG_FROM_EMAIL }}
129-
MAILER_CONNECTION=${{ secrets.MAILER_CONNECTION }}
128+
MAILER_CONNECTION=${{ secrets.MAILER_CONNECTION }}
130129
MEILISEARCH_MASTER_KEY=${{ secrets.MEILISEARCH_MASTER_KEY }}
131130
MEILISEARCH_REBUILD_SECRET=${{ secrets.MEILISEARCH_REBUILD_SECRET }}
132131
MEILISEARCH_URL=${{ secrets.MEILISEARCH_URL }}
133132
NODE_ENV=${{ vars.NODE_ENV }}
134133
PORT=${{ vars.PORT }}
135134
PUBLIC_URL=${{ secrets.PUBLIC_URL }}
136135
RECAPTCHA_SECRET_ACCESS_KEY=${{ secrets.RECAPTCHA_SECRET_ACCESS_KEY }}
137-
REDIS_CONNECTION=${{ secrets.REDIS_CONNECTION }}
136+
REDIS_CONNECTION=${{ secrets.REDIS_CONNECTION }}
138137
REFRESH_TOKEN_JWT_SECRET=${{ secrets.REFRESH_TOKEN_JWT_SECRET }}
139138
S3_FILE_ITEM_ACCESS_KEY_ID=${{ secrets.S3_FILE_ITEM_ACCESS_KEY_ID }}
140139
S3_FILE_ITEM_BUCKET=${{ vars.S3_FILE_ITEM_BUCKET }}

.github/workflows/test.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ env:
5151
SECURE_SESSION_SECRET_KEY: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
5252
MEILISEARCH_URL: fake
5353
MEILISEARCH_MASTER_KEY: fake
54-
JOB_SCHEDULING: false
5554
GEOLOCATION_API_KEY: geolocation-key
5655
GEOLOCATION_API_HOST: http://localhost:12345
5756

@@ -79,6 +78,20 @@ jobs:
7978
--health-timeout 5s
8079
--health-retries 5
8180
81+
# Label used to access the service container
82+
graasp-redis:
83+
# Docker Hub image
84+
image: redis
85+
ports:
86+
# Opens tcp port 6379 on the host and service container
87+
- 6379:6379
88+
# Set health checks to wait until redis has started
89+
options: >-
90+
--health-cmd "redis-cli ping"
91+
--health-interval 10s
92+
--health-timeout 5s
93+
--health-retries 5
94+
8295
steps:
8396
- uses: actions/checkout@v4
8497

@@ -113,6 +126,9 @@ jobs:
113126
- name: check migrations are up to date
114127
run: yarn migration:check
115128

129+
- name: vitest tests
130+
run: yarn vitest
131+
116132
test-node:
117133
needs: build-node
118134
strategy:

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,6 @@ MEILISEARCH_URL=http://meilisearch:7700
216216
MEILISEARCH_MASTER_KEY=masterKey
217217
MEILISEARCH_REBUILD_SECRET=secret
218218

219-
# Enable job scheduling (for cron based tasks)
220-
JOB_SCHEDULING=true
221-
222219
# OPEN AI
223220
# OPENAI_GPT_VERSION=<DEFAULT_GPT_VERSION> # valid values are gpt-4 or gpt-3.5-turbo
224221
OPENAI_API_KEY=<openai-api-key>

docker/Dockerfile

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,43 @@
1-
# Production Docker backend image definition
2-
# Used in CI for creating images to push on registry
1+
FROM node:22.15-bookworm AS base
32

4-
# Update the NODE_VERSION arg in docker-compose.yml to pick a Node version of Docker Image
5-
ARG NODE_VERSION=22.14.0
63

74
##############################
85
### Build Application Step ###
96
##############################
107
# This step will build the application
11-
FROM node:${NODE_VERSION} AS build
8+
FROM base AS tools
129

1310
# update packages and install the minimal init system "dumb-init"
1411
RUN apt-get update && apt-get install -y --no-install-recommends dumb-init
1512

13+
14+
# -------------------------------------------------------
15+
FROM base AS build
16+
1617
WORKDIR /app
17-
COPY . .
18-
RUN yarn set version berry && yarn install
18+
COPY package.json yarn.lock .yarnrc.yml ./
19+
# We need a specific command because we need to copy the folder with it, not just the content.
20+
COPY .yarn/releases ./.yarn/releases/
21+
RUN yarn set version berry && yarn install --immutable
1922

23+
ENV NODE_ENV=production
24+
COPY . .
2025
RUN yarn build-ts
2126

22-
ENV NODE_ENV=production
27+
# -------------------------------------------------------
28+
FROM base AS deps
2329

24-
# Delete old node_modules and re-install only production dependencies
25-
RUN rm -rf node_modules && yarn workspaces focus --all --production
30+
WORKDIR /app
31+
COPY package.json yarn.lock .yarnrc.yml ./
32+
# We need a specific command because we need to copy the folder with it, not just the content.
33+
COPY .yarn/releases ./.yarn/releases/
34+
RUN yarn set version berry && yarn workspaces focus --all --production
2635

2736
############################
2837
### Run Application Step ###
2938
############################
3039
# Final step that will run the application
31-
FROM node:${NODE_VERSION}-bookworm-slim AS runner
40+
FROM node:22.15-bookworm-slim AS runner
3241

3342
# Variable passed as a build arg. Represents the tag or git sha used for the build
3443
ARG APP_VERSION
@@ -45,10 +54,10 @@ EXPOSE 3000
4554
WORKDIR /app
4655

4756
# Copy the installed dumb-init system from build image
48-
COPY --from=build /usr/bin/dumb-init /usr/bin/dumb-init
57+
COPY --from=tools /usr/bin/dumb-init /usr/bin/dumb-init
4958

5059
# Copy the dependencies and compiled server code
51-
COPY --chown=node:node --from=build ./app/node_modules ./node_modules
60+
COPY --chown=node:node --from=deps ./app/node_modules ./node_modules
5261
COPY --chown=node:node --from=build ./app/dist ./dist
5362

5463
# Set user to be non-root node

docker/build.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,17 @@ tag_version=$2
3131
core_tag_short="graasp:core-$tag_version"
3232
core_tag_full="$aws_ecr_uri/$core_tag_short"
3333

34+
workers_tag_short="graasp:workers-$tag_version"
35+
workers_tag_full="$aws_ecr_uri/$workers_tag_short"
36+
3437
migrate_tag_short="graasp:migrate-$tag_version"
3538
migrate_tag_full="$aws_ecr_uri/$migrate_tag_short"
3639

3740
docker build -t $core_tag_full -f docker/Dockerfile --platform linux/amd64 --build-arg APP_VERSION=$tag_version --build-arg BUILD_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S) .
3841
docker push $core_tag_full
3942

43+
docker build -t $workers_tag_full -f docker/workers.Dockerfile --platform linux/amd64 --build-arg APP_VERSION=$tag_version --build-arg BUILD_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S) .
44+
docker push $workers_tag_full
45+
4046
docker build -t $migrate_tag_full -f docker/migrate.Dockerfile --platform linux/amd64 .
4147
docker push $migrate_tag_full

0 commit comments

Comments
 (0)