Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions .env.from-dump
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
IGNORE_SEEDING=true
DONT_EXECUTE_TRIGGERS=true
FROM_DUMP=true
SKIP_CACHE_REBUILD=true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ prisma-local/seeds/productionTxs.csv
paybutton-config.json

dump.sql*
.forever
Comment thread
Fabcien marked this conversation as resolved.
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ dev-from-dump:
$(touch_local_env)
docker compose -f docker-compose-from-dump.yml --env-file .env --env-file .env.local --env-file .env.from-dump up --build -d

stop-dev-from-dump:
docker compose -f docker-compose-from-dump.yml --env-file .env --env-file .env.local --env-file .env.from-dump down

reset-dev-from-dump:
make stop-dev-from-dump && make dev-from-dump

reset-dev-from-dump-keep-db:
docker compose -f docker-compose-from-dump.yml --env-file .env --env-file .env.local --env-file .env.from-dump up --build -d --force-recreate --no-deps paybutton

nuke-dev-from-dump:
docker compose -f docker-compose-from-dump.yml --env-file .env --env-file .env.local --env-file .env.from-dump down -v

logs-dev:
docker logs -f paybutton-dev

Expand Down
4 changes: 4 additions & 0 deletions docker-compose-from-dump.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ services:
- ./scripts/db/init-supertokens-db.sql:/home/mysql/raw_entrypoint/3-init-supertokens-db.sql
- ./scripts/db/prisma-shadow-db-fix.sql:/home/mysql/raw_entrypoint/4-prisma-shadow-db-fix.sql
- ./dump.sql:/home/mysql/raw_entrypoint/5-dump.sql
- paybutton-dump-db-data:/var/lib/mysql

users-service:
container_name: paybutton-users-service
Expand Down Expand Up @@ -69,3 +70,6 @@ services:
- ./redis:/data/redis:z
- ./scripts:/data/scripts
command: sh -c "sed -i 's/\\r//g' ./scripts/redis-start.sh && sh ./scripts/redis-start.sh"

volumes:
paybutton-dump-db-data:
19 changes: 12 additions & 7 deletions redis/paymentCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ export async function * getUserUncachedAddresses (userId: string): AsyncGenerato
}

export const getPaymentList = async (userId: string): Promise<Payment[]> => {
const uncachedAddressStream = getUserUncachedAddresses(userId)
for await (const address of uncachedAddressStream) {
void await CacheSet.addressCreation(address)
if (process.env.SKIP_CACHE_REBUILD === undefined) {
const uncachedAddressStream = getUserUncachedAddresses(userId)
for await (const address of uncachedAddressStream) {
void await CacheSet.addressCreation(address)
}
}
return await getCachedPaymentsForUser(userId)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Expand Down Expand Up @@ -304,6 +306,7 @@ export const clearPaymentCacheForAddress = async (addressString: string): Promis
}

export const initPaymentCache = async (address: Address): Promise<boolean> => {
if (process.env.SKIP_CACHE_REBUILD !== undefined) return false
const cachedKeys = await getCachedWeekKeysForAddress(address.address)
if (cachedKeys.length === 0) {
await CacheSet.addressCreation(address)
Expand All @@ -313,10 +316,12 @@ export const initPaymentCache = async (address: Address): Promise<boolean> => {
}

export async function * getPaymentStream (userId: string): AsyncGenerator<Payment> {
const uncachedAddressStream = getUserUncachedAddresses(userId)
for await (const address of uncachedAddressStream) {
console.log('[CACHE]: Creating cache for address', address.address)
await CacheSet.addressCreation(address)
if (process.env.SKIP_CACHE_REBUILD === undefined) {
const uncachedAddressStream = getUserUncachedAddresses(userId)
for await (const address of uncachedAddressStream) {
console.log('[CACHE]: Creating cache for address', address.address)
await CacheSet.addressCreation(address)
}
}
const userButtonIds: string[] = (await fetchPaybuttonArrayByUserId(userId))
.map(p => p.id)
Expand Down
18 changes: 16 additions & 2 deletions scripts/db-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,25 @@ sed_vars () {
cd /home/mysql/raw_entrypoint || exit

for file in *.sql; do
sed_vars "$file"
if [[ "$file" == *dump* ]]; then
echo "Linking dump file: $file"
ln -s /home/mysql/raw_entrypoint/"$file" /home/mysql/entrypoint/"$file"
else
echo "Copying file $file after seding vars"
sed_vars "$file"
fi
done

cd ../entrypoint/ || exit

for file in *.sql; do
mariadb -u root -p"$MYSQL_ROOT_PASSWORD" < "$file"
if [[ "$file" == *dump* ]]; then
filesize=$(stat -Lc%s "$file" 2>/dev/null || stat -Lf%z "$file" 2>/dev/null)
echo "Importing $file ($(numfmt --to=iec $filesize)) ..."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Quote filesize when calling numfmt.

Unquoted $filesize can trigger argument-splitting/empty-arg behavior; quote it to keep parsing deterministic.

Suggested fix
-        echo "Importing $file ($(numfmt --to=iec $filesize)) ..."
+        echo "Importing $file ($(numfmt --to=iec "$filesize")) ..."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "Importing $file ($(numfmt --to=iec $filesize)) ..."
echo "Importing $file ($(numfmt --to=iec "$filesize")) ..."
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 27-27: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/db-entrypoint.sh` at line 27, The echo line uses unquoted $filesize
when invoking numfmt which can cause word-splitting or empty-argument issues;
update the call in scripts/db-entrypoint.sh so numfmt receives a single argument
by quoting the variable (use "$filesize" instead of $filesize) in the
echo/numfmt pipeline where the import message is printed.

Source: Linters/SAST tools

pv "$file" | mariadb -u root -p"$MYSQL_ROOT_PASSWORD"
else
echo "Importing $file ..."
mariadb -u root -p"$MYSQL_ROOT_PASSWORD" < "$file"
fi
echo "Done importing $file"
done
Comment on lines 24 to 34

@coderabbitai coderabbitai Bot Jun 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Stop on import errors to avoid partial DB initialization.

This loop continues even if mariadb/pv fails, and still logs Done importing ..., which can leave a partially imported database while returning success.

Suggested fix
+set -euo pipefail
+
 for file in *.sql; do
     if [[ "$file" == *dump* ]]; then
         filesize=$(stat -Lc%s "$file" 2>/dev/null || stat -Lf%z "$file" 2>/dev/null)
         echo "Importing $file ($(numfmt --to=iec $filesize)) ..."
-        pv "$file" | mariadb -u root -p"$MYSQL_ROOT_PASSWORD"
+        pv "$file" | mariadb -u root -p"$MYSQL_ROOT_PASSWORD"
     else
         echo "Importing $file ..."
         mariadb -u root -p"$MYSQL_ROOT_PASSWORD" < "$file"
     fi
     echo "Done importing $file"
 done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for file in *.sql; do
mariadb -u root -p"$MYSQL_ROOT_PASSWORD" < "$file"
if [[ "$file" == *dump* ]]; then
filesize=$(stat -Lc%s "$file" 2>/dev/null || stat -Lf%z "$file" 2>/dev/null)
echo "Importing $file ($(numfmt --to=iec $filesize)) ..."
pv "$file" | mariadb -u root -p"$MYSQL_ROOT_PASSWORD"
else
echo "Importing $file ..."
mariadb -u root -p"$MYSQL_ROOT_PASSWORD" < "$file"
fi
echo "Done importing $file"
done
set -euo pipefail
for file in *.sql; do
if [[ "$file" == *dump* ]]; then
filesize=$(stat -Lc%s "$file" 2>/dev/null || stat -Lf%z "$file" 2>/dev/null)
echo "Importing $file ($(numfmt --to=iec $filesize)) ..."
pv "$file" | mariadb -u root -p"$MYSQL_ROOT_PASSWORD"
else
echo "Importing $file ..."
mariadb -u root -p"$MYSQL_ROOT_PASSWORD" < "$file"
fi
echo "Done importing $file"
done
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 27-27: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/db-entrypoint.sh` around lines 24 - 34, The loop that imports SQL
files (the for file in *.sql; do block) ignores failures from the mariadb and pv
pipelines and still prints "Done importing $file", risking partial DB
initialization; modify the script to enable strict failure handling (e.g., set
-euo pipefail) or explicitly check the command exit statuses after each import
command (both pv "$file" | mariadb -u root -p"$MYSQL_ROOT_PASSWORD" and mariadb
-u root -p"$MYSQL_ROOT_PASSWORD" < "$file") and if a command fails, print an
error with the file name and exit non‑zero immediately instead of printing "Done
importing $file".

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set -euo pipefail at the top of the script is a good idea

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Fabcien, agreed! One small note: placing it at line 2 (right after #!/bin/bash) is even better than just before the second loop, so both the first and second loops are covered.

 #!/bin/bash
+set -euo pipefail
 
 vars="MYSQL_USER MYSQL_PASSWORD ...

One thing to watch out for with -e enabled: the ln -s call in the first loop will fail if the symlink already exists (e.g., on a container restart with a persistent named volume). Switching to ln -sf (force) avoids that:

-      ln -s /home/mysql/raw_entrypoint/"$file" /home/mysql/entrypoint/"$file"
+      ln -sf /home/mysql/raw_entrypoint/"$file" /home/mysql/entrypoint/"$file"

The pipefail part is particularly important for the pv "$file" | mariadb ... pipeline — without it, only mariadb's exit code is checked and a pv read error would be silently swallowed.

4 changes: 2 additions & 2 deletions scripts/db/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ FROM mariadb:latest

RUN mkhomedir_helper mysql

RUN apt-get update || echo && \
apt-get install -y gettext || echo
RUN apt-get update || true && \
apt-get install -y gettext pv || true

RUN mkdir -p /home/mysql/raw_entrypoint && \
mkdir -p /home/mysql/entrypoint
Expand Down
14 changes: 8 additions & 6 deletions scripts/paybutton-server-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ logtime=$(date +%Y-%m-%d@%H:%M)
[ -e logs/jobs.log ] && mv logs/jobs.log logs/history/jobs_"$logtime".log
[ -e logs/ws-server.log ] && mv logs/ws-server.log logs/history/ws-server_"$logtime".log

if [ "$ENVIRONMENT" = "production" ]; then
if [ "$FROM_DUMP" = "true" ] || [ "$ENVIRONMENT" = "production" ]; then
yarn prisma migrate deploy || exit 1
yarn prisma generate || exit 1
pm2 start yarn --time --interpreter ash --name jobs --output logs/jobs.log --error logs/jobs.log -- initJobs || exit 1
pm2 start yarn --time --interpreter ash --name WSServer --output logs/ws-server.log --error logs/ws-server.log -- initWSServer || exit 1
pm2 start yarn --time --interpreter ash --name next --output logs/next.log --error logs/next.log -- prod || exit 1
else
yarn prisma migrate dev || exit 1
yarn prisma db seed || exit 1
pm2 start yarn --time --interpreter ash --name jobs --output logs/jobs.log --error logs/jobs.log -- initJobs || exit 1
pm2 start yarn --time --interpreter ash --name WSServer --output logs/ws-server.log --error logs/ws-server.log -- initWSServer || exit 1
fi

pm2 start yarn --time --interpreter ash --name jobs --output logs/jobs.log --error logs/jobs.log -- initJobs || exit 1
pm2 start yarn --time --interpreter ash --name WSServer --output logs/ws-server.log --error logs/ws-server.log -- initWSServer || exit 1
if [ "$ENVIRONMENT" = "production" ]; then
pm2 start yarn --time --interpreter ash --name next --output logs/next.log --error logs/next.log -- prod || exit 1
else
pm2 start yarn --time --interpreter ash --name next --output logs/next.log --error logs/next.log -- dev || exit 1
fi
pm2 logs next
Loading