From 37b16ebe5f33258d4aa5b07e85992438a14f38e2 Mon Sep 17 00:00:00 2001 From: merlin Date: Thu, 14 May 2026 22:45:35 +0800 Subject: [PATCH] feat: add ci & fix some bug --- .dockerignore | 1 + .gitea/workflows/main.yaml | 35 +++++++++++++++++++ .gitea/workflows/tag.yaml | 34 ++++++++++++++++++ .gitignore | 1 + Dockerfile | 34 ++++++++++++++++++ .../websocket/OnlineWebSocketHandler.java | 1 + .../OnlineWebSocketSessionManager.java | 25 +++++++++++++ 7 files changed, 131 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/main.yaml create mode 100644 .gitea/workflows/tag.yaml create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ae0304e --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +src/main/resources/application.yml \ No newline at end of file diff --git a/.gitea/workflows/main.yaml b/.gitea/workflows/main.yaml new file mode 100644 index 0000000..669b73a --- /dev/null +++ b/.gitea/workflows/main.yaml @@ -0,0 +1,35 @@ +name: Docker Image CI +on: + push: + branches: + - main + +jobs: + build: + runs-on: gitea-runner-group-myplayer + container: + image: ${{ vars.HARBOR_URL }}/candlelight/action_builder:v0.0.2 + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: docker login + env: + HARBOR_USERNAME: ${{ secrets.HARBOR_ROBOT }} + HARBOR_PASSWORD: ${{ secrets.HARBOR_ROBOT_SECRET }} + HARBOR_URL: ${{ vars.HARBOR_URL }} + run: docker login ${HARBOR_URL} -u ${HARBOR_USERNAME} -p ${HARBOR_PASSWORD} + - name: Build and push Docker images + env: + HARBOR_URL: ${{ vars.HARBOR_URL }} + TAG: ${{ github.sha }} + REPOSITORY: ${{ github.repository }} + run: | + ROOT_DIR=$(pwd) + IMAGE_NAME="${HARBOR_URL}/testing/$REPOSITORY:${TAG}" + echo "Building image: ${IMAGE_NAME}" + docker build -t ${IMAGE_NAME} . + echo "Pushing image: ${IMAGE_NAME}" + docker push ${IMAGE_NAME} + echo "Successfully pushed: ${IMAGE_NAME}" + docker rmi ${IMAGE_NAME} + echo "cleaned up local image" diff --git a/.gitea/workflows/tag.yaml b/.gitea/workflows/tag.yaml new file mode 100644 index 0000000..ce0f1e6 --- /dev/null +++ b/.gitea/workflows/tag.yaml @@ -0,0 +1,34 @@ +name: Docker Image CI +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: gitea-runner-group-myplayer + container: + image: ${{ vars.HARBOR_URL }}/candlelight/action_builder:v0.0.2 + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: docker login + env: + HARBOR_USERNAME: ${{ secrets.HARBOR_ROBOT }} + HARBOR_PASSWORD: ${{ secrets.HARBOR_ROBOT_SECRET }} + HARBOR_URL: ${{ vars.HARBOR_URL }} + run: docker login ${HARBOR_URL} -u ${HARBOR_USERNAME} -p ${HARBOR_PASSWORD} + - name: Build and push Docker images + env: + HARBOR_URL: ${{ vars.HARBOR_URL }} + REPOSITORY: ${{ github.repository }} + run: | + ROOT_DIR=$(pwd) + IMAGE_NAME="${HARBOR_URL}/$REPOSITORY:$GITHUB_REF_NAME" + echo "Building image: ${IMAGE_NAME}" + docker build -t ${IMAGE_NAME} . + echo "Pushing image: ${IMAGE_NAME}" + docker push ${IMAGE_NAME} + echo "Successfully pushed: ${IMAGE_NAME}" + docker rmi ${IMAGE_NAME} + echo "cleaned up local image" diff --git a/.gitignore b/.gitignore index 3d1e9b3..91bd998 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ src/main/resources/application.yaml *.iws *.iml *.ipr +src/main/resources/application.yml ### NetBeans ### /nbproject/private/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f89e1fc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +# ===== build stage ===== +FROM registry.merlin.xin/library/maven:4.0.0-rc-5-eclipse-temurin-17 AS builder + +WORKDIR /app +COPY pom.xml . +RUN --mount=type=cache,target=/root/.m2 mvn -B -q dependency:go-offline + +COPY . . +RUN --mount=type=cache,target=/root/.m2 mvn -B -q package -DskipTests + + +# ===== runtime stage ===== +FROM registry.merlin.xin/library/eclipse-temurin:17-jre-alpine + +# >>> Install debug tools <<< +#RUN apk update && apk add --no-cache \ +# curl \ +# bind-tools \ +# busybox-extras \ +# iproute2 \ +# tcpdump \ +# net-tools + +WORKDIR /app +COPY --from=builder /app/target/*.jar app.jar + +RUN addgroup -S spring && adduser -S spring -G spring + +RUN mkdir -p /app/uploads/photo \ + && chown -R spring:spring /app/uploads + +USER spring + +ENTRYPOINT ["java","-jar","/app/app.jar","--spring.config.location=file:/app/application.yml"] diff --git a/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketHandler.java b/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketHandler.java index 892a232..ea82e91 100644 --- a/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketHandler.java +++ b/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketHandler.java @@ -39,6 +39,7 @@ public class OnlineWebSocketHandler extends TextWebSocketHandler { onlineStatusService.online(userId); sessionManager.addSession(userId, session); + sessionManager.getMessages(userId); log.info("用户 {} 已连接", userId); } diff --git a/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketSessionManager.java b/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketSessionManager.java index bb9ffe7..3800859 100644 --- a/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketSessionManager.java +++ b/src/main/java/xin/merlin/myplayerbackend/utils/websocket/OnlineWebSocketSessionManager.java @@ -1,18 +1,27 @@ package xin.merlin.myplayerbackend.utils.websocket; +import lombok.AllArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import java.io.IOException; +import java.util.ArrayList; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Component +@AllArgsConstructor public class OnlineWebSocketSessionManager { + private static final String MESSAGE_WAITING_LIST = "message:"; + + private final StringRedisTemplate redis; + private static final Map websocketSessions = new ConcurrentHashMap<>(); public void addSession(Integer id, WebSocketSession session) {websocketSessions.put(id, session);} @@ -23,10 +32,26 @@ public class OnlineWebSocketSessionManager { public Map getSessions() {return websocketSessions;} + public void getMessages(Integer userId) throws IOException { + WebSocketSession session = websocketSessions.get(userId); + String message = redis.opsForList().leftPop(MESSAGE_WAITING_LIST + userId); + do { + if (message != null) { + session.sendMessage(new TextMessage(message)); + message = redis.opsForList().leftPop(MESSAGE_WAITING_LIST + userId); + }else { + break; + } + } + while (message!=null); + } + public void sendToUser(Integer userId, String message) throws IOException { WebSocketSession session = websocketSessions.get(userId); if (session != null && session.isOpen()) { session.sendMessage(new TextMessage(message)); + }else { + redis.opsForList().leftPush(MESSAGE_WAITING_LIST + userId, message); } }