diff --git a/.github/workflows/docker-build-and-release-services-images.yml b/.github/workflows/docker-build-and-release-services-images.yml index 407589f1e..1d085e153 100644 --- a/.github/workflows/docker-build-and-release-services-images.yml +++ b/.github/workflows/docker-build-and-release-services-images.yml @@ -16,11 +16,17 @@ on: jobs: build-and-push: runs-on: ubuntu-latest + permissions: + contents: read + packages: write steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3.3.0 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3.8.0 @@ -44,48 +50,63 @@ jobs: username: ${{ secrets.ALIREGISTRY_USERNAME }} password: ${{ secrets.ALIREGISTRY_TOKEN }} - - name: Extract metadata for Docker (tags, labels) - id: meta - uses: docker/metadata-action@v5.6.0 - with: - tags: | - type=ref,event=tag - type=schedule - type=ref,event=branch - type=semver,pattern={{version}} - type=semver,pattern=v{{version}} - type=semver,pattern=release-{{raw}} - type=sha - type=raw,value=${{ github.event.inputs.tag }} + - name: Resolve Docker image tags + id: tags + env: + INPUT_TAG: ${{ github.event.inputs.tag }} + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: | + set -euo pipefail + + tags=() + declare -A seen=() + + add_tag() { + local tag="$1" + [[ -n "$tag" ]] || return 0 + + tag="${tag//\//-}" + if [[ -z "${seen[$tag]+x}" ]]; then + tags+=("$tag") + seen["$tag"]=1 + fi + } + + add_tag_with_semver_alias() { + local tag="$1" + add_tag "$tag" + if [[ "$tag" =~ ^v([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then + add_tag "${BASH_REMATCH[1]}" + add_tag "release-$tag" + fi + } + + add_tag_with_semver_alias "${INPUT_TAG:-}" + add_tag_with_semver_alias "${RELEASE_TAG:-}" + + if [[ "${GITHUB_REF_TYPE:-}" == "tag" ]]; then + add_tag_with_semver_alias "${GITHUB_REF_NAME}" + elif [[ "${GITHUB_REF_TYPE:-}" == "branch" ]]; then + add_tag "${GITHUB_REF_NAME}" + fi + + add_tag "sha-${GITHUB_SHA::7}" + + { + echo "tags<> "$GITHUB_OUTPUT" - name: Build and push Docker images + env: + RELEASE: "true" + PUSH: "true" + PLATFORMS: linux/amd64,linux/arm64 + IMAGE_TAGS: ${{ steps.tags.outputs.tags }} + IMAGE_REGISTRIES: | + ${{ secrets.DOCKER_USERNAME }} + ghcr.io/${{ github.repository_owner }} + registry.cn-hangzhou.aliyuncs.com/openimsdk run: | - IMG_DIR="build/images" - for dir in "$IMG_DIR"/*/; do - # Find Dockerfile or *.dockerfile in a case-insensitive manner - dockerfile=$(find "$dir" -maxdepth 1 -type f \( -iname 'dockerfile' -o -iname '*.dockerfile' \) | head -n 1) - - if [ -n "$dockerfile" ] && [ -f "$dockerfile" ]; then - IMAGE_NAME=$(basename "$dir") - echo "Building Docker image for $IMAGE_NAME with tags:" - - # Initialize tag arguments - tag_args=() - - # Read each tag and append --tag arguments - while IFS= read -r tag; do - tag_args+=(--tag "${{ secrets.DOCKER_USERNAME }}/$IMAGE_NAME:$tag") - tag_args+=(--tag "ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME:$tag") - tag_args+=(--tag "registry.cn-hangzhou.aliyuncs.com/openimsdk/$IMAGE_NAME:$tag") - done <<< "${{ steps.meta.outputs.tags }}" - - # Build and push the Docker image with all tags - docker buildx build --platform linux/amd64,linux/arm64 \ - --file "$dockerfile" \ - "${tag_args[@]}" \ - --push \ - "." - else - echo "No valid Dockerfile found in $dir" - fi - done + bash build/build.sh diff --git a/.github/workflows/go-build-test.yml b/.github/workflows/go-build-test.yml index 9e2aa3f1c..8425293e9 100644 --- a/.github/workflows/go-build-test.yml +++ b/.github/workflows/go-build-test.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - go_version: ["1.22.x"] + go_version: ["1.25.x"] steps: - name: Checkout Server repository @@ -188,7 +188,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - go_version: ["1.22.x"] + go_version: ["1.25.x"] steps: - name: Checkout Server repository @@ -237,7 +237,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_version: ["1.22"] + go_version: ["1.25.x"] steps: - name: Checkout Repository diff --git a/Dockerfile b/Dockerfile index 8a95b6851..30af8f7ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,49 +1,25 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder +FROM golang:1.25-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server +ARG RELEASE=false +ARG COMPRESS=false +WORKDIR /openim-server -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR +RUN apk add --no-cache upx -# Set the Go proxy to improve dependency resolution speed -# ENV GOPROXY=https://goproxy.io,direct +RUN go install github.com/magefile/mage@latest -# Copy all files from the current directory into the container COPY . . - RUN go mod download +RUN RELEASE=${RELEASE} COMPRESS=${COMPRESS} mage build +RUN mage -compile ./mage -ldflags "-s -w" -# Install Mage to use for building the application -RUN go install github.com/magefile/mage@v1.15.0 - -# Optionally build your application if needed -RUN mage build - -# Using Alpine Linux with Go environment for the final image -FROM golang:1.22-alpine - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - +FROM alpine:latest -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config -COPY --from=builder /go/bin/mage /usr/local/bin/mage -COPY --from=builder $SERVER_DIR/magefile_windows.go $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/magefile_unix.go $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/magefile.go $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/start-config.yml $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/go.mod $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/go.sum $SERVER_DIR/ +WORKDIR /openim-server -RUN go get github.com/openimsdk/gomake@v0.0.15-alpha.1 +COPY --from=builder /openim-server/_output ./_output +COPY --from=builder /openim-server/config ./config +COPY --from=builder /openim-server/start-config.yml ./start-config.yml +COPY --from=builder /openim-server/mage ./mage -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"] +ENTRYPOINT ["sh", "-c", "./mage start && sleep infinity"] \ No newline at end of file diff --git a/build/build.sh b/build/build.sh new file mode 100755 index 000000000..354cd3945 --- /dev/null +++ b/build/build.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash + +set -euo pipefail + +CYAN='\033[0;36m' +GREEN='\033[0;32m' +RED='\033[0;31m' +NO_COLOR='\033[0m' + +BASE_DIR="$(cd "$(dirname "$0")" && pwd)" +COMPOSE_FILE="$BASE_DIR/images/openim-server/docker-compose.build.yml" +RELEASE="${RELEASE:-false}" +PUSH="${PUSH:-false}" +DRY_RUN="${DRY_RUN:-false}" +PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" +IMAGE_TAGS="${IMAGE_TAGS:-}" +IMAGE_REGISTRIES="${IMAGE_REGISTRIES:-}" + +if [[ ! -f "$COMPOSE_FILE" ]]; then + echo -e "${RED}docker-compose.build.yml not found: $COMPOSE_FILE${NO_COLOR}" + exit 1 +fi + +cd "$BASE_DIR/.." || exit 1 + +split_values() { + printf '%s\n' "$1" | tr ', ' '\n\n' | while IFS= read -r value; do + [[ -n "$value" ]] && printf '%s\n' "$value" + done +} + +print_command() { + printf '%q ' "$@" + printf '\n' +} + +run_or_print() { + if [[ "$DRY_RUN" == "true" ]]; then + print_command "$@" + else + "$@" + fi +} + +build_local() { + echo -e "${CYAN}Building all services...${NO_COLOR}" + RELEASE="$RELEASE" docker compose -f "$COMPOSE_FILE" build + + echo -e "${CYAN}Tagging compatibility images for Kubernetes...${NO_COLOR}" + while IFS= read -r built_image; do + [[ -n "$built_image" ]] || continue + compatibility_tag="${built_image##*/}" + + if [[ "$built_image" != "$compatibility_tag" ]]; then + docker tag "$built_image" "$compatibility_tag" + fi + done < <(docker compose -f "$COMPOSE_FILE" config --images) + + echo -e "${GREEN}Successfully built all services${NO_COLOR}" +} + +build_push() { + if ! command -v jq >/dev/null 2>&1; then + echo -e "${RED}jq is required for PUSH=true${NO_COLOR}" + exit 1 + fi + + if [[ -z "$IMAGE_TAGS" || -z "$IMAGE_REGISTRIES" ]]; then + echo -e "${RED}IMAGE_TAGS and IMAGE_REGISTRIES are required for PUSH=true${NO_COLOR}" + exit 1 + fi + + image_tags=() + while IFS= read -r tag; do + image_tags+=("$tag") + done < <(split_values "$IMAGE_TAGS") + + image_registries=() + while IFS= read -r registry; do + image_registries+=("$registry") + done < <(split_values "$IMAGE_REGISTRIES") + + if [[ ${#image_tags[@]} -eq 0 || ${#image_registries[@]} -eq 0 ]]; then + echo -e "${RED}IMAGE_TAGS and IMAGE_REGISTRIES must contain at least one value${NO_COLOR}" + exit 1 + fi + + compose_config=$(docker compose -f "$COMPOSE_FILE" config --format json) + + echo -e "${CYAN}Building and pushing service images...${NO_COLOR}" + while IFS= read -r service; do + context=$(jq -r --arg service "$service" '.services[$service].build.context // empty' <<< "$compose_config") + dockerfile=$(jq -r --arg service "$service" '.services[$service].build.dockerfile // empty' <<< "$compose_config") + cmd_path=$(jq -r --arg service "$service" '.services[$service].build.args.CMD_PATH // empty' <<< "$compose_config") + binary_name=$(jq -r --arg service "$service" '.services[$service].build.args.BINARY_NAME // empty' <<< "$compose_config") + + if [[ -z "$context" || -z "$dockerfile" || -z "$cmd_path" || -z "$binary_name" ]]; then + echo -e "${RED}Invalid build config for $service${NO_COLOR}" + exit 1 + fi + + if [[ ! -d "$cmd_path" && ! -f "$cmd_path/main.go" ]]; then + echo -e "${CYAN}Skipping $service because $cmd_path does not exist${NO_COLOR}" + continue + fi + + tag_args=() + for registry in "${image_registries[@]}"; do + for tag in "${image_tags[@]}"; do + tag_args+=(--tag "$registry/$binary_name:$tag") + done + done + + echo -e "${CYAN}Building $binary_name for $PLATFORMS...${NO_COLOR}" + run_or_print docker buildx build \ + --platform "$PLATFORMS" \ + --file "$dockerfile" \ + --build-arg "CMD_PATH=$cmd_path" \ + --build-arg "BINARY_NAME=$binary_name" \ + --build-arg "RELEASE=$RELEASE" \ + "${tag_args[@]}" \ + --push \ + "$context" + done < <(jq -r '.services | keys[]' <<< "$compose_config" | sort) + + echo -e "${GREEN}Successfully pushed service images${NO_COLOR}" +} + +if [[ "$PUSH" == "true" ]]; then + build_push +else + build_local +fi diff --git a/build/images/Dockerfile b/build/images/Dockerfile deleted file mode 100644 index 020d50786..000000000 --- a/build/images/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -# # Copyright © 2023 OpenIM. All rights reserved. -# # -# # Licensed under the Apache License, Version 2.0 (the "License"); -# # you may not use this file except in compliance with the License. -# # You may obtain a copy of the License at -# # -# # http://www.apache.org/licenses/LICENSE-2.0 -# # -# # Unless required by applicable law or agreed to in writing, software -# # distributed under the License is distributed on an "AS IS" BASIS, -# # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# # See the License for the specific language governing permissions and -# # limitations under the License. - -# FROM BASE_IMAGE - -# WORKDIR ${SERVER_WORKDIR} - -# # Set HTTP proxy -# ARG BINARY_NAME - -# COPY BINARY_NAME ./bin/BINARY_NAME - -# ENTRYPOINT ["./bin/BINARY_NAME"] \ No newline at end of file diff --git a/build/images/openim-api/Dockerfile b/build/images/openim-api/Dockerfile deleted file mode 100644 index eb9971c9b..000000000 --- a/build/images/openim-api/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder - -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - -RUN go build -o _output/openim-api ./cmd/openim-api - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-api"] diff --git a/build/images/openim-crontask/Dockerfile b/build/images/openim-crontask/Dockerfile deleted file mode 100644 index 863ef4e65..000000000 --- a/build/images/openim-crontask/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-crontask ./cmd/openim-crontask - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-crontask"] diff --git a/build/images/openim-msggateway/Dockerfile b/build/images/openim-msggateway/Dockerfile deleted file mode 100644 index 981c8215b..000000000 --- a/build/images/openim-msggateway/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-msggateway ./cmd/openim-msggateway - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-msggateway"] diff --git a/build/images/openim-msgtransfer/Dockerfile b/build/images/openim-msgtransfer/Dockerfile deleted file mode 100644 index b765b01ed..000000000 --- a/build/images/openim-msgtransfer/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-msgtransfer ./cmd/openim-msgtransfer - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-msgtransfer"] diff --git a/build/images/openim-push/Dockerfile b/build/images/openim-push/Dockerfile deleted file mode 100644 index ee5ede79a..000000000 --- a/build/images/openim-push/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-push ./cmd/openim-push - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-push"] diff --git a/build/images/openim-rpc-auth/Dockerfile b/build/images/openim-rpc-auth/Dockerfile deleted file mode 100644 index b09258eee..000000000 --- a/build/images/openim-rpc-auth/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-rpc-auth ./cmd/openim-rpc/openim-rpc-auth - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-rpc-auth"] diff --git a/build/images/openim-rpc-conversation/Dockerfile b/build/images/openim-rpc-conversation/Dockerfile deleted file mode 100644 index ff6b315b2..000000000 --- a/build/images/openim-rpc-conversation/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-rpc-conversation ./cmd/openim-rpc/openim-rpc-conversation - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-rpc-conversation"] diff --git a/build/images/openim-rpc-friend/Dockerfile b/build/images/openim-rpc-friend/Dockerfile deleted file mode 100644 index 540678310..000000000 --- a/build/images/openim-rpc-friend/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-rpc-friend ./cmd/openim-rpc/openim-rpc-friend - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-rpc-friend"] diff --git a/build/images/openim-rpc-group/Dockerfile b/build/images/openim-rpc-group/Dockerfile deleted file mode 100644 index d1aab9ad9..000000000 --- a/build/images/openim-rpc-group/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-rpc-group ./cmd/openim-rpc/openim-rpc-group - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-rpc-group"] diff --git a/build/images/openim-rpc-msg/Dockerfile b/build/images/openim-rpc-msg/Dockerfile deleted file mode 100644 index da40bb293..000000000 --- a/build/images/openim-rpc-msg/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-rpc-msg ./cmd/openim-rpc/openim-rpc-msg - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-rpc-msg"] diff --git a/build/images/openim-rpc-third/Dockerfile b/build/images/openim-rpc-third/Dockerfile deleted file mode 100644 index 52cdb0de8..000000000 --- a/build/images/openim-rpc-third/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - - - -RUN go build -o _output/openim-rpc-third ./cmd/openim-rpc/openim-rpc-third - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-rpc-third"] diff --git a/build/images/openim-rpc-user/Dockerfile b/build/images/openim-rpc-user/Dockerfile deleted file mode 100644 index 1b3481c66..000000000 --- a/build/images/openim-rpc-user/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod tidy - -RUN go build -o _output/openim-rpc-user ./cmd/openim-rpc/openim-rpc-user - - -# Using Alpine Linux for the final image -FROM alpine:latest - -# Install necessary packages, such as bash -RUN apk add --no-cache bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -# COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "_output/openim-rpc-user"] diff --git a/build/images/openim-server/Dockerfile b/build/images/openim-server/Dockerfile new file mode 100644 index 000000000..e821260a6 --- /dev/null +++ b/build/images/openim-server/Dockerfile @@ -0,0 +1,30 @@ +FROM golang:1.25-alpine AS builder + +ARG CMD_PATH +ARG BINARY_NAME +ARG RELEASE=false + +ENV SERVER_DIR=/openim-server +WORKDIR $SERVER_DIR + +COPY . . +RUN go mod tidy + +RUN if [ "$RELEASE" = "true" ]; then \ + go build -trimpath -ldflags "-s -w" -o _output/${BINARY_NAME} ./${CMD_PATH}; \ + else \ + go build -o _output/${BINARY_NAME} ./${CMD_PATH}; \ + fi + +FROM alpine:latest + +RUN apk add --no-cache bash + +ARG BINARY_NAME +ENV BINARY_NAME=${BINARY_NAME} +ENV SERVER_DIR=/openim-server +WORKDIR $SERVER_DIR + +COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output + +ENTRYPOINT ["sh", "-c", "_output/${BINARY_NAME}"] \ No newline at end of file diff --git a/build/images/openim-server/docker-compose.build.override.yml b/build/images/openim-server/docker-compose.build.override.yml new file mode 100644 index 000000000..7ef19f988 --- /dev/null +++ b/build/images/openim-server/docker-compose.build.override.yml @@ -0,0 +1,72 @@ +services: + openim-api: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-crontask: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-msggateway: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-msgtransfer: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-push: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-rpc-auth: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-rpc-conversation: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-rpc-friend: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-rpc-group: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-rpc-msg: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-rpc-third: + build: + platforms: + - linux/amd64 + - linux/arm64 + + openim-rpc-user: + build: + platforms: + - linux/amd64 + - linux/arm64 diff --git a/build/images/openim-server/docker-compose.build.yml b/build/images/openim-server/docker-compose.build.yml new file mode 100644 index 000000000..1837fa836 --- /dev/null +++ b/build/images/openim-server/docker-compose.build.yml @@ -0,0 +1,120 @@ +services: + openim-api: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-api + BINARY_NAME: openim-api + RELEASE: ${RELEASE:-false} + image: openim-api:test + + openim-crontask: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-crontask + BINARY_NAME: openim-crontask + RELEASE: ${RELEASE:-false} + image: openim-crontask:test + + openim-msggateway: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-msggateway + BINARY_NAME: openim-msggateway + RELEASE: ${RELEASE:-false} + image: openim-msggateway:test + + openim-msgtransfer: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-msgtransfer + BINARY_NAME: openim-msgtransfer + RELEASE: ${RELEASE:-false} + image: openim-msgtransfer:test + + openim-push: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-push + BINARY_NAME: openim-push + RELEASE: ${RELEASE:-false} + image: openim-push:test + + openim-rpc-auth: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-rpc/openim-rpc-auth + BINARY_NAME: openim-rpc-auth + RELEASE: ${RELEASE:-false} + image: openim-rpc-auth:test + + openim-rpc-conversation: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-rpc/openim-rpc-conversation + BINARY_NAME: openim-rpc-conversation + RELEASE: ${RELEASE:-false} + image: openim-rpc-conversation:test + + openim-rpc-friend: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-rpc/openim-rpc-friend + BINARY_NAME: openim-rpc-friend + RELEASE: ${RELEASE:-false} + image: openim-rpc-friend:test + + openim-rpc-group: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-rpc/openim-rpc-group + BINARY_NAME: openim-rpc-group + RELEASE: ${RELEASE:-false} + image: openim-rpc-group:test + + openim-rpc-msg: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-rpc/openim-rpc-msg + BINARY_NAME: openim-rpc-msg + RELEASE: ${RELEASE:-false} + image: openim-rpc-msg:test + + openim-rpc-third: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-rpc/openim-rpc-third + BINARY_NAME: openim-rpc-third + RELEASE: ${RELEASE:-false} + image: openim-rpc-third:test + + openim-rpc-user: + build: + context: ../../.. + dockerfile: build/images/openim-server/Dockerfile + args: + CMD_PATH: cmd/openim-rpc/openim-rpc-user + BINARY_NAME: openim-rpc-user + RELEASE: ${RELEASE:-false} + image: openim-rpc-user:test diff --git a/build/images/openim-tools/component/Dockerfile b/build/images/openim-tools/component/Dockerfile deleted file mode 100644 index ae8de800f..000000000 --- a/build/images/openim-tools/component/Dockerfile +++ /dev/null @@ -1,108 +0,0 @@ -# # Copyright © 2023 OpenIM. All rights reserved. -# # -# # Licensed under the Apache License, Version 2.0 (the "License"); -# # you may not use this file except in compliance with the License. -# # You may obtain a copy of the License at -# # -# # http://www.apache.org/licenses/LICENSE-2.0 -# # -# # Unless required by applicable law or agreed to in writing, software -# # distributed under the License is distributed on an "AS IS" BASIS, -# # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# # See the License for the specific language governing permissions and -# # limitations under the License. - -# # OpenIM base image: https://github.com/openim-sigs/openim-base-image - -# # Set go mod installation source and proxy - -# FROM golang:1.20 AS builder - -# - -# WORKDIR /openim/openim-server - -# -# ENV GOPROXY=$GOPROXY - -# COPY go.mod go.sum ./ -# RUN go mod download - -# COPY . . - -# RUN make clean -# RUN make build BINS=component - -# # FROM ghcr.io/openim-sigs/openim-bash-image:latest -# FROM ghcr.io/openim-sigs/openim-bash-image:latest - -# WORKDIR /openim/openim-server - -# COPY --from=builder /openim/openim-server/_output/bin/tools /openim/openim-server/_output/bin/tools/ -# COPY --from=builder /openim/openim-server/config /openim/openim-server/config - -# ENV OPENIM_SERVER_CONFIG_NAME=/openim/openim-server/config - -# RUN mv ${OPENIM_SERVER_BINDIR}/platforms/$(get_os)/$(get_arch)/component /usr/bin/component - -# ENTRYPOINT ["bash", "-c", "component -c $OPENIM_SERVER_CONFIG_NAME"] - - -# Use Go 1.22 Alpine as the base image for building the application -FROM golang:1.22-alpine AS builder -# Define the base directory for the application as an environment variable -ENV SERVER_DIR=/openim-server - -# Set the working directory inside the container based on the environment variable -WORKDIR $SERVER_DIR - -# Set the Go proxy to improve dependency resolution speed - -#ENV GOPROXY=https://goproxy.io,direct - -# Copy all files from the current directory into the container -COPY . . - -RUN go mod download - -# Install Mage to use for building the application -RUN go install github.com/magefile/mage@v1.15.0 - -# ENV BINS=openim-rpc-user - -# Optionally build your application if needed -# RUN mage build ${BINS} check-free-memory seq || true -RUN mage build check-free-memory seq || true - -# Using Alpine Linux with Go environment for the final image -FROM golang:1.22-alpine - -# Install necessary packages, such as bash -RUN apk add bash - -# Set the environment and work directory -ENV SERVER_DIR=/openim-server -WORKDIR $SERVER_DIR - - -# Copy the compiled binaries and mage from the builder image to the final image -COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output -COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config -COPY --from=builder /go/bin/mage /usr/local/bin/mage -COPY --from=builder $SERVER_DIR/magefile_windows.go $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/magefile_unix.go $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/magefile.go $SERVER_DIR/ -# COPY --from=builder $SERVER_DIR/start-config.yml $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/go.mod $SERVER_DIR/ -COPY --from=builder $SERVER_DIR/go.sum $SERVER_DIR/ - - -RUN echo -e "serviceBinaries:\n \n" \ - > $SERVER_DIR/start-config.yml && \ - echo -e "toolBinaries:\n - check-free-memory\n - seq\n" >> $SERVER_DIR/start-config.yml && \ - echo "maxFileDescriptors: 10000" >> $SERVER_DIR/start-config.yml - -RUN go get github.com/openimsdk/gomake@v0.0.15-alpha.1 - -# Set the command to run when the container starts -ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"] diff --git a/go.mod b/go.mod index 45211ccec..f00a6ee40 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/openimsdk/open-im-server/v3 -go 1.22.7 +go 1.25.0 require ( firebase.google.com/go/v4 v4.14.1 @@ -8,19 +8,19 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/go-playground/validator/v10 v10.20.0 github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.1 + github.com/golang-jwt/jwt/v4 v4.5.2 github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/mitchellh/mapstructure v1.5.0 - github.com/openimsdk/protocol v0.0.73-alpha.18 - github.com/openimsdk/tools v0.0.50-alpha.106 + github.com/openimsdk/protocol v0.0.73-alpha.19 + github.com/openimsdk/tools v0.0.50-alpha.117 github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 go.mongodb.org/mongo-driver v1.14.0 google.golang.org/api v0.170.0 - google.golang.org/grpc v1.71.0 - google.golang.org/protobuf v1.36.4 + google.golang.org/grpc v1.79.3 + google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v3 v3.0.1 ) @@ -35,14 +35,14 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/kelindar/bitmap v1.5.2 github.com/likexian/gokit v0.25.13 - github.com/openimsdk/gomake v0.0.15-alpha.11 + github.com/openimsdk/gomake v0.0.17 github.com/redis/go-redis/v9 v9.4.0 github.com/robfig/cron/v3 v3.0.1 github.com/shirou/gopsutil v3.21.11+incompatible github.com/spf13/viper v1.18.2 go.etcd.io/etcd/client/v3 v3.5.13 go.uber.org/automaxprocs v1.5.3 - golang.org/x/sync v0.10.0 + golang.org/x/sync v0.20.0 k8s.io/api v0.31.2 k8s.io/apimachinery v0.31.2 k8s.io/client-go v0.31.2 @@ -50,7 +50,7 @@ require ( require ( cloud.google.com/go v0.112.1 // indirect - cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/firestore v1.15.0 // indirect cloud.google.com/go/iam v1.1.7 // indirect cloud.google.com/go/longrunning v0.5.5 // indirect @@ -76,6 +76,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect github.com/aws/smithy-go v1.22.1 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -90,15 +91,16 @@ require ( github.com/eapache/go-resiliency v1.6.0 // indirect github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect github.com/eapache/queue v1.1.0 // indirect + github.com/ebitengine/purego v0.10.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect @@ -108,7 +110,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.7 // indirect @@ -135,7 +137,7 @@ require ( github.com/leodido/go-urn v1.4.0 // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect github.com/lithammer/shortuuid v3.0.0+incompatible // indirect - github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect + github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88 // indirect github.com/magefile/mage v1.15.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -152,7 +154,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect @@ -163,6 +165,7 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sercand/kuberesolver/v6 v6.0.1 // indirect github.com/shirou/gopsutil/v3 v3.24.5 // indirect + github.com/shirou/gopsutil/v4 v4.26.2 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect @@ -171,8 +174,8 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tencentyun/cos-go-sdk-v5 v0.7.47 // indirect - github.com/tklauser/go-sysconf v0.3.13 // indirect - github.com/tklauser/numcpus v0.7.0 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect @@ -183,27 +186,27 @@ require ( go.etcd.io/etcd/api/v3 v3.5.13 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/otel v1.39.0 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect + go.opentelemetry.io/otel/trace v1.39.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.7.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/image v0.15.0 // indirect - golang.org/x/net v0.34.0 // indirect - golang.org/x/oauth2 v0.25.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/term v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/image v0.39.0 // indirect + golang.org/x/net v0.55.0 // indirect + golang.org/x/oauth2 v0.34.0 // indirect + golang.org/x/sys v0.45.0 // indirect + golang.org/x/term v0.43.0 // indirect + golang.org/x/text v0.37.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/appengine/v2 v2.0.2 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/gorm v1.25.8 // indirect @@ -222,6 +225,6 @@ require ( github.com/spf13/cobra v1.8.0 github.com/ugorji/go/codec v1.2.12 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.32.0 // indirect + golang.org/x/crypto v0.52.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/go.sum b/go.sum index a96abc9c3..0da371b9f 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8= cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= cloud.google.com/go/iam v1.1.7 h1:z4VHOhwKLF/+UYXAJDFwGtNF0b6gjsW1Pk9Ml0U/IoM= @@ -61,6 +61,8 @@ github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLj github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs= +github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -80,6 +82,8 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= @@ -103,12 +107,19 @@ github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4A github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0= github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= +github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= +github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -130,12 +141,13 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= @@ -171,8 +183,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= -github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -202,8 +214,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= @@ -303,8 +315,8 @@ github.com/likexian/gokit v0.25.13 h1:p2Uw3+6fGG53CwdU2Dz0T6bOycdb2+bAFAa3ymwWVk github.com/likexian/gokit v0.25.13/go.mod h1:qQhEWFBEfqLCO3/vOEo2EDKd+EycekVtUK4tex+l2H4= github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w= github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w= -github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE= -github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= +github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88 h1:PTw+yKnXcOFCR6+8hHTyWBeQ/P4Nb7dd4/0ohEcWQuM= +github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -347,12 +359,12 @@ github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/openimsdk/gomake v0.0.15-alpha.11 h1:PQudYDRESYeYlUYrrLLJhYIlUPO5x7FAx+o5El9U/Bw= -github.com/openimsdk/gomake v0.0.15-alpha.11/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= -github.com/openimsdk/protocol v0.0.73-alpha.18 h1:LXmDFx3KnMd2mN0/S3Q2U33Ft/DHvplSsINO0/bto/c= -github.com/openimsdk/protocol v0.0.73-alpha.18/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw= -github.com/openimsdk/tools v0.0.50-alpha.106 h1:gaqU08IbRxOdL16ZEQNyYLhCTf7K1HNkrik8KZLA+BM= -github.com/openimsdk/tools v0.0.50-alpha.106/go.mod h1:x9i/e+WJFW4tocy6RNJQ9NofQiP3KJ1Y576/06TqOG4= +github.com/openimsdk/gomake v0.0.17 h1:q8haP48VOH45WhJRiLj1YSBJyUFJqD8CTedH65i1YH8= +github.com/openimsdk/gomake v0.0.17/go.mod h1:nnjS8yCtrPJAt1knMbyPiUwCH2gpyBzj/EZAONfUOXg= +github.com/openimsdk/protocol v0.0.73-alpha.19 h1:CvXoDF2U73UcMhLnrtMFks2Aw+bXiDgH8AITEt783/s= +github.com/openimsdk/protocol v0.0.73-alpha.19/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw= +github.com/openimsdk/tools v0.0.50-alpha.117 h1:ACfijEVCeBcttT7OOkNGOOOvq14pJtb9szNIMHLm6Vc= +github.com/openimsdk/tools v0.0.50-alpha.117/go.mod h1:I0WESSa7ghPIo9BL+ETlH/qEIbO6+KZioM1jwNuDwz0= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= @@ -360,11 +372,13 @@ github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFu github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= @@ -388,8 +402,8 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -403,6 +417,8 @@ github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKl github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= +github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI= +github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -433,18 +449,18 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0= github.com/tencentyun/cos-go-sdk-v5 v0.7.47 h1:uoS4Sob16qEYoapkqJq1D1Vnsy9ira9BfNUMtoFYTI4= github.com/tencentyun/cos-go-sdk-v5 v0.7.47/go.mod h1:DH9US8nB+AJXqwu/AMOrCFN1COv3dpytXuJWHgdg7kE= -github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= -github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= -github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= -github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -474,22 +490,22 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= @@ -510,13 +526,13 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= +golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= -golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= +golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= +golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -539,19 +555,19 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -567,14 +583,14 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -583,8 +599,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -596,14 +612,16 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.170.0 h1:zMaruDePM88zxZBG+NG8+reALO2rfLhe/JShitLyT48= google.golang.org/api v0.170.0/go.mod h1:/xql9M2btF85xac/VAm4PsLMTLVGUOpq4BE9R8jyNy8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -615,17 +633,17 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24= -google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= +google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -635,8 +653,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/internal/msggateway/client_conn.go b/internal/msggateway/client_conn.go index 15a0d8c07..0fb1620a6 100644 --- a/internal/msggateway/client_conn.go +++ b/internal/msggateway/client_conn.go @@ -208,7 +208,11 @@ func (c *websocketClientConn) pingHandler(appData string) error { return nil } -func (c *websocketClientConn) pongHandler(string) error { +func (c *websocketClientConn) pongHandler(appData string) error { + log.ZDebug(context.Background(), "pong handler recv pong", "remoteAddr", c.conn.RemoteAddr(), "appData", appData) + if err := c.setReadDeadline(); err != nil { + return err + } return nil } diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index 359ecfa6f..cc51fdf18 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -23,9 +23,11 @@ import ( "strings" "time" + "github.com/openimsdk/tools/utils/stringutil" + "google.golang.org/grpc" + "github.com/openimsdk/open-im-server/v3/pkg/dbbuild" "github.com/openimsdk/open-im-server/v3/pkg/rpcli" - "google.golang.org/grpc" "github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" @@ -143,8 +145,8 @@ func (g *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgro return nil, err } } - for _, groupID := range groupIDs { - g.notification.GroupMemberInfoSetNotification(ctx, groupID, req.UserID) + if err = g.notification.GroupMemberInfoSetNotificationBulk(ctx, groupIDs, req.NewUserInfo); err != nil { + log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) } if err = g.db.DeleteGroupMemberHash(ctx, groupIDs); err != nil { return nil, err diff --git a/internal/rpc/group/notification.go b/internal/rpc/group/notification.go index 5a3cbbe26..8cf214459 100644 --- a/internal/rpc/group/notification.go +++ b/internal/rpc/group/notification.go @@ -802,6 +802,182 @@ func (g *NotificationSender) GroupCancelMutedNotification(ctx context.Context, g g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupCancelMutedNotification, tips) } +func (g *NotificationSender) getPublicUserInfos(ctx context.Context, userIDs []string) ([]*sdkws.PublicUserInfo, error) { + users, err := g.getUsersInfo(ctx, userIDs) + if err != nil { + return nil, err + } + userMap := make(map[string]common_user.CommonUser) + for _, user := range users { + userMap[user.GetUserID()] = user + } + for _, userID := range userIDs { + if _, ok := userMap[userID]; !ok { + return nil, servererrs.ErrUserIDNotFound.WrapMsg(fmt.Sprintf("user %s not found", userID)) + } + } + + return datautil.Slice(users, func(e common_user.CommonUser) *sdkws.PublicUserInfo { + return &sdkws.PublicUserInfo{ + UserID: e.GetUserID(), + Nickname: e.GetNickname(), + FaceURL: e.GetFaceURL(), + Ex: e.GetEx(), + } + }), nil +} + +func (g *NotificationSender) getGroupMembersForUser(ctx context.Context, groupIDs []string, userID string) ([]*sdkws.GroupMemberFullInfo, error) { + members, err := g.db.FindGroupMemberUser(ctx, groupIDs, userID) + if err != nil { + return nil, err + } + if err := g.PopulateGroupMember(ctx, members...); err != nil { + return nil, err + } + log.ZDebug(ctx, "getGroupMembers", "members", members) + return datautil.Slice(members, func(e *model.GroupMember) *sdkws.GroupMemberFullInfo { return g.groupMemberDB2PB(e, 0) }), nil +} + +func (g *NotificationSender) getGroupMemberMapForUser(ctx context.Context, groupIDs []string, userID string) (map[string]*sdkws.GroupMemberFullInfo, error) { + members, err := g.getGroupMembersForUser(ctx, groupIDs, userID) + if err != nil { + return nil, err + } + m := make(map[string]*sdkws.GroupMemberFullInfo) + for i, member := range members { + m[member.GroupID] = members[i] + } + return m, nil +} + +func (g *NotificationSender) migrateFallbackToGroupMemberFullInfo(groupMemberFullInfo *sdkws.GroupMemberFullInfo, publicUserInfo *sdkws.PublicUserInfo) *sdkws.GroupMemberFullInfo { + if groupMemberFullInfo == nil { + groupMemberFullInfo = &sdkws.GroupMemberFullInfo{} + } + if publicUserInfo == nil { + publicUserInfo = &sdkws.PublicUserInfo{} + } + + firstNotEmpty := func(s ...string) string { + for _, s := range s { + if s != "" { + return s + } + } + return "" + } + + return &sdkws.GroupMemberFullInfo{ + GroupID: groupMemberFullInfo.GroupID, + UserID: firstNotEmpty(groupMemberFullInfo.UserID, publicUserInfo.UserID), + RoleLevel: groupMemberFullInfo.RoleLevel, + JoinTime: groupMemberFullInfo.JoinTime, + Nickname: firstNotEmpty(groupMemberFullInfo.Nickname, publicUserInfo.Nickname), + FaceURL: firstNotEmpty(groupMemberFullInfo.FaceURL, publicUserInfo.FaceURL), + AppMangerLevel: groupMemberFullInfo.AppMangerLevel, + JoinSource: groupMemberFullInfo.JoinSource, + OperatorUserID: firstNotEmpty(groupMemberFullInfo.OperatorUserID, publicUserInfo.UserID), + InviterUserID: groupMemberFullInfo.InviterUserID, + Ex: groupMemberFullInfo.Ex, + MuteEndTime: groupMemberFullInfo.MuteEndTime, + } +} + +func (g *NotificationSender) getGroupInfos(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) { + var err error + defer func() { + if err != nil { + log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) + } + }() + + groups, err := g.db.FindGroup(ctx, groupIDs) + if err != nil { + return nil, err + } + numMap, err := g.db.FindGroupMemberNums(ctx, groupIDs) + if err != nil { + return nil, err + } + owners, err := g.db.FindGroupsOwner(ctx, groupIDs) + if err != nil { + return nil, err + } + ownerMap := make(map[string]string) + for _, owner := range owners { + ownerMap[owner.GroupID] = owner.UserID + } + + return datautil.Slice(groups, func(group *model.Group) *sdkws.GroupInfo { + return convert.Db2PbGroupInfo(group, ownerMap[group.GroupID], numMap[group.GroupID]) + }), nil +} + +func (g *NotificationSender) GroupMemberInfoSetNotificationBulk(ctx context.Context, groupIDs []string, changedUserInfo *sdkws.UserInfo) error { + opUserID := mcontext.GetOpUserID(ctx) + opIsAdmin := authverify.CheckUserIsAdmin(ctx, opUserID) + + groupInfos, err := g.getGroupInfos(ctx, groupIDs) + if err != nil { + return err + } + + groupMemberMap, err := g.getGroupMemberMapForUser(ctx, groupIDs, changedUserInfo.UserID) + if err != nil { + return err + } + + opMemberMap := groupMemberMap + if opUserID != changedUserInfo.UserID { + opMemberMap, err = g.getGroupMemberMapForUser(ctx, groupIDs, opUserID) + if err != nil { + return err + } + } + + opPublicUser := &sdkws.PublicUserInfo{ + UserID: changedUserInfo.GetUserID(), + Nickname: changedUserInfo.GetNickname(), + FaceURL: changedUserInfo.GetFaceURL(), + Ex: changedUserInfo.GetEx(), + } + if opUserID != changedUserInfo.UserID { + opPublicUser, err = g.getUser(ctx, opUserID) + if err != nil { + return err + } + } + + for _, groupInfo := range groupInfos { + if groupMemberMap[groupInfo.GroupID] == nil { + continue + } + + opUserGroupMemberFullInfo := datautil.If(opIsAdmin, &sdkws.GroupMemberFullInfo{ + GroupID: groupInfo.GroupID, + UserID: opUserID, + RoleLevel: constant.GroupAdmin, + AppMangerLevel: constant.AppAdmin, + }, opMemberMap[groupInfo.GroupID]) + if opUserGroupMemberFullInfo == nil { + opUserGroupMemberFullInfo = &sdkws.GroupMemberFullInfo{} + } + opUserGroupMemberFullInfo.GroupID = groupInfo.GroupID + + tips := &sdkws.GroupMemberInfoSetTips{ + Group: groupInfo, + OpUser: g.migrateFallbackToGroupMemberFullInfo(opUserGroupMemberFullInfo, opPublicUser), + ChangedUser: groupMemberMap[groupInfo.GroupID], + } + + g.setSortVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID, &tips.GroupSortVersion) + g.Notification(ctx, opUserID, groupInfo.GroupID, constant.GroupMemberInfoSetNotification, tips) + } + + return nil +} + func (g *NotificationSender) GroupMemberInfoSetNotification(ctx context.Context, groupID, groupMemberUserID string) { var err error defer func() { @@ -809,13 +985,11 @@ func (g *NotificationSender) GroupMemberInfoSetNotification(ctx context.Context, log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) } }() - var group *sdkws.GroupInfo - group, err = g.getGroupInfo(ctx, groupID) + group, err := g.getGroupInfo(ctx, groupID) if err != nil { return } - var user map[string]*sdkws.GroupMemberFullInfo - user, err = g.getGroupMemberMap(ctx, groupID, []string{groupMemberUserID}) + user, err := g.getGroupMemberMap(ctx, groupID, []string{groupMemberUserID}) if err != nil { return } @@ -834,8 +1008,7 @@ func (g *NotificationSender) GroupMemberSetToAdminNotification(ctx context.Conte log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) } }() - var group *sdkws.GroupInfo - group, err = g.getGroupInfo(ctx, groupID) + group, err := g.getGroupInfo(ctx, groupID) if err != nil { return } @@ -858,13 +1031,11 @@ func (g *NotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx contex log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) } }() - var group *sdkws.GroupInfo - group, err = g.getGroupInfo(ctx, groupID) + group, err := g.getGroupInfo(ctx, groupID) if err != nil { return } - var user map[string]*sdkws.GroupMemberFullInfo - user, err = g.getGroupMemberMap(ctx, groupID, []string{mcontext.GetOpUserID(ctx), groupMemberUserID}) + user, err := g.getGroupMemberMap(ctx, groupID, []string{mcontext.GetOpUserID(ctx), groupMemberUserID}) if err != nil { return } diff --git a/magefile.go b/magefile.go index b9861bd5e..9b34dfa60 100644 --- a/magefile.go +++ b/magefile.go @@ -5,9 +5,12 @@ package main import ( "flag" + "fmt" "os" "github.com/openimsdk/gomake/mageutil" + "github.com/openimsdk/open-im-server/v3/version" + "github.com/openimsdk/tools/utils/datautil" ) var Default = Build @@ -25,7 +28,6 @@ var ( customToolsDir = "tools" // tools source code directory, default is "tools" ) - // Build support specifical binary build. // // Example: `mage build openim-api openim-rpc-user seq` @@ -35,8 +37,7 @@ func Build() { if len(bin) != 0 { bin = bin[1:] } - - mageutil.Build(bin, nil) + mageutil.WithSpinner("Building binaries...", func() { mageutil.Build(bin, nil, nil) }) } func BuildWithCustomConfig() { @@ -53,7 +54,9 @@ func BuildWithCustomConfig() { ToolsDir: &customToolsDir, } - mageutil.Build(bin, config) + mageutil.WithSpinner("Building binaries with custom config...", func() { + mageutil.Build(bin, config, nil) + }) } func Start() { @@ -70,7 +73,9 @@ func Start() { bin = bin[1:] } - mageutil.StartToolsAndServices(bin, nil) + mageutil.WithSpinner("Starting...", func() { + mageutil.StartToolsAndServices(bin, nil) + }) } func StartWithCustomConfig() { @@ -93,13 +98,42 @@ func StartWithCustomConfig() { ConfigDir: &customConfigDir, } - mageutil.StartToolsAndServices(bin, config) + mageutil.WithSpinner("Starting with custom config...", func() { + mageutil.StartToolsAndServices(bin, config) + }) } func Stop() { - mageutil.StopAndCheckBinaries() + mageutil.WithSpinner("Stopping...", mageutil.StopAndCheckBinaries) } func Check() { - mageutil.CheckAndReportBinariesStatus() + mageutil.WithSpinner("Checking binaries...", mageutil.CheckAndReportBinariesStatus) +} + +func Export() { + mappingPaths, err := mageutil.GetDefaultExportMappingPaths([]string{ + "cmd", + "internal", + "pkg", + "test", + "tools", + "**/*.go", + "go.mod", + "go.work", + }) + if err != nil { + mageutil.PrintRed("GetDefaultExportMappingPaths failed " + err.Error()) + os.Exit(1) + } + + mageutil.WithSpinner("Exporting...", func() { + mageutil.ExportMageLauncherArchived(mappingPaths, &mageutil.ExportOptions{ + ProjectName: datautil.ToPtr(fmt.Sprintf("open-im-server_%s", version.Version)), + BuildOpt: &mageutil.BuildOptions{ + Release: datautil.ToPtr(true), + Compress: datautil.ToPtr(true), + }, + }) + }) } diff --git a/pkg/common/prommetrics/prommetrics.go b/pkg/common/prommetrics/prommetrics.go index 3f683a50e..68e37a013 100644 --- a/pkg/common/prommetrics/prommetrics.go +++ b/pkg/common/prommetrics/prommetrics.go @@ -100,11 +100,11 @@ type RespTarget struct { } func BuildDiscoveryKeyPrefix(name string) string { - return fmt.Sprintf("%s/%s/%s", "openim", "prometheus_discovery", name) + return fmt.Sprintf("%s/%s", "prometheus_discovery", name) } func BuildDiscoveryKey(name string, index int) string { - return fmt.Sprintf("%s/%s/%s/%d", "openim", "prometheus_discovery", name, index) + return fmt.Sprintf("%s/%s/%d", "prometheus_discovery", name, index) } func BuildDefaultTarget(host string, ip int) Target { diff --git a/pkg/common/storage/cache/group.go b/pkg/common/storage/cache/group.go index 05b75745a..4be494bf1 100644 --- a/pkg/common/storage/cache/group.go +++ b/pkg/common/storage/cache/group.go @@ -57,6 +57,7 @@ type GroupCache interface { GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*model.GroupMember, error) GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*model.GroupMember, error) GetGroupMemberNum(ctx context.Context, groupID string) (memberNum int64, err error) + GetGroupMemberNums(ctx context.Context, groupIDs []string) (memberNumMap map[string]int64, err error) DelGroupsMemberNum(groupID ...string) GroupCache //FindSortGroupMemberUserIDs(ctx context.Context, groupID string) ([]string, error) diff --git a/pkg/common/storage/cache/mcache/seq_conversation.go b/pkg/common/storage/cache/mcache/seq_conversation.go index 27f00de15..879b03535 100644 --- a/pkg/common/storage/cache/mcache/seq_conversation.go +++ b/pkg/common/storage/cache/mcache/seq_conversation.go @@ -32,7 +32,7 @@ func (x *seqConversationCache) GetMinSeq(ctx context.Context, conversationID str func (x *seqConversationCache) GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) { res := make(map[string]int64) for _, conversationID := range conversationIDs { - seq, err := x.GetMinSeq(ctx, conversationID) + seq, err := x.GetMaxSeq(ctx, conversationID) if err != nil { return nil, err } @@ -44,7 +44,7 @@ func (x *seqConversationCache) GetMaxSeqs(ctx context.Context, conversationIDs [ func (x *seqConversationCache) GetMaxSeqsWithTime(ctx context.Context, conversationIDs []string) (map[string]database.SeqTime, error) { res := make(map[string]database.SeqTime) for _, conversationID := range conversationIDs { - seq, err := x.GetMinSeq(ctx, conversationID) + seq, err := x.GetMaxSeq(ctx, conversationID) if err != nil { return nil, err } diff --git a/pkg/common/storage/cache/redis/group.go b/pkg/common/storage/cache/redis/group.go index d66716404..2c727666b 100644 --- a/pkg/common/storage/cache/redis/group.go +++ b/pkg/common/storage/cache/redis/group.go @@ -2,9 +2,13 @@ package redis import ( "context" + "encoding/json" "fmt" "time" + "github.com/openimsdk/tools/utils/datautil" + "github.com/redis/go-redis/v9" + "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey" @@ -14,7 +18,6 @@ import ( "github.com/openimsdk/protocol/constant" "github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/log" - "github.com/redis/go-redis/v9" ) const ( @@ -258,6 +261,57 @@ func (g *GroupCacheRedis) GetGroupMemberNum(ctx context.Context, groupID string) }) } +type groupMemberNumCache struct { + GroupID string `json:"group_id"` + MemberNum int64 `json:"member_num"` +} + +type groupMemberNumBatchCache struct { + GroupID string + MemberNum int64 +} + +func (r *groupMemberNumBatchCache) BatchCache(groupID string) { + r.GroupID = groupID +} +func (r *groupMemberNumBatchCache) UnmarshalJSON(bytes []byte) error { + return json.Unmarshal(bytes, &r.MemberNum) +} +func (r *groupMemberNumBatchCache) MarshalJSON() ([]byte, error) { + return json.Marshal(r.MemberNum) +} +func (g *GroupCacheRedis) GetGroupMemberNums(ctx context.Context, groupIDs []string) (map[string]int64, error) { + items, err := batchGetCache2( + ctx, + g.rcClient, + g.expireTime, + groupIDs, + func(groupID string) string { return g.getGroupMemberNumKey(groupID) }, + func(v *groupMemberNumBatchCache) string { return v.GroupID }, + func(ctx context.Context, ids []string) ([]*groupMemberNumBatchCache, error) { + res := make([]*groupMemberNumBatchCache, 0, len(ids)) + for _, groupID := range ids { + num, err := g.groupMemberDB.TakeGroupMemberNum(ctx, groupID) + if err != nil { + return nil, err + } + res = append(res, &groupMemberNumBatchCache{ + GroupID: groupID, + MemberNum: num, + }) + } + return res, nil + }, + ) + if err != nil { + return nil, err + } + + return datautil.SliceToMapAny(items, func(item *groupMemberNumBatchCache) (string, int64) { + return item.GroupID, item.MemberNum + }), nil +} + func (g *GroupCacheRedis) DelGroupsMemberNum(groupID ...string) cache.GroupCache { keys := make([]string, 0, len(groupID)) for _, groupID := range groupID { @@ -280,18 +334,111 @@ func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID string) (*m return members[0], nil } +type groupRoleLevelMemberIDsBatchCache struct { + GroupID string + UserIDs []string +} + +func (r *groupRoleLevelMemberIDsBatchCache) BatchCache(groupID string) { + r.GroupID = groupID +} +func (r *groupRoleLevelMemberIDsBatchCache) UnmarshalJSON(bytes []byte) (err error) { + return json.Unmarshal(bytes, &r.UserIDs) +} +func (r *groupRoleLevelMemberIDsBatchCache) MarshalJSON() ([]byte, error) { + return json.Marshal(r.UserIDs) +} + +func (g *GroupCacheRedis) batchGetGroupRoleLevelMemberIDs(ctx context.Context, groupIDs []string, roleLevel int32) (map[string][]string, error) { + items, err := batchGetCache2( + ctx, + g.rcClient, + g.expireTime, + groupIDs, + func(groupID string) string { + return g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel) + }, + func(v *groupRoleLevelMemberIDsBatchCache) string { + return v.GroupID + }, + func(ctx context.Context, ids []string) ([]*groupRoleLevelMemberIDsBatchCache, error) { + res := make([]*groupRoleLevelMemberIDsBatchCache, 0, len(ids)) + for _, groupID := range ids { + userIDs, err := g.groupMemberDB.FindRoleLevelUserIDs(ctx, groupID, roleLevel) + if err != nil { + return nil, err + } + res = append(res, &groupRoleLevelMemberIDsBatchCache{ + GroupID: groupID, + UserIDs: userIDs, + }) + } + return res, nil + }, + ) + if err != nil { + return nil, err + } + + return datautil.SliceToMapAny(items, func(item *groupRoleLevelMemberIDsBatchCache) (string, []string) { + return item.GroupID, item.UserIDs + }), nil +} + +type groupUserIDPair struct { + GroupID string + UserID string +} + +func (g *GroupCacheRedis) batchGetGroupMembersByPairs(ctx context.Context, ids []groupUserIDPair) ([]*model.GroupMember, error) { + return batchGetCache2(ctx, g.rcClient, g.expireTime, ids, func(id groupUserIDPair) string { + return g.getGroupMemberInfoKey(id.GroupID, id.UserID) + }, func(member *model.GroupMember) groupUserIDPair { + return groupUserIDPair{GroupID: member.GroupID, UserID: member.UserID} + }, func(ctx context.Context, ids []groupUserIDPair) ([]*model.GroupMember, error) { + groupIDsByUser := make(map[string][]string) + for _, id := range ids { + groupIDsByUser[id.UserID] = append(groupIDsByUser[id.UserID], id.GroupID) + } + members := make([]*model.GroupMember, 0, len(ids)) + for userID, groupIDs := range groupIDsByUser { + items, err := g.groupMemberDB.FindInGroup(ctx, userID, groupIDs) + if err != nil { + return nil, err + } + members = append(members, items...) + } + return members, nil + }) +} + func (g *GroupCacheRedis) GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*model.GroupMember, error) { - members := make([]*model.GroupMember, 0, len(groupIDs)) + ownerIDs, err := g.batchGetGroupRoleLevelMemberIDs(ctx, groupIDs, constant.GroupOwner) + if err != nil { + return nil, err + } + pairs := make([]groupUserIDPair, 0, len(groupIDs)) for _, groupID := range groupIDs { - items, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner) - if err != nil { - return nil, err + ids := ownerIDs[groupID] + if len(ids) == 0 { + continue } - if len(items) > 0 { - members = append(members, items[0]) + pairs = append(pairs, groupUserIDPair{GroupID: groupID, UserID: ids[0]}) + } + members, err := g.batchGetGroupMembersByPairs(ctx, pairs) + if err != nil { + return nil, err + } + memberMap := datautil.SliceToMapAny(members, func(member *model.GroupMember) (groupUserIDPair, *model.GroupMember) { + return groupUserIDPair{GroupID: member.GroupID, UserID: member.UserID}, member + }) + result := make([]*model.GroupMember, 0, len(pairs)) + for _, pair := range pairs { + if member, ok := memberMap[pair]; ok { + result = append(result, member) } } - return members, nil + return result, nil } func (g *GroupCacheRedis) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) { diff --git a/pkg/common/storage/controller/group.go b/pkg/common/storage/controller/group.go index 24209cd6c..17de62444 100644 --- a/pkg/common/storage/controller/group.go +++ b/pkg/common/storage/controller/group.go @@ -65,6 +65,8 @@ type GroupDatabase interface { FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) // FindGroupMemberNum retrieves the number of members in a group. FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) + // FindGroupMemberNums retrieves the number of members for multiple groups. + FindGroupMemberNums(ctx context.Context, groupIDs []string) (map[string]uint32, error) // FindUserManagedGroupID retrieves group IDs managed by a user. FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) // PageGroupRequest paginates through group requests for specified groups. @@ -232,6 +234,18 @@ func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string) return uint32(num), nil } +func (g *groupDatabase) FindGroupMemberNums(ctx context.Context, groupIDs []string) (map[string]uint32, error) { + nums, err := g.cache.GetGroupMemberNums(ctx, groupIDs) + if err != nil { + return nil, err + } + result := make(map[string]uint32, len(nums)) + for groupID, num := range nums { + result[groupID] = uint32(num) + } + return result, nil +} + func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (*model.Group, error) { return g.cache.GetGroupInfo(ctx, groupID) } diff --git a/pkg/common/storage/database/mgo/conversation.go b/pkg/common/storage/database/mgo/conversation.go index c1d00f0ed..30f08f5e5 100644 --- a/pkg/common/storage/database/mgo/conversation.go +++ b/pkg/common/storage/database/mgo/conversation.go @@ -51,7 +51,7 @@ func NewConversationMongo(db *mongo.Database) (*ConversationMgo, error) { Keys: bson.D{ {Key: "conversation_id", Value: 1}, }, - Options: options.Index().SetUnique(true), + Options: options.Index(), }, }) if err != nil {