mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-04-28 22:39:18 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 15762172fe |
@@ -1,26 +1,17 @@
|
||||
MONGO_IMAGE=mongo:7.0
|
||||
REDIS_IMAGE=redis:7.0.0
|
||||
KAFKA_IMAGE=bitnamilegacy/kafka:3.5.1
|
||||
KAFKA_IMAGE=bitnami/kafka:3.5.1
|
||||
MINIO_IMAGE=minio/minio:RELEASE.2024-01-11T07-46-16Z
|
||||
ETCD_IMAGE=quay.io/coreos/etcd:v3.5.13
|
||||
PROMETHEUS_IMAGE=prom/prometheus:v2.45.6
|
||||
ALERTMANAGER_IMAGE=prom/alertmanager:v0.27.0
|
||||
GRAFANA_IMAGE=grafana/grafana:11.0.1
|
||||
NODE_EXPORTER_IMAGE=prom/node-exporter:v1.7.0
|
||||
|
||||
OPENIM_WEB_FRONT_IMAGE=openim/openim-web-front:release-v3.8.3
|
||||
OPENIM_ADMIN_FRONT_IMAGE=openim/openim-admin-front:release-v1.8.4
|
||||
OPENIM_WEB_FRONT_IMAGE=openim/openim-web-front:release-v3.8.1
|
||||
OPENIM_ADMIN_FRONT_IMAGE=openim/openim-admin-front:release-v1.8.3
|
||||
|
||||
#FRONT_IMAGE: use aliyun images
|
||||
#OPENIM_WEB_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web-front:release-v3.8.3
|
||||
#OPENIM_ADMIN_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:release-v1.8.4
|
||||
#OPENIM_WEB_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web-front:release-v3.8.1
|
||||
#OPENIM_ADMIN_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:release-v1.8.3
|
||||
|
||||
DATA_DIR=./
|
||||
|
||||
MONGO_BACKUP_DIR=${DATA_DIR}components/backup/mongo/
|
||||
|
||||
PROMETHEUS_PORT=19091
|
||||
ALERTMANAGER_PORT=19093
|
||||
GRAFANA_PORT=13000
|
||||
|
||||
NODE_EXPORTER_PORT=19100
|
||||
@@ -1,91 +0,0 @@
|
||||
name: Build and release services Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release-*
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Tag version to be used for Docker image"
|
||||
required: true
|
||||
default: "v3.8.3"
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Log in to Aliyun Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALIREGISTRY_USERNAME }}
|
||||
password: ${{ secrets.ALIREGISTRY_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker (tags, labels)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern=v{{version}}
|
||||
# type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern=release-{{raw}}
|
||||
type=sha
|
||||
type=raw,value=${{ github.event.inputs.tag }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
run: |
|
||||
ROOT_DIR="build/images"
|
||||
for dir in "$ROOT_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 "$dir"
|
||||
else
|
||||
echo "No valid Dockerfile found in $dir"
|
||||
fi
|
||||
done
|
||||
@@ -92,13 +92,12 @@ jobs:
|
||||
contents: write
|
||||
env:
|
||||
SDK_DIR: openim-sdk-core
|
||||
NOTIFICATION_CONFIG_PATH: config/notification.yml
|
||||
SHARE_CONFIG_PATH: config/share.yml
|
||||
|
||||
CONFIG_PATH: config/notification.yml
|
||||
# pull-requests: write
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
go_version: ["1.22.x"]
|
||||
os: [ ubuntu-latest ]
|
||||
go_version: [ "1.22.x" ]
|
||||
|
||||
steps:
|
||||
- name: Checkout Server repository
|
||||
@@ -107,8 +106,7 @@ jobs:
|
||||
- name: Checkout SDK repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "openimsdk/openim-sdk-core"
|
||||
ref: "main"
|
||||
repository: 'openimsdk/openim-sdk-core'
|
||||
path: ${{ env.SDK_DIR }}
|
||||
|
||||
- name: Set up Go ${{ matrix.go_version }}
|
||||
@@ -121,11 +119,15 @@ jobs:
|
||||
go install github.com/magefile/mage@latest
|
||||
go mod download
|
||||
|
||||
- name: Install yq
|
||||
run: |
|
||||
sudo wget https://github.com/mikefarah/yq/releases/download/v4.34.1/yq_linux_amd64 -O /usr/bin/yq
|
||||
sudo chmod +x /usr/bin/yq
|
||||
|
||||
- name: Modify Server Configuration
|
||||
run: |
|
||||
yq e '.groupCreated.isSendMsg = true' -i ${{ env.NOTIFICATION_CONFIG_PATH }}
|
||||
yq e '.friendApplicationApproved.isSendMsg = true' -i ${{ env.NOTIFICATION_CONFIG_PATH }}
|
||||
yq e '.secret = 123456' -i ${{ env.SHARE_CONFIG_PATH }}
|
||||
yq e '.groupCreated.unreadCount = true' -i ${{ env.CONFIG_PATH }}
|
||||
yq e '.friendApplicationApproved.unreadCount = true' -i ${{ env.CONFIG_PATH }}
|
||||
|
||||
- name: Start Server Services
|
||||
run: |
|
||||
|
||||
@@ -4,80 +4,45 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- release-*
|
||||
# tags:
|
||||
# - 'v*'
|
||||
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Tag version to be used for Docker image"
|
||||
required: true
|
||||
default: "v3.8.3"
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.22"
|
||||
IMAGE_NAME: "openim-server"
|
||||
# IMAGE_NAME: ${{ github.event.repository.name }}
|
||||
DOCKER_BUILDKIT: 1
|
||||
default: "v3.8.0"
|
||||
|
||||
jobs:
|
||||
publish-docker-images:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.merged == false) }}
|
||||
steps:
|
||||
- name: Checkout main repository
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: main-repo
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3.3.0
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build Docker image
|
||||
id: build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
driver-opts: network=host
|
||||
context: ./main-repo
|
||||
load: true
|
||||
tags: "openim/openim-server:local"
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5.6.0
|
||||
with:
|
||||
images: |
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}
|
||||
ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
|
||||
registry.cn-hangzhou.aliyuncs.com/openimsdk/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern=v{{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
|
||||
- name: Install skopeo
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install -y skopeo
|
||||
|
||||
- name: Build multi-arch images as OCI
|
||||
run: |
|
||||
mkdir -p /tmp/oci-image /tmp/docker-cache
|
||||
|
||||
# Build multi-architecture image and save in OCI format
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--output type=oci,dest=/tmp/oci-image/multi-arch.tar \
|
||||
--cache-to type=local,dest=/tmp/docker-cache \
|
||||
--cache-from type=gha \
|
||||
./main-repo
|
||||
|
||||
# Use skopeo to convert the amd64 image from OCI format to Docker format and load it
|
||||
skopeo copy --override-arch amd64 oci-archive:/tmp/oci-image/multi-arch.tar docker-daemon:${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:local
|
||||
|
||||
# check image
|
||||
docker image ls | grep openim
|
||||
- name: Save Docker image to file
|
||||
run: docker save -o image.tar openim/openim-server:local
|
||||
|
||||
- name: Checkout compose repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -90,19 +55,18 @@ jobs:
|
||||
run: |
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
echo "The IP Address is: $IP"
|
||||
echo "ip=$IP" >> $GITHUB_OUTPUT
|
||||
echo "::set-output name=ip::$IP"
|
||||
|
||||
- name: Update .env to use the local image
|
||||
run: |
|
||||
sed -i 's|OPENIM_SERVER_IMAGE=.*|OPENIM_SERVER_IMAGE=${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:local|' ${{ github.workspace }}/compose-repo/.env
|
||||
sed -i 's|OPENIM_SERVER_IMAGE=.*|OPENIM_SERVER_IMAGE=openim/openim-server:local|' ${{ github.workspace }}/compose-repo/.env
|
||||
sed -i 's|MINIO_EXTERNAL_ADDRESS=.*|MINIO_EXTERNAL_ADDRESS=http://${{ steps.get-ip.outputs.ip }}:10005|' ${{ github.workspace }}/compose-repo/.env
|
||||
|
||||
- name: Start services using Docker Compose
|
||||
run: |
|
||||
cd ${{ github.workspace }}/compose-repo
|
||||
docker compose up -d
|
||||
|
||||
docker compose ps
|
||||
sleep 60
|
||||
|
||||
# - name: Check openim-server health
|
||||
# run: |
|
||||
@@ -133,62 +97,54 @@ jobs:
|
||||
# exit 0
|
||||
# fi
|
||||
|
||||
- name: Load Docker image from file
|
||||
run: docker load -i image.tar
|
||||
|
||||
- name: Extract metadata for Docker (tags, labels)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5.5.1
|
||||
with:
|
||||
images: |
|
||||
openim/openim-server
|
||||
ghcr.io/openimsdk/openim-server
|
||||
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern=v{{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=semver,pattern=release-{{raw}}
|
||||
type=sha
|
||||
type=raw,value=${{ github.event.inputs.tag }}
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3.3.0
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3.3.0
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Log in to Aliyun Container Registry
|
||||
uses: docker/login-action@v3.3.0
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALIREGISTRY_USERNAME }}
|
||||
password: ${{ secrets.ALIREGISTRY_TOKEN }}
|
||||
|
||||
- name: Push multi-architecture images
|
||||
if: success()
|
||||
run: |
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
$(echo "${{ steps.meta.outputs.tags }}" | sed 's/,/ --tag /g' | sed 's/^/--tag /') \
|
||||
--cache-from type=local,src=/tmp/docker-cache \
|
||||
--push \
|
||||
./main-repo
|
||||
|
||||
- name: Verify multi-platform support
|
||||
run: |
|
||||
images=(
|
||||
"${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}"
|
||||
"ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}"
|
||||
"registry.cn-hangzhou.aliyuncs.com/openimsdk/${{ env.IMAGE_NAME }}"
|
||||
)
|
||||
|
||||
for image in "${images[@]}"; do
|
||||
for tag in $(echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | cut -d':' -f2); do
|
||||
echo "Verifying multi-arch support for $image:$tag"
|
||||
manifest=$(docker manifest inspect "$image:$tag" || echo "error")
|
||||
if [[ "$manifest" == "error" ]]; then
|
||||
echo "Manifest not found for $image:$tag"
|
||||
exit 1
|
||||
fi
|
||||
amd64_found=$(echo "$manifest" | jq '.manifests[] | select(.platform.architecture == "amd64")')
|
||||
arm64_found=$(echo "$manifest" | jq '.manifests[] | select(.platform.architecture == "arm64")')
|
||||
if [[ -z "$amd64_found" ]]; then
|
||||
echo "Multi-platform support check failed for $image:$tag - missing amd64"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$arm64_found" ]]; then
|
||||
echo "Multi-platform support check failed for $image:$tag - missing arm64"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ $image:$tag supports both amd64 and arm64 architectures"
|
||||
done
|
||||
done
|
||||
- name: Push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./main-repo
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
@@ -8,40 +8,19 @@ jobs:
|
||||
update-version:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TAG_VERSION: ${{ github.event.release.tag_name }}
|
||||
TAG_VERSION: ${{ github.event.release.tag_name }}
|
||||
steps:
|
||||
# Step 1: Checkout the original repository's code
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
# submodules: "recursive"
|
||||
|
||||
- name: Safe submodule initialization
|
||||
run: |
|
||||
echo "Checking for submodules..."
|
||||
if [ -f .gitmodules ]; then
|
||||
if [ -s .gitmodules ]; then
|
||||
echo "Initializing submodules..."
|
||||
if git submodule sync --recursive 2>/dev/null; then
|
||||
git submodule update --init --force --recursive || {
|
||||
echo "Warning: Some submodules failed to initialize, continuing anyway..."
|
||||
}
|
||||
else
|
||||
echo "Warning: Submodule sync failed, continuing without submodules..."
|
||||
fi
|
||||
else
|
||||
echo ".gitmodules exists but is empty, skipping submodule initialization"
|
||||
fi
|
||||
else
|
||||
echo "No .gitmodules file found, no submodules to initialize"
|
||||
fi
|
||||
|
||||
# Step 2: Set up Git with official account
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Step 3: Check and delete existing tag
|
||||
- name: Check and delete existing tag
|
||||
@@ -54,8 +33,7 @@ jobs:
|
||||
# Step 4: Update version file
|
||||
- name: Update version file
|
||||
run: |
|
||||
mkdir -p version
|
||||
echo -n "${{ env.TAG_VERSION }}" > version/version
|
||||
echo "${{ env.TAG_VERSION }}" > version/version
|
||||
|
||||
# Step 5: Commit and push changes
|
||||
- name: Commit and push changes
|
||||
@@ -64,56 +42,43 @@ jobs:
|
||||
run: |
|
||||
git add version/version
|
||||
git commit -m "Update version to ${{ env.TAG_VERSION }}"
|
||||
git push origin HEAD:${{ github.ref }}
|
||||
|
||||
# Step 6: Update tag
|
||||
- name: Update tag
|
||||
# Step 6: Create and push tag
|
||||
- name: Create and push tag
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
git tag -fa ${{ env.TAG_VERSION }} -m "Update version to ${{ env.TAG_VERSION }}"
|
||||
git push origin ${{ env.TAG_VERSION }} --force
|
||||
git tag ${{ env.TAG_VERSION }}
|
||||
git push origin ${{ env.TAG_VERSION }}
|
||||
|
||||
# Step 7: Find and Publish Draft Release
|
||||
- name: Find and Publish Draft Release
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { owner, repo } = context.repo;
|
||||
const tagName = process.env.TAG_VERSION;
|
||||
// Get the list of releases
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
|
||||
try {
|
||||
let release;
|
||||
try {
|
||||
const response = await github.rest.repos.getReleaseByTag({
|
||||
owner,
|
||||
repo,
|
||||
tag: tagName
|
||||
});
|
||||
release = response.data;
|
||||
} catch (tagError) {
|
||||
core.info(`Release not found by tag, searching all releases...`);
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
owner,
|
||||
repo,
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
release = releases.data.find(r => r.draft && r.tag_name === tagName);
|
||||
if (!release) {
|
||||
throw new Error(`No release found with tag ${tagName}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the draft release where the title and tag_name are the same
|
||||
const draftRelease = releases.data.find(release =>
|
||||
release.draft && release.name === release.tag_name
|
||||
);
|
||||
|
||||
if (draftRelease) {
|
||||
// Publish the draft release using the release_id
|
||||
await github.rest.repos.updateRelease({
|
||||
owner,
|
||||
repo,
|
||||
release_id: release.id,
|
||||
draft: false,
|
||||
prerelease: release.prerelease
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: draftRelease.id, // Use release_id
|
||||
draft: false
|
||||
});
|
||||
|
||||
const status = release.draft ? "was draft" : "was already published";
|
||||
core.info(`Release ${tagName} ensured to be published (${status}).`);
|
||||
|
||||
} catch (error) {
|
||||
core.warning(`Could not find or update release for tag ${tagName}: ${error.message}`);
|
||||
}
|
||||
|
||||
core.info(`Draft Release ${draftRelease.tag_name} published successfully.`);
|
||||
} else {
|
||||
core.info("No matching draft release found.");
|
||||
}
|
||||
+1
-1
@@ -43,7 +43,7 @@ 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 go get github.com/openimsdk/gomake@v0.0.15-alpha.5
|
||||
RUN go get github.com/openimsdk/gomake@v0.0.14-alpha.5
|
||||
|
||||
# Set the command to run when the container starts
|
||||
ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"]
|
||||
|
||||
+13
-13
@@ -33,7 +33,7 @@ joinGroupApplication:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: true
|
||||
enable: false
|
||||
title: joinGroupApplication title
|
||||
desc: joinGroupApplication desc
|
||||
ext: joinGroupApplication ext
|
||||
@@ -53,7 +53,7 @@ groupApplicationAccepted:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: true
|
||||
enable: false
|
||||
title: groupApplicationAccepted title
|
||||
desc: groupApplicationAccepted desc
|
||||
ext: groupApplicationAccepted ext
|
||||
@@ -63,7 +63,7 @@ groupApplicationRejected:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: true
|
||||
enable: false
|
||||
title: groupApplicationRejected title
|
||||
desc: groupApplicationRejected desc
|
||||
ext: groupApplicationRejected ext
|
||||
@@ -200,7 +200,7 @@ friendApplicationAdded:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: true
|
||||
enable: false
|
||||
title: Somebody applies to add you as a friend
|
||||
desc: Somebody applies to add you as a friend
|
||||
ext: Somebody applies to add you as a friend
|
||||
@@ -230,7 +230,7 @@ friendAdded:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: We have become friends
|
||||
desc: We have become friends
|
||||
ext: We have become friends
|
||||
@@ -240,7 +240,7 @@ friendDeleted:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: deleted a friend
|
||||
desc: deleted a friend
|
||||
ext: deleted a friend
|
||||
@@ -250,7 +250,7 @@ friendRemarkSet:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: Your friend's profile has been changed
|
||||
desc: Your friend's profile has been changed
|
||||
ext: Your friend's profile has been changed
|
||||
@@ -260,7 +260,7 @@ blackAdded:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: blocked a user
|
||||
desc: blocked a user
|
||||
ext: blocked a user
|
||||
@@ -270,7 +270,7 @@ blackDeleted:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: Remove a blocked user
|
||||
desc: Remove a blocked user
|
||||
ext: Remove a blocked user
|
||||
@@ -280,7 +280,7 @@ friendInfoUpdated:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: friend info updated
|
||||
desc: friend info updated
|
||||
ext: friend info updated
|
||||
@@ -291,7 +291,7 @@ userInfoUpdated:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: userInfo updated
|
||||
desc: userInfo updated
|
||||
ext: userInfo updated
|
||||
@@ -312,7 +312,7 @@ conversationChanged:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: conversation changed
|
||||
desc: conversation changed
|
||||
ext: conversation changed
|
||||
@@ -322,7 +322,7 @@ conversationSetPrivate:
|
||||
reliabilityLevel: 1
|
||||
unreadCount: false
|
||||
offlinePush:
|
||||
enable: false
|
||||
enable: true
|
||||
title: burn after reading
|
||||
desc: burn after reading
|
||||
ext: burn after reading
|
||||
|
||||
@@ -10,10 +10,7 @@ api:
|
||||
prometheus:
|
||||
# Whether to enable prometheus
|
||||
enable: true
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# Prometheus listening ports, must match the number of api.ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12002 ]
|
||||
# This address can be accessed via a browser
|
||||
grafanaURL: http://127.0.0.1:13000/
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
rpc:
|
||||
# The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP
|
||||
registerIP:
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
registerIP:
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10140, 10141, 10142, 10143, 10144, 10145, 10146, 10147, 10148, 10149, 10150, 10151, 10152, 10153, 10154, 10155 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12140, 12141, 12142, 12143, 12144, 12145, 12146, 12147, 12148, 12149, 12150, 12151, 12152, 12153, 12154, 12155 ]
|
||||
|
||||
# IP address that the RPC/WebSocket service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that Prometheus listens on; each port corresponds to an instance of monitoring. Ensure these are managed accordingly
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
# Because four instances have been launched, four ports need to be specified
|
||||
ports: [ 12020, 12021, 12022, 12023, 12024, 12025, 12026, 12027, 12028, 12029, 12030, 12031, 12032, 12033, 12034, 12035 ]
|
||||
|
||||
@@ -3,17 +3,13 @@ rpc:
|
||||
registerIP:
|
||||
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10170, 10171, 10172, 10173, 10174, 10175, 10176, 10177, 10178, 10179, 10180, 10181, 10182, 10183, 10184, 10185 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12170, 12171, 12172, 12173, 12174, 12175, 12176, 12177, 12178, 12179, 12180, 12182, 12183, 12184, 12185, 12186 ]
|
||||
|
||||
maxConcurrentWorkers: 3
|
||||
|
||||
@@ -3,17 +3,13 @@ rpc:
|
||||
registerIP:
|
||||
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10200 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12200 ]
|
||||
|
||||
tokenPolicy:
|
||||
|
||||
@@ -3,15 +3,11 @@ rpc:
|
||||
registerIP:
|
||||
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10220 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12220 ]
|
||||
|
||||
@@ -3,15 +3,11 @@ rpc:
|
||||
registerIP:
|
||||
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10240 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12240 ]
|
||||
|
||||
@@ -3,17 +3,13 @@ rpc:
|
||||
registerIP:
|
||||
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10260 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12260 ]
|
||||
|
||||
|
||||
|
||||
@@ -3,17 +3,13 @@ rpc:
|
||||
registerIP:
|
||||
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10280 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12280 ]
|
||||
|
||||
|
||||
|
||||
@@ -3,17 +3,13 @@ rpc:
|
||||
registerIP:
|
||||
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 10300 ]
|
||||
|
||||
prometheus:
|
||||
# Enable or disable Prometheus monitoring
|
||||
enable: true
|
||||
# List of ports that Prometheus listens on; these must match the number of rpc.ports to ensure correct monitoring setup
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12300 ]
|
||||
|
||||
|
||||
@@ -42,10 +38,3 @@ object:
|
||||
accessKeySecret:
|
||||
sessionToken:
|
||||
publicRead: false
|
||||
aws:
|
||||
region: ap-southeast-2
|
||||
bucket: testdemo832234
|
||||
accessKeyID:
|
||||
secretAccessKey:
|
||||
sessionToken:
|
||||
publicRead: false
|
||||
|
||||
@@ -3,15 +3,11 @@ rpc:
|
||||
registerIP:
|
||||
# Listening IP; 0.0.0.0 means both internal and external IPs are listened to, if blank, the internal network IP is automatically obtained by default
|
||||
listenIP: 0.0.0.0
|
||||
# autoSetPorts indicates whether to automatically set the ports
|
||||
autoSetPorts: true
|
||||
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances. These must match the number of configured prometheus ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
# Listening ports; if multiple are configured, multiple instances will be launched, and must be consistent with the number of prometheus.ports
|
||||
ports: [ 10320 ]
|
||||
|
||||
prometheus:
|
||||
# Whether to enable prometheus
|
||||
enable: true
|
||||
# Prometheus listening ports, must be consistent with the number of rpc.ports
|
||||
# It will only take effect when autoSetPorts is set to false.
|
||||
ports: [ 12320 ]
|
||||
|
||||
+49
-82
@@ -8,7 +8,7 @@ global:
|
||||
alerting:
|
||||
alertmanagers:
|
||||
- static_configs:
|
||||
- targets: [127.0.0.1:19093]
|
||||
- targets: [internal_ip:19093]
|
||||
|
||||
# Load rules once and periodically evaluate them according to the global evaluation_interval.
|
||||
rule_files:
|
||||
@@ -25,95 +25,62 @@ scrape_configs:
|
||||
# prometheus fetches application services
|
||||
- job_name: node_exporter
|
||||
static_configs:
|
||||
- targets: [ 127.0.0.1:19100 ]
|
||||
|
||||
- targets: [ internal_ip:20500 ]
|
||||
- job_name: openimserver-openim-api
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/api"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12002 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12002 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-msggateway
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/msg_gateway"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12140 ]
|
||||
# # - targets: [ 127.0.0.1:12140, 127.0.0.1:12141, 127.0.0.1:12142, 127.0.0.1:12143, 127.0.0.1:12144, 127.0.0.1:12145, 127.0.0.1:12146, 127.0.0.1:12147, 127.0.0.1:12148, 127.0.0.1:12149, 127.0.0.1:12150, 127.0.0.1:12151, 127.0.0.1:12152, 127.0.0.1:12153, 127.0.0.1:12154, 127.0.0.1:12155 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12140 ]
|
||||
# - targets: [ internal_ip:12140, internal_ip:12141, internal_ip:12142, internal_ip:12143, internal_ip:12144, internal_ip:12145, internal_ip:12146, internal_ip:12147, internal_ip:12148, internal_ip:12149, internal_ip:12150, internal_ip:12151, internal_ip:12152, internal_ip:12153, internal_ip:12154, internal_ip:12155 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-msgtransfer
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/msg_transfer"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12020, 127.0.0.1:12021, 127.0.0.1:12022, 127.0.0.1:12023, 127.0.0.1:12024, 127.0.0.1:12025, 127.0.0.1:12026, 127.0.0.1:12027 ]
|
||||
# # - targets: [ 127.0.0.1:12020, 127.0.0.1:12021, 127.0.0.1:12022, 127.0.0.1:12023, 127.0.0.1:12024, 127.0.0.1:12025, 127.0.0.1:12026, 127.0.0.1:12027, 127.0.0.1:12028, 127.0.0.1:12029, 127.0.0.1:12030, 127.0.0.1:12031, 127.0.0.1:12032, 127.0.0.1:12033, 127.0.0.1:12034, 127.0.0.1:12035 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12020, internal_ip:12021, internal_ip:12022, internal_ip:12023, internal_ip:12024, internal_ip:12025, internal_ip:12026, internal_ip:12027 ]
|
||||
# - targets: [ internal_ip:12020, internal_ip:12021, internal_ip:12022, internal_ip:12023, internal_ip:12024, internal_ip:12025, internal_ip:12026, internal_ip:12027, internal_ip:12028, internal_ip:12029, internal_ip:12030, internal_ip:12031, internal_ip:12032, internal_ip:12033, internal_ip:12034, internal_ip:12035 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-push
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/push"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12170, 127.0.0.1:12171, 127.0.0.1:12172, 127.0.0.1:12173, 127.0.0.1:12174, 127.0.0.1:12175, 127.0.0.1:12176, 127.0.0.1:12177 ]
|
||||
## - targets: [ 127.0.0.1:12170, 127.0.0.1:12171, 127.0.0.1:12172, 127.0.0.1:12173, 127.0.0.1:12174, 127.0.0.1:12175, 127.0.0.1:12176, 127.0.0.1:12177, 127.0.0.1:12178, 127.0.0.1:12179, 127.0.0.1:12180, 127.0.0.1:12182, 127.0.0.1:12183, 127.0.0.1:12184, 127.0.0.1:12185, 127.0.0.1:12186 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12170, internal_ip:12171, internal_ip:12172, internal_ip:12173, internal_ip:12174, internal_ip:12175, internal_ip:12176, internal_ip:12177 ]
|
||||
# - targets: [ internal_ip:12170, internal_ip:12171, internal_ip:12172, internal_ip:12173, internal_ip:12174, internal_ip:12175, internal_ip:12176, internal_ip:12177, internal_ip:12178, internal_ip:12179, internal_ip:12180, internal_ip:12182, internal_ip:12183, internal_ip:12184, internal_ip:12185, internal_ip:12186 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-rpc-auth
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/auth"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12200 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12200 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-rpc-conversation
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/conversation"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12220 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12220 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-rpc-friend
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/friend"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12240 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12240 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-rpc-group
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/group"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12260 ]
|
||||
# labels:
|
||||
# namespace: default.
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12260 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-rpc-msg
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/msg"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12280 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12280 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-rpc-third
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/third"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12300 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12300 ]
|
||||
labels:
|
||||
namespace: default
|
||||
- job_name: openimserver-openim-rpc-user
|
||||
http_sd_configs:
|
||||
- url: "http://127.0.0.1:10002/prometheus_discovery/user"
|
||||
# static_configs:
|
||||
# - targets: [ 127.0.0.1:12320 ]
|
||||
# labels:
|
||||
# namespace: default
|
||||
static_configs:
|
||||
- targets: [ internal_ip:12320 ]
|
||||
labels:
|
||||
namespace: default
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
address: [ localhost:16379 ]
|
||||
username:
|
||||
password: openIM123
|
||||
# redisMode can be "cluster", "sentinel", or "standalone"
|
||||
redisMode: "standalone"
|
||||
clusterMode: false
|
||||
db: 0
|
||||
maxRetry: 10
|
||||
poolSize: 100
|
||||
|
||||
+1
-5
@@ -15,8 +15,4 @@ imAdminUserID: [ imAdmin ]
|
||||
# 1: For Android, iOS, Windows, Mac, and web platforms, only one instance can be online at a time
|
||||
multiLogin:
|
||||
policy: 1
|
||||
maxNumOneEnd: 30
|
||||
|
||||
rpcMaxBodySize:
|
||||
requestMaxBodySize: 8388608
|
||||
responseMaxBodySize: 8388608
|
||||
maxNumOneEnd: 30
|
||||
+138
-151
@@ -1,188 +1,175 @@
|
||||
# Kubernetes Deployment
|
||||
# OpenIM Application Containerization Deployment Guide
|
||||
|
||||
## Resource Requests
|
||||
OpenIM supports a variety of cluster deployment methods, including but not limited to `helm`, `sealos`, `kustomize`
|
||||
|
||||
- CPU: 2 cores
|
||||
- Memory: 4 GiB
|
||||
- Disk usage: 20 GiB (on Node)
|
||||
Various contributors, as well as previous official releases, have provided some referenceable solutions:
|
||||
|
||||
## Preconditions
|
||||
+ [k8s-jenkins Repository](https://github.com/OpenIMSDK/k8s-jenkins)
|
||||
+ [open-im-server-k8s-deploy Repository](https://github.com/openimsdk/open-im-server-k8s-deploy)
|
||||
+ [openim-charts Repository](https://github.com/OpenIMSDK/openim-charts)
|
||||
+ [deploy-openim Repository](https://github.com/showurl/deploy-openim)
|
||||
|
||||
ensure that you have already deployed the following components:
|
||||
### Dependency Check
|
||||
|
||||
- Redis
|
||||
- MongoDB
|
||||
- Kafka
|
||||
- MinIO
|
||||
```bash
|
||||
Kubernetes: >= 1.16.0-0
|
||||
Helm: >= 3.0
|
||||
```
|
||||
|
||||
## Origin Deploy
|
||||
### Minimum Configuration
|
||||
|
||||
### Enter the target dir
|
||||
|
||||
`cd ./deployments/deploy/`
|
||||
|
||||
### Deploy configs and dependencies
|
||||
|
||||
Upate your configMap `openim-config.yml`. **You can check the official docs for more details.**
|
||||
|
||||
In `openim-config.yml`, you need modify the following configurations:
|
||||
|
||||
**discovery.yml**
|
||||
|
||||
- `kubernetes.namespace`: default is `default`, you can change it to your namespace.
|
||||
|
||||
**mongodb.yml**
|
||||
|
||||
- `address`: set to your already mongodb address or mongo Service name and port in your deployed.
|
||||
- `database`: set to your mongodb database name.(Need have a created database.)
|
||||
- `authSource`: set to your mongodb authSource. (authSource is specify the database name associated with the user's credentials, user need create in this database.)
|
||||
|
||||
**kafka.yml**
|
||||
|
||||
- `address`: set to your already kafka address or kafka Service name and port in your deployed.
|
||||
|
||||
**redis.yml**
|
||||
|
||||
- `address`: set to your already redis address or redis Service name and port in your deployed.
|
||||
|
||||
**minio.yml**
|
||||
|
||||
- `internalAddress`: set to your minio Service name and port in your deployed.
|
||||
- `externalAddress`: set to your already expose minio external address.
|
||||
|
||||
### Set the secret
|
||||
|
||||
A Secret is an object that contains a small amount of sensitive data. Such as password and secret. Secret is similar to ConfigMaps.
|
||||
|
||||
#### Redis:
|
||||
|
||||
Update the `redis-password` value in `redis-secret.yml` to your Redis password encoded in base64.
|
||||
The recommended minimum configuration for a production environment is as follows:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-redis-secret
|
||||
type: Opaque
|
||||
data:
|
||||
redis-password: b3BlbklNMTIz # update to your redis password encoded in base64, if need empty, you can set to ""
|
||||
CPU: 4
|
||||
Memory: 8G
|
||||
Disk: 100G
|
||||
```
|
||||
|
||||
#### Mongo:
|
||||
## Configuration File Generation
|
||||
|
||||
Update the `mongo_openim_username`, `mongo_openim_password` value in `mongo-secret.yml` to your Mongo username and password encoded in base64.
|
||||
We have automated all the files, making the generation of configuration files optional for OpenIM. However, if you desire custom configurations, you can follow the steps below:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-mongo-secret
|
||||
type: Opaque
|
||||
data:
|
||||
mongo_openim_username: b3BlbklN # update to your mongo username encoded in base64, if need empty, you can set to "" (this user credentials need in authSource database).
|
||||
mongo_openim_password: b3BlbklNMTIz # update to your mongo password encoded in base64, if need empty, you can set to ""
|
||||
```bash
|
||||
$ make init
|
||||
# Alternatively, use script:
|
||||
# ./scripts/init-config.sh
|
||||
```
|
||||
|
||||
#### Minio:
|
||||
At this point, configuration files will be generated under `deployments/openim/config`, which you can modify as per your requirements.
|
||||
|
||||
Update the `minio-root-user` and `minio-root-password` value in `minio-secret.yml` to your MinIO accessKeyID and secretAccessKey encoded in base64.
|
||||
## Cluster Setup
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-minio-secret
|
||||
type: Opaque
|
||||
data:
|
||||
minio-root-user: cm9vdA== # update to your minio accessKeyID encoded in base64, if need empty, you can set to ""
|
||||
minio-root-password: b3BlbklNMTIz # update to your minio secretAccessKey encoded in base64, if need empty, you can set to ""
|
||||
If you already have a `kubernetes` cluster, or if you wish to build a `kubernetes` cluster from scratch, you can skip this step.
|
||||
|
||||
For a quick start, I used [sealos](https://github.com/labring/sealos) to rapidly set up the cluster, with sealos also being a wrapper for kubeadm at its core:
|
||||
|
||||
```bash
|
||||
$ SEALOS_VERSION=`curl -s https://api.github.com/repos/labring/sealos/releases/latest | grep -oE '"tag_name": "[^"]+"' | head -n1 | cut -d'"' -f4` && \
|
||||
curl -sfL https://raw.githubusercontent.com/labring/sealos/${SEALOS_VERSION}/scripts/install.sh |
|
||||
sh -s ${SEALOS_VERSION} labring/sealos
|
||||
```
|
||||
|
||||
#### Kafka:
|
||||
**Supported Versions:**
|
||||
|
||||
Update the `kafka-password` value in `kafka-secret.yml` to your Kafka password encoded in base64.
|
||||
+ docker: `labring/kubernetes-docker`:(v1.24.0~v1.27.0)
|
||||
+ containerd: `labring/kubernetes`:(v1.24.0~v1.27.0)
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-kafka-secret
|
||||
type: Opaque
|
||||
data:
|
||||
kafka-password: b3BlbklNMTIz # update to your kafka password encoded in base64, if need empty, you can set to ""
|
||||
#### Cluster Installation:
|
||||
|
||||
Cluster details are as follows:
|
||||
|
||||
| Hostname | IP Address | System Info |
|
||||
| -------- | ---------- | ------------------------------------------------------------ |
|
||||
| master01 | 10.0.0.9 | `Linux VM-0-9-ubuntu 5.15.0-76-generic #83-Ubuntu SMP Thu Jun 15 19:16:32 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux` |
|
||||
| node01 | 10.0.0.4 | Similar to master01 |
|
||||
| node02 | 10.0.0.10 | Similar to master01 |
|
||||
|
||||
```bash
|
||||
$ export CLUSTER_USERNAME=ubuntu
|
||||
$ export CLUSTER_PASSWORD=123456
|
||||
$ sudo sealos run labring/kubernetes:v1.25.0 labring/helm:v3.8.2 labring/calico:v3.24.1 \
|
||||
--masters 10.0.0.9 \
|
||||
--nodes 10.0.0.4,10.0.0.10 \
|
||||
-u "$CLUSTER_USERNAME" \
|
||||
-p "$CLUSTER_PASSWORD"
|
||||
```
|
||||
|
||||
### Apply the secret.
|
||||
|
||||
```shell
|
||||
kubectl apply -f redis-secret.yml -f minio-secret.yml -f mongo-secret.yml -f kafka-secret.yml
|
||||
```
|
||||
|
||||
### Apply all config
|
||||
|
||||
`kubectl apply -f ./openim-config.yml`
|
||||
|
||||
> Attation: If you use `default` namespace, you can excute `clusterRile.yml` to create a cluster role binding for default service account.
|
||||
> **Node** Uninstallation method: using `kubeadm` for uninstallation does not remove `etcd` and `cni` related configurations. Manual clearance or using `sealos` for uninstallation is needed.
|
||||
>
|
||||
> Namespace is modify to `discovery.yml` in `openim-config.yml`, you can change `kubernetes.namespace` to your namespace.
|
||||
> ```bash
|
||||
> $ sealos reset
|
||||
> ```
|
||||
|
||||
**Excute `clusterRole.yml`**
|
||||
|
||||
`kubectl apply -f ./clusterRole.yml`
|
||||
|
||||
### run all deployments and services
|
||||
|
||||
> Note: Ensure that infrastructure services like MinIO, Redis, and Kafka are running before deploying the main applications.
|
||||
If you are local, you can also use Kind and Minikube to test, for example, using Kind:
|
||||
|
||||
```bash
|
||||
kubectl apply \
|
||||
-f openim-api-deployment.yml \
|
||||
-f openim-api-service.yml \
|
||||
-f openim-crontask-deployment.yml \
|
||||
-f openim-rpc-user-deployment.yml \
|
||||
-f openim-rpc-user-service.yml \
|
||||
-f openim-msggateway-deployment.yml \
|
||||
-f openim-msggateway-service.yml \
|
||||
-f openim-push-deployment.yml \
|
||||
-f openim-push-service.yml \
|
||||
-f openim-msgtransfer-service.yml \
|
||||
-f openim-msgtransfer-deployment.yml \
|
||||
-f openim-rpc-conversation-deployment.yml \
|
||||
-f openim-rpc-conversation-service.yml \
|
||||
-f openim-rpc-auth-deployment.yml \
|
||||
-f openim-rpc-auth-service.yml \
|
||||
-f openim-rpc-group-deployment.yml \
|
||||
-f openim-rpc-group-service.yml \
|
||||
-f openim-rpc-friend-deployment.yml \
|
||||
-f openim-rpc-friend-service.yml \
|
||||
-f openim-rpc-msg-deployment.yml \
|
||||
-f openim-rpc-msg-service.yml \
|
||||
-f openim-rpc-third-deployment.yml \
|
||||
-f openim-rpc-third-service.yml
|
||||
$ GO111MODULE="on" go get sigs.k8s.io/kind@v0.11.1
|
||||
$ kind create cluster
|
||||
```
|
||||
|
||||
### Verification
|
||||
### Installing helm
|
||||
|
||||
After deploying the services, verify that everything is running smoothly:
|
||||
Helm simplifies the deployment and management of Kubernetes applications to a large extent by offering version control and release management through packaging.
|
||||
|
||||
**Using Script:**
|
||||
|
||||
```bash
|
||||
# Check the status of all pods
|
||||
kubectl get pods
|
||||
|
||||
# Check the status of services
|
||||
kubectl get svc
|
||||
|
||||
# Check the status of deployments
|
||||
kubectl get deployments
|
||||
|
||||
# View all resources
|
||||
kubectl get all
|
||||
$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||
```
|
||||
|
||||
### clean all
|
||||
**Adding Repository:**
|
||||
|
||||
`kubectl delete -f ./`
|
||||
```bash
|
||||
$ helm repo add brigade https://openimsdk.github.io/openim-charts
|
||||
```
|
||||
|
||||
### Notes:
|
||||
### OpenIM Image Strategy
|
||||
|
||||
- If you use a specific namespace for your deployment, be sure to append the -n <namespace> flag to your kubectl commands.
|
||||
Automated offerings include aliyun, ghcr, docker hub: [Image Documentation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md)
|
||||
|
||||
**Local Test Build Method:**
|
||||
|
||||
```bash
|
||||
$ make image
|
||||
```
|
||||
|
||||
> This command assists in quickly building the required images locally. For a detailed build strategy, refer to the [Build Documentation](https://github.com/openimsdk/open-im-server/blob/main/build/README.md).
|
||||
|
||||
## Installation
|
||||
|
||||
Explore our Helm-Charts repository and read through: [Helm-Charts Repository](https://github.com/openimsdk/helm-charts)
|
||||
|
||||
|
||||
Using the helm charts repository, you can ignore the following configuration, but if you want to just use the server and scale on top of it, you can go ahead:
|
||||
|
||||
**Use the Helm template to generate the deployment yaml file: `openim-charts.yaml`**
|
||||
|
||||
**Gen Image:**
|
||||
|
||||
```bash
|
||||
../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/helm-image.yaml > ./charts/generated-configs/helm-image.yaml
|
||||
```
|
||||
|
||||
**Gen Charts:**
|
||||
|
||||
```bash
|
||||
for chart in ./charts/*/; do
|
||||
if [[ "$chart" == *"generated-configs"* || "$chart" == *"helmfile.yaml"* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -f "${chart}values.yaml" ]; then
|
||||
helm template "$chart" -f "./charts/generated-configs/helm-image.yaml" -f "./charts/generated-configs/config.yaml" -f "./charts/generated-configs/notification.yaml" >> openim-charts.yaml
|
||||
else
|
||||
helm template "$chart" >> openim-charts.yaml
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
**Use Helmfile:**
|
||||
|
||||
```bash
|
||||
GO111MODULE=on go get github.com/roboll/helmfile@latest
|
||||
```
|
||||
|
||||
```bash
|
||||
export MONGO_ADDRESS=im-mongo
|
||||
export MONGO_PORT=27017
|
||||
export REDIS_ADDRESS=im-redis-master
|
||||
export REDIS_PORT=6379
|
||||
export KAFKA_ADDRESS=im-kafka
|
||||
export KAFKA_PORT=9092
|
||||
export OBJECT_APIURL="https://openim.server.com/api"
|
||||
export MINIO_ENDPOINT="http://im-minio:9000"
|
||||
export MINIO_SIGN_ENDPOINT="https://openim.server.com/im-minio-api"
|
||||
|
||||
mkdir ./charts/generated-configs
|
||||
../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/config.yaml > ./charts/generated-configs/config.yaml
|
||||
cp ../config/notification.yaml ./charts/generated-configs/notification.yaml
|
||||
../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/helm-image.yaml > ./charts/generated-configs/helm-image.yaml
|
||||
```
|
||||
|
||||
```bash
|
||||
helmfile apply
|
||||
```
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-kafka-secret
|
||||
type: Opaque
|
||||
data:
|
||||
kafka-password: ""
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-minio-secret
|
||||
type: Opaque
|
||||
data:
|
||||
minio-root-user: cm9vdA== # Base64 encoded "root"
|
||||
minio-root-password: b3BlbklNMTIz # Base64 encoded "openIM123"
|
||||
@@ -1,79 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: minio
|
||||
labels:
|
||||
app: minio
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: minio
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: minio
|
||||
spec:
|
||||
containers:
|
||||
- name: minio
|
||||
image: minio/minio:RELEASE.2024-01-11T07-46-16Z
|
||||
ports:
|
||||
- containerPort: 9000 # MinIO service port
|
||||
- containerPort: 9090 # MinIO console port
|
||||
volumeMounts:
|
||||
- name: minio-data
|
||||
mountPath: /data
|
||||
- name: minio-config
|
||||
mountPath: /root/.minio
|
||||
env:
|
||||
- name: TZ
|
||||
value: "Asia/Shanghai"
|
||||
- name: MINIO_ROOT_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-user
|
||||
- name: MINIO_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-password
|
||||
command:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- |
|
||||
mkdir -p /data && \
|
||||
minio server /data --console-address ":9090"
|
||||
volumes:
|
||||
- name: minio-data
|
||||
persistentVolumeClaim:
|
||||
claimName: minio-pvc
|
||||
- name: minio-config
|
||||
persistentVolumeClaim:
|
||||
claimName: minio-config-pvc
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: minio-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: minio-config-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-mongo-secret
|
||||
type: Opaque
|
||||
data:
|
||||
mongo_openim_username: b3BlbklN # base64 for "openIM", this user credentials need in authSource database.
|
||||
mongo_openim_password: b3BlbklNMTIz # base64 for "openIM123"
|
||||
@@ -1,108 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: mongo-statefulset
|
||||
spec:
|
||||
serviceName: "mongo"
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mongo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mongo
|
||||
spec:
|
||||
containers:
|
||||
- name: mongo
|
||||
image: mongo:7.0
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- >
|
||||
docker-entrypoint.sh mongod --wiredTigerCacheSizeGB ${wiredTigerCacheSizeGB} --auth &
|
||||
until mongosh -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --authenticationDatabase admin --eval "db.runCommand({ ping: 1 })" &>/dev/null; do
|
||||
echo "Waiting for MongoDB to start...";
|
||||
sleep 1;
|
||||
done &&
|
||||
mongosh -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --authenticationDatabase admin --eval "
|
||||
db = db.getSiblingDB(\"${MONGO_INITDB_DATABASE}\");
|
||||
if (!db.getUser(\"${MONGO_OPENIM_USERNAME}\")) {
|
||||
db.createUser({
|
||||
user: \"${MONGO_OPENIM_USERNAME}\",
|
||||
pwd: \"${MONGO_OPENIM_PASSWORD}\",
|
||||
roles: [{role: \"readWrite\", db: \"${MONGO_INITDB_DATABASE}\"}]
|
||||
});
|
||||
print(\"User created successfully: \");
|
||||
print(\"Username: ${MONGO_OPENIM_USERNAME}\");
|
||||
print(\"Password: ${MONGO_OPENIM_PASSWORD}\");
|
||||
print(\"Database: ${MONGO_INITDB_DATABASE}\");
|
||||
} else {
|
||||
print(\"User already exists in database: ${MONGO_INITDB_DATABASE}, Username: ${MONGO_OPENIM_USERNAME}\");
|
||||
}
|
||||
" &&
|
||||
tail -f /dev/null
|
||||
ports:
|
||||
- containerPort: 27017
|
||||
env:
|
||||
- name: MONGO_INITDB_ROOT_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_initdb_root_username
|
||||
- name: MONGO_INITDB_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_initdb_root_password
|
||||
- name: MONGO_INITDB_DATABASE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_initdb_database
|
||||
- name: MONGO_OPENIM_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_openim_username
|
||||
- name: MONGO_OPENIM_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_openim_password
|
||||
- name: TZ
|
||||
value: "Asia/Shanghai"
|
||||
- name: wiredTigerCacheSizeGB
|
||||
value: "1"
|
||||
volumeMounts:
|
||||
- name: mongo-storage
|
||||
mountPath: /data/db
|
||||
|
||||
volumes:
|
||||
- name: mongo-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: mongo-pvc
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: mongo-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-mongo-init-secret
|
||||
type: Opaque
|
||||
data:
|
||||
mongo_initdb_root_username: cm9vdA== # base64 for "root"
|
||||
mongo_initdb_root_password: b3BlbklNMTIz # base64 for "openIM123"
|
||||
mongo_initdb_database: b3BlbmltX3Yz # base64 for "openim_v3"
|
||||
mongo_openim_username: b3BlbklN # base64 for "openIM"
|
||||
mongo_openim_password: b3BlbklNMTIz # base64 for "openIM123"
|
||||
@@ -1,47 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: openim-api
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: openim-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: openim-api
|
||||
spec:
|
||||
containers:
|
||||
- name: openim-api-container
|
||||
image: openim/openim-api:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10002
|
||||
- containerPort: 12002
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messagegateway-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messagegateway-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messagegateway-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: openim-msggateway-container
|
||||
image: openim/openim-msggateway:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10140
|
||||
- containerPort: 12001
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,50 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: openim-msgtransfer-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: openim-msgtransfer-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: openim-msgtransfer-server
|
||||
spec:
|
||||
containers:
|
||||
- name: openim-msgtransfer-container
|
||||
image: openim/openim-msgtransfer:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 12020
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,41 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: push-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: push-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: push-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: push-rpc-server-container
|
||||
image: openim/openim-push:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10170
|
||||
- containerPort: 12170
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,37 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: auth-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: auth-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: auth-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: auth-rpc-server-container
|
||||
image: openim/openim-rpc-auth:v3.8.3
|
||||
imagePullPolicy: Never
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10200
|
||||
- containerPort: 12200
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,46 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: conversation-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: conversation-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: conversation-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: conversation-rpc-server-container
|
||||
image: openim/openim-rpc-conversation:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10220
|
||||
- containerPort: 12220
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,46 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: friend-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: friend-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: friend-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: friend-rpc-server-container
|
||||
image: openim/openim-rpc-friend:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10240
|
||||
- containerPort: 12240
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,46 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: group-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: group-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: group-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: group-rpc-server-container
|
||||
image: openim/openim-rpc-group:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10260
|
||||
- containerPort: 12260
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,51 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: msg-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: msg-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: msg-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: msg-rpc-server-container
|
||||
image: openim/openim-rpc-msg:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10280
|
||||
- containerPort: 12280
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,56 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: third-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: third-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: third-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: third-rpc-server-container
|
||||
image: openim/openim-rpc-third:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_MINIO_ACCESSKEYID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-user
|
||||
- name: IMENV_MINIO_SECRETACCESSKEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-password
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10300
|
||||
- containerPort: 12300
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,51 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: user-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: user-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: user-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: user-rpc-server-container
|
||||
image: openim/openim-rpc-user:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10320
|
||||
- containerPort: 12320
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-redis-secret
|
||||
type: Opaque
|
||||
data:
|
||||
redis-password: b3BlbklNMTIz # "openIM123" in base64
|
||||
@@ -1,55 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: redis-statefulset
|
||||
spec:
|
||||
serviceName: "redis"
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7.0.0
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
env:
|
||||
- name: TZ
|
||||
value: "Asia/Shanghai"
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: redis-secret
|
||||
key: redis-password
|
||||
volumeMounts:
|
||||
- name: redis-data
|
||||
mountPath: /data
|
||||
command:
|
||||
[
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
'redis-server --requirepass "$REDIS_PASSWORD" --appendonly yes',
|
||||
]
|
||||
volumes:
|
||||
- name: redis-config-volume
|
||||
configMap:
|
||||
name: openim-config
|
||||
- name: redis-data
|
||||
persistentVolumeClaim:
|
||||
claimName: redis-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: redis-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
+50
-122
@@ -37,7 +37,6 @@ services:
|
||||
- "${DATA_DIR}/components/mongodb/data/db:/data/db"
|
||||
- "${DATA_DIR}/components/mongodb/data/logs:/data/logs"
|
||||
- "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo"
|
||||
- "${MONGO_BACKUP_DIR}:/data/backup"
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
- wiredTigerCacheSizeGB=1
|
||||
@@ -63,12 +62,7 @@ services:
|
||||
restart: always
|
||||
sysctls:
|
||||
net.core.somaxconn: 1024
|
||||
command: >
|
||||
redis-server
|
||||
--requirepass openIM123
|
||||
--appendonly yes
|
||||
--aof-use-rdb-preamble yes
|
||||
--save ""
|
||||
command: redis-server /usr/local/redis/config/redis.conf --requirepass openIM123 --appendonly yes
|
||||
networks:
|
||||
- openim
|
||||
|
||||
@@ -104,62 +98,15 @@ services:
|
||||
environment:
|
||||
#KAFKA_HEAP_OPTS: "-Xms128m -Xmx256m"
|
||||
TZ: Asia/Shanghai
|
||||
# Unique identifier for the Kafka node (required in controller mode)
|
||||
KAFKA_CFG_NODE_ID: 0
|
||||
# Defines the roles this Kafka node plays: broker, controller, or both
|
||||
KAFKA_CFG_PROCESS_ROLES: controller,broker
|
||||
# Specifies which nodes are controller nodes for quorum voting.
|
||||
# The syntax follows the KRaft mode (no ZooKeeper): node.id@host:port
|
||||
# The controller listener endpoint here is kafka:9093
|
||||
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093
|
||||
# Specifies which listener is used for controller-to-controller communication
|
||||
KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
|
||||
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,EXTERNAL://localhost:19094
|
||||
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
|
||||
KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
|
||||
# Default number of partitions for new topics
|
||||
KAFKA_NUM_PARTITIONS: 8
|
||||
# Whether to enable automatic topic creation
|
||||
KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "true"
|
||||
# Kafka internal listeners; Kafka supports multiple ports with different protocols
|
||||
# Each port is used for a specific purpose: INTERNAL for internal broker communication,
|
||||
# CONTROLLER for controller communication, EXTERNAL for external client connections.
|
||||
# These logical listener names are mapped to actual protocols via KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP
|
||||
# In short, Kafka is listening on three logical ports: 9092 for internal communication,
|
||||
# 9093 for controller traffic, and 9094 for external access.
|
||||
KAFKA_CFG_LISTENERS: "INTERNAL://:9092,CONTROLLER://:9093,EXTERNAL://:9094"
|
||||
# Addresses advertised to clients. INTERNAL://kafka:9092 uses the internal Docker service name 'kafka',
|
||||
# so other containers can access Kafka via kafka:9092.
|
||||
# EXTERNAL://localhost:19094 is the address external clients (e.g., in the LAN) should use to connect.
|
||||
# If Kafka is deployed on a different machine than IM, 'localhost' should be replaced with the LAN IP.
|
||||
KAFKA_CFG_ADVERTISED_LISTENERS: "INTERNAL://kafka:9092,EXTERNAL://localhost:19094"
|
||||
# Maps logical listener names to actual protocols.
|
||||
# Supported protocols include: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL
|
||||
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,INTERNAL:PLAINTEXT"
|
||||
# Defines which listener is used for inter-broker communication within the Kafka cluster
|
||||
KAFKA_CFG_INTER_BROKER_LISTENER_NAME: "INTERNAL"
|
||||
|
||||
|
||||
# Authentication configuration variables - comment out to disable auth
|
||||
# KAFKA_USERNAME: "openIM"
|
||||
# KAFKA_PASSWORD: "openIM123"
|
||||
command: >
|
||||
/bin/sh -c '
|
||||
if [ -n "$${KAFKA_USERNAME}" ] && [ -n "$${KAFKA_PASSWORD}" ]; then
|
||||
echo "=== Kafka SASL Authentication ENABLED ==="
|
||||
echo "Username: $${KAFKA_USERNAME}"
|
||||
|
||||
# Set environment variables for SASL authentication
|
||||
export KAFKA_CFG_LISTENERS="SASL_PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094"
|
||||
export KAFKA_CFG_ADVERTISED_LISTENERS="SASL_PLAINTEXT://kafka:9092,EXTERNAL://localhost:19094"
|
||||
export KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP="CONTROLLER:PLAINTEXT,EXTERNAL:SASL_PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT"
|
||||
export KAFKA_CFG_SASL_ENABLED_MECHANISMS="PLAIN"
|
||||
export KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL="PLAIN"
|
||||
export KAFKA_CFG_INTER_BROKER_LISTENER_NAME="SASL_PLAINTEXT"
|
||||
export KAFKA_CLIENT_USERS="$${KAFKA_USERNAME}"
|
||||
export KAFKA_CLIENT_PASSWORDS="$${KAFKA_PASSWORD}"
|
||||
fi
|
||||
|
||||
# Start Kafka with the configured environment
|
||||
exec /opt/bitnami/scripts/kafka/entrypoint.sh /opt/bitnami/scripts/kafka/run.sh
|
||||
'
|
||||
networks:
|
||||
- openim
|
||||
|
||||
@@ -199,68 +146,49 @@ services:
|
||||
networks:
|
||||
- openim
|
||||
|
||||
prometheus:
|
||||
image: ${PROMETHEUS_IMAGE}
|
||||
container_name: prometheus
|
||||
restart: always
|
||||
user: root
|
||||
profiles:
|
||||
- m
|
||||
volumes:
|
||||
- ./config/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
|
||||
- ${DATA_DIR}/components/prometheus/data:/prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--storage.tsdb.path=/prometheus'
|
||||
- '--web.listen-address=:${PROMETHEUS_PORT}'
|
||||
network_mode: host
|
||||
|
||||
alertmanager:
|
||||
image: ${ALERTMANAGER_IMAGE}
|
||||
container_name: alertmanager
|
||||
restart: always
|
||||
profiles:
|
||||
- m
|
||||
volumes:
|
||||
- ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
|
||||
- ./config/email.tmpl:/etc/alertmanager/email.tmpl
|
||||
command:
|
||||
- '--config.file=/etc/alertmanager/alertmanager.yml'
|
||||
- '--web.listen-address=:${ALERTMANAGER_PORT}'
|
||||
network_mode: host
|
||||
|
||||
grafana:
|
||||
image: ${GRAFANA_IMAGE}
|
||||
container_name: grafana
|
||||
user: root
|
||||
restart: always
|
||||
profiles:
|
||||
- m
|
||||
environment:
|
||||
- GF_SECURITY_ALLOW_EMBEDDING=true
|
||||
- GF_SESSION_COOKIE_SAMESITE=none
|
||||
- GF_SESSION_COOKIE_SECURE=true
|
||||
- GF_AUTH_ANONYMOUS_ENABLED=true
|
||||
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||
- GF_SERVER_HTTP_PORT=${GRAFANA_PORT}
|
||||
volumes:
|
||||
- ${DATA_DIR:-./}/components/grafana:/var/lib/grafana
|
||||
network_mode: host
|
||||
|
||||
node-exporter:
|
||||
image: ${NODE_EXPORTER_IMAGE}
|
||||
container_name: node-exporter
|
||||
restart: always
|
||||
profiles:
|
||||
- m
|
||||
volumes:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/rootfs:ro
|
||||
command:
|
||||
- '--path.procfs=/host/proc'
|
||||
- '--path.sysfs=/host/sys'
|
||||
- '--path.rootfs=/rootfs'
|
||||
- '--web.listen-address=:${NODE_EXPORTER_PORT}'
|
||||
network_mode: host
|
||||
# prometheus:
|
||||
# image: ${PROMETHEUS_IMAGE}
|
||||
# container_name: prometheus
|
||||
# restart: always
|
||||
# user: root
|
||||
# volumes:
|
||||
# - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
# - ./config/instance-down-rules.yml:/etc/prometheus/instance-down-rules.yml
|
||||
# - ${DATA_DIR}/components/prometheus/data:/prometheus
|
||||
# command:
|
||||
# - '--config.file=/etc/prometheus/prometheus.yml'
|
||||
# - '--storage.tsdb.path=/prometheus'
|
||||
# ports:
|
||||
# - "19091:9090"
|
||||
# networks:
|
||||
# - openim
|
||||
#
|
||||
# alertmanager:
|
||||
# image: ${ALERTMANAGER_IMAGE}
|
||||
# container_name: alertmanager
|
||||
# restart: always
|
||||
# volumes:
|
||||
# - ./config/alertmanager.yml:/etc/alertmanager/alertmanager.yml
|
||||
# - ./config/email.tmpl:/etc/alertmanager/email.tmpl
|
||||
# ports:
|
||||
# - "19093:9093"
|
||||
# networks:
|
||||
# - openim
|
||||
#
|
||||
# grafana:
|
||||
# image: ${GRAFANA_IMAGE}
|
||||
# container_name: grafana
|
||||
# user: root
|
||||
# restart: always
|
||||
# environment:
|
||||
# - GF_SECURITY_ALLOW_EMBEDDING=true
|
||||
# - GF_SESSION_COOKIE_SAMESITE=none
|
||||
# - GF_SESSION_COOKIE_SECURE=true
|
||||
# - GF_AUTH_ANONYMOUS_ENABLED=true
|
||||
# - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||
# ports:
|
||||
# - "13000:3000"
|
||||
# volumes:
|
||||
# - ${DATA_DIR:-./}/components/grafana:/var/lib/grafana
|
||||
# networks:
|
||||
# - openim
|
||||
|
||||
@@ -2,6 +2,8 @@ module github.com/openimsdk/open-im-server/v3
|
||||
|
||||
go 1.22.7
|
||||
|
||||
toolchain go1.23.2
|
||||
|
||||
require (
|
||||
firebase.google.com/go/v4 v4.14.1
|
||||
github.com/dtm-labs/rockscache v0.1.1
|
||||
@@ -12,15 +14,15 @@ require (
|
||||
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.12
|
||||
github.com/openimsdk/tools v0.0.50-alpha.106
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.63
|
||||
github.com/openimsdk/tools v0.0.50-alpha.50
|
||||
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.9.0
|
||||
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.68.0
|
||||
google.golang.org/protobuf v1.35.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
@@ -35,18 +37,20 @@ 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.5
|
||||
github.com/openimsdk/gomake v0.0.14-alpha.5
|
||||
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
|
||||
github.com/stathat/consistent v1.0.0
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
golang.org/x/sync v0.10.0
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||
golang.org/x/sync v0.8.0
|
||||
)
|
||||
|
||||
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.5.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
|
||||
@@ -86,27 +90,19 @@ 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/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/fsnotify/fsnotify v1.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/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // 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
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-zookeeper/zk v1.0.3 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
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-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
|
||||
@@ -123,7 +119,6 @@ require (
|
||||
github.com/jinzhu/copier v0.4.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kelindar/simd v1.1.2 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
@@ -133,7 +128,6 @@ require (
|
||||
github.com/lithammer/shortuuid v3.0.0+incompatible // 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
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
@@ -143,7 +137,6 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/mozillazg/go-httpheader v0.4.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
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
|
||||
@@ -155,7 +148,6 @@ require (
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sercand/kuberesolver/v6 v6.0.1 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
@@ -166,7 +158,6 @@ require (
|
||||
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||
github.com/tklauser/numcpus v0.7.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
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
@@ -176,39 +167,26 @@ require (
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.13 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // 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.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.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/net v0.29.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.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
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
gorm.io/gorm v1.25.8 // indirect
|
||||
k8s.io/api v0.31.2 // indirect
|
||||
k8s.io/apimachinery v0.31.2 // indirect
|
||||
k8s.io/client-go v0.31.2 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
stathat.com/c/consistent v1.0.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -218,6 +196,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.27.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
)
|
||||
|
||||
@@ -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.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||
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=
|
||||
@@ -103,8 +103,6 @@ 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/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=
|
||||
@@ -117,10 +115,8 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE=
|
||||
@@ -136,13 +132,6 @@ 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-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=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
@@ -161,8 +150,6 @@ github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGK
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw=
|
||||
github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
|
||||
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
@@ -192,8 +179,6 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@@ -201,19 +186,14 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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-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=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
||||
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
|
||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -264,8 +244,6 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
|
||||
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kelindar/bitmap v1.5.2 h1:XwX7CTvJtetQZ64zrOkApoZZHBJRkjE23NfqUALA/HE=
|
||||
@@ -307,8 +285,6 @@ 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=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
@@ -335,22 +311,18 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ
|
||||
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
|
||||
github.com/mozillazg/go-httpheader v0.4.0 h1:aBn6aRXtFzyDLZ4VIRLsZbbJloagQfMnCiYgOq6hK4w=
|
||||
github.com/mozillazg/go-httpheader v0.4.0/go.mod h1:PuT8h0pw6efvp8ZeUec1Rs7dwjK08bt6gKSReGMqtdA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
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.5 h1:eEZCEHm+NsmcO3onXZPIUbGFCYPYbsX5beV3ZyOsGhY=
|
||||
github.com/openimsdk/gomake v0.0.15-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
|
||||
github.com/openimsdk/protocol v0.0.73-alpha.12 h1:2NYawXeHChYUeSme6QJ9pOLh+Empce2WmwEtbP4JvKk=
|
||||
github.com/openimsdk/protocol v0.0.73-alpha.12/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.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y=
|
||||
github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.63 h1:IyPBibEvwBtTmD8DSrlqcekfEXe74k4+KeeHsgdhGh0=
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.63/go.mod h1:Iet+piS/jaS+kWWyj6EEr36mk4ISzIRYjoMSVA4dq2M=
|
||||
github.com/openimsdk/tools v0.0.50-alpha.50 h1:+naDlvHcqJDj2NsCGnQd1LLQOET5IRPbrtmWbM/o7JQ=
|
||||
github.com/openimsdk/tools v0.0.50-alpha.50/go.mod h1:muCtxguNJv8lFwLei27UASu2Nvg4ERSeN0R4K5tivk0=
|
||||
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=
|
||||
@@ -384,8 +356,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.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
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=
|
||||
@@ -393,8 +365,6 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sercand/kuberesolver/v6 v6.0.1 h1:XZUTA0gy/lgDYp/UhEwv7Js24F1j8NJ833QrWv0Xux4=
|
||||
github.com/sercand/kuberesolver/v6 v6.0.1/go.mod h1:C0tsTuRMONSY+Xf7pv7RMW1/JlewY1+wS8SZE+1lf1s=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
@@ -409,6 +379,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
||||
github.com/stathat/consistent v1.0.0 h1:ZFJ1QTRn8npNBKW065raSZ8xfOqhpb8vLOkfp4CcL/U=
|
||||
github.com/stathat/consistent v1.0.0/go.mod h1:uajTPbgSygZBJ+V+0mY7meZ8i0XAcZs7AQ6V121XSxw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@@ -422,9 +394,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
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 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
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/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=
|
||||
@@ -439,8 +410,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
||||
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=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
@@ -464,28 +433,24 @@ 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/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.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw=
|
||||
go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
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=
|
||||
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
@@ -500,8 +465,8 @@ 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.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
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=
|
||||
@@ -529,19 +494,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.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
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.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
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.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
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=
|
||||
@@ -556,14 +521,12 @@ 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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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/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=
|
||||
@@ -572,8 +535,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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
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=
|
||||
@@ -585,8 +548,6 @@ 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/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=
|
||||
@@ -604,17 +565,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-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
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.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||
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=
|
||||
@@ -624,21 +585,18 @@ 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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
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=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -649,23 +607,7 @@ gorm.io/gorm v1.25.8 h1:WAGEZ/aEcznN4D03laj8DKnehe1e9gYQAjW8xyPRdeo=
|
||||
gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=
|
||||
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=
|
||||
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=
|
||||
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc=
|
||||
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
stathat.com/c/consistent v1.0.0 h1:ezyc51EGcRPJUxfHGSgJjWzJdj3NiMU9pNfLNGiXV0c=
|
||||
stathat.com/c/consistent v1.0.0/go.mod h1:QkzMWzcbB+yQBL2AttO6sgsQS/JSTapcDISJalmCDS0=
|
||||
|
||||
@@ -16,30 +16,29 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type AuthApi struct {
|
||||
Client auth.AuthClient
|
||||
}
|
||||
type AuthApi rpcclient.Auth
|
||||
|
||||
func NewAuthApi(client auth.AuthClient) AuthApi {
|
||||
return AuthApi{client}
|
||||
func NewAuthApi(client rpcclient.Auth) AuthApi {
|
||||
return AuthApi(client)
|
||||
}
|
||||
|
||||
func (o *AuthApi) GetAdminToken(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.GetAdminToken, o.Client)
|
||||
a2r.Call(auth.AuthClient.GetAdminToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *AuthApi) GetUserToken(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.GetUserToken, o.Client)
|
||||
a2r.Call(auth.AuthClient.GetUserToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *AuthApi) ParseToken(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.ParseToken, o.Client)
|
||||
a2r.Call(auth.AuthClient.ParseToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *AuthApi) ForceLogout(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.ForceLogout, o.Client)
|
||||
a2r.Call(auth.AuthClient.ForceLogout, o.Client, c)
|
||||
}
|
||||
|
||||
@@ -1,313 +0,0 @@
|
||||
package api
|
||||
|
||||
//
|
||||
//import (
|
||||
// "encoding/json"
|
||||
// "reflect"
|
||||
// "strconv"
|
||||
// "time"
|
||||
//
|
||||
// "github.com/gin-gonic/gin"
|
||||
// "github.com/openimsdk/open-im-server/v3/pkg/apistruct"
|
||||
// "github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
// "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
// "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
||||
// "github.com/openimsdk/open-im-server/v3/version"
|
||||
// "github.com/openimsdk/tools/apiresp"
|
||||
// "github.com/openimsdk/tools/errs"
|
||||
// "github.com/openimsdk/tools/log"
|
||||
// "github.com/openimsdk/tools/utils/runtimeenv"
|
||||
// clientv3 "go.etcd.io/etcd/client/v3"
|
||||
//)
|
||||
//
|
||||
//const (
|
||||
// // wait for Restart http call return
|
||||
// waitHttp = time.Millisecond * 200
|
||||
//)
|
||||
//
|
||||
//type ConfigManager struct {
|
||||
// imAdminUserID []string
|
||||
// config *config.AllConfig
|
||||
// client *clientv3.Client
|
||||
//
|
||||
// configPath string
|
||||
// runtimeEnv string
|
||||
//}
|
||||
//
|
||||
//func NewConfigManager(IMAdminUserID []string, cfg *config.AllConfig, client *clientv3.Client, configPath string, runtimeEnv string) *ConfigManager {
|
||||
// cm := &ConfigManager{
|
||||
// imAdminUserID: IMAdminUserID,
|
||||
// config: cfg,
|
||||
// client: client,
|
||||
// configPath: configPath,
|
||||
// runtimeEnv: runtimeEnv,
|
||||
// }
|
||||
// return cm
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) CheckAdmin(c *gin.Context) {
|
||||
// if err := authverify.CheckAdmin(c, cm.imAdminUserID); err != nil {
|
||||
// apiresp.GinError(c, err)
|
||||
// c.Abort()
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) GetConfig(c *gin.Context) {
|
||||
// var req apistruct.GetConfigReq
|
||||
// if err := c.BindJSON(&req); err != nil {
|
||||
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||
// return
|
||||
// }
|
||||
// conf := cm.config.Name2Config(req.ConfigName)
|
||||
// if conf == nil {
|
||||
// apiresp.GinError(c, errs.ErrArgs.WithDetail("config name not found").Wrap())
|
||||
// return
|
||||
// }
|
||||
// b, err := json.Marshal(conf)
|
||||
// if err != nil {
|
||||
// apiresp.GinError(c, err)
|
||||
// return
|
||||
// }
|
||||
// apiresp.GinSuccess(c, string(b))
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) GetConfigList(c *gin.Context) {
|
||||
// var resp apistruct.GetConfigListResp
|
||||
// resp.ConfigNames = cm.config.GetConfigNames()
|
||||
// resp.Environment = runtimeenv.PrintRuntimeEnvironment()
|
||||
// resp.Version = version.Version
|
||||
//
|
||||
// apiresp.GinSuccess(c, resp)
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) SetConfig(c *gin.Context) {
|
||||
// if cm.config.Discovery.Enable != config.ETCD {
|
||||
// apiresp.GinError(c, errs.New("only etcd support set config").Wrap())
|
||||
// return
|
||||
// }
|
||||
// var req apistruct.SetConfigReq
|
||||
// if err := c.BindJSON(&req); err != nil {
|
||||
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||
// return
|
||||
// }
|
||||
// var err error
|
||||
// switch req.ConfigName {
|
||||
// case cm.config.Discovery.GetConfigFileName():
|
||||
// err = compareAndSave[config.Discovery](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Kafka.GetConfigFileName():
|
||||
// err = compareAndSave[config.Kafka](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.LocalCache.GetConfigFileName():
|
||||
// err = compareAndSave[config.LocalCache](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Log.GetConfigFileName():
|
||||
// err = compareAndSave[config.Log](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Minio.GetConfigFileName():
|
||||
// err = compareAndSave[config.Minio](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Mongo.GetConfigFileName():
|
||||
// err = compareAndSave[config.Mongo](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Notification.GetConfigFileName():
|
||||
// err = compareAndSave[config.Notification](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.API.GetConfigFileName():
|
||||
// err = compareAndSave[config.API](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.CronTask.GetConfigFileName():
|
||||
// err = compareAndSave[config.CronTask](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.MsgGateway.GetConfigFileName():
|
||||
// err = compareAndSave[config.MsgGateway](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.MsgTransfer.GetConfigFileName():
|
||||
// err = compareAndSave[config.MsgTransfer](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Push.GetConfigFileName():
|
||||
// err = compareAndSave[config.Push](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Auth.GetConfigFileName():
|
||||
// err = compareAndSave[config.Auth](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Conversation.GetConfigFileName():
|
||||
// err = compareAndSave[config.Conversation](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Friend.GetConfigFileName():
|
||||
// err = compareAndSave[config.Friend](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Group.GetConfigFileName():
|
||||
// err = compareAndSave[config.Group](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Msg.GetConfigFileName():
|
||||
// err = compareAndSave[config.Msg](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Third.GetConfigFileName():
|
||||
// err = compareAndSave[config.Third](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.User.GetConfigFileName():
|
||||
// err = compareAndSave[config.User](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Redis.GetConfigFileName():
|
||||
// err = compareAndSave[config.Redis](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Share.GetConfigFileName():
|
||||
// err = compareAndSave[config.Share](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// case cm.config.Webhooks.GetConfigFileName():
|
||||
// err = compareAndSave[config.Webhooks](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||
// default:
|
||||
// apiresp.GinError(c, errs.ErrArgs.Wrap())
|
||||
// return
|
||||
// }
|
||||
// if err != nil {
|
||||
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||
// return
|
||||
// }
|
||||
// apiresp.GinSuccess(c, nil)
|
||||
//}
|
||||
//
|
||||
//func compareAndSave[T any](c *gin.Context, old any, req *apistruct.SetConfigReq, cm *ConfigManager) error {
|
||||
// conf := new(T)
|
||||
// err := json.Unmarshal([]byte(req.Data), &conf)
|
||||
// if err != nil {
|
||||
// return errs.ErrArgs.WithDetail(err.Error()).Wrap()
|
||||
// }
|
||||
// eq := reflect.DeepEqual(old, conf)
|
||||
// if eq {
|
||||
// return nil
|
||||
// }
|
||||
// data, err := json.Marshal(conf)
|
||||
// if err != nil {
|
||||
// return errs.ErrArgs.WithDetail(err.Error()).Wrap()
|
||||
// }
|
||||
// _, err = cm.client.Put(c, etcd.BuildKey(req.ConfigName), string(data))
|
||||
// if err != nil {
|
||||
// return errs.WrapMsg(err, "save to etcd failed")
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) ResetConfig(c *gin.Context) {
|
||||
// go func() {
|
||||
// if err := cm.resetConfig(c, true); err != nil {
|
||||
// log.ZError(c, "reset config err", err)
|
||||
// }
|
||||
// }()
|
||||
// apiresp.GinSuccess(c, nil)
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) resetConfig(c *gin.Context, checkChange bool, ops ...clientv3.Op) error {
|
||||
// txn := cm.client.Txn(c)
|
||||
// type initConf struct {
|
||||
// old any
|
||||
// new any
|
||||
// }
|
||||
// configMap := map[string]*initConf{
|
||||
// cm.config.Discovery.GetConfigFileName(): {old: &cm.config.Discovery, new: new(config.Discovery)},
|
||||
// cm.config.Kafka.GetConfigFileName(): {old: &cm.config.Kafka, new: new(config.Kafka)},
|
||||
// cm.config.LocalCache.GetConfigFileName(): {old: &cm.config.LocalCache, new: new(config.LocalCache)},
|
||||
// cm.config.Log.GetConfigFileName(): {old: &cm.config.Log, new: new(config.Log)},
|
||||
// cm.config.Minio.GetConfigFileName(): {old: &cm.config.Minio, new: new(config.Minio)},
|
||||
// cm.config.Mongo.GetConfigFileName(): {old: &cm.config.Mongo, new: new(config.Mongo)},
|
||||
// cm.config.Notification.GetConfigFileName(): {old: &cm.config.Notification, new: new(config.Notification)},
|
||||
// cm.config.API.GetConfigFileName(): {old: &cm.config.API, new: new(config.API)},
|
||||
// cm.config.CronTask.GetConfigFileName(): {old: &cm.config.CronTask, new: new(config.CronTask)},
|
||||
// cm.config.MsgGateway.GetConfigFileName(): {old: &cm.config.MsgGateway, new: new(config.MsgGateway)},
|
||||
// cm.config.MsgTransfer.GetConfigFileName(): {old: &cm.config.MsgTransfer, new: new(config.MsgTransfer)},
|
||||
// cm.config.Push.GetConfigFileName(): {old: &cm.config.Push, new: new(config.Push)},
|
||||
// cm.config.Auth.GetConfigFileName(): {old: &cm.config.Auth, new: new(config.Auth)},
|
||||
// cm.config.Conversation.GetConfigFileName(): {old: &cm.config.Conversation, new: new(config.Conversation)},
|
||||
// cm.config.Friend.GetConfigFileName(): {old: &cm.config.Friend, new: new(config.Friend)},
|
||||
// cm.config.Group.GetConfigFileName(): {old: &cm.config.Group, new: new(config.Group)},
|
||||
// cm.config.Msg.GetConfigFileName(): {old: &cm.config.Msg, new: new(config.Msg)},
|
||||
// cm.config.Third.GetConfigFileName(): {old: &cm.config.Third, new: new(config.Third)},
|
||||
// cm.config.User.GetConfigFileName(): {old: &cm.config.User, new: new(config.User)},
|
||||
// cm.config.Redis.GetConfigFileName(): {old: &cm.config.Redis, new: new(config.Redis)},
|
||||
// cm.config.Share.GetConfigFileName(): {old: &cm.config.Share, new: new(config.Share)},
|
||||
// cm.config.Webhooks.GetConfigFileName(): {old: &cm.config.Webhooks, new: new(config.Webhooks)},
|
||||
// }
|
||||
//
|
||||
// changedKeys := make([]string, 0, len(configMap))
|
||||
// for k, v := range configMap {
|
||||
// err := config.Load(
|
||||
// cm.configPath,
|
||||
// k,
|
||||
// config.EnvPrefixMap[k],
|
||||
// cm.runtimeEnv,
|
||||
// v.new,
|
||||
// )
|
||||
// if err != nil {
|
||||
// log.ZError(c, "load config failed", err)
|
||||
// continue
|
||||
// }
|
||||
// equal := reflect.DeepEqual(v.old, v.new)
|
||||
// if !checkChange || !equal {
|
||||
// changedKeys = append(changedKeys, k)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for _, k := range changedKeys {
|
||||
// data, err := json.Marshal(configMap[k].new)
|
||||
// if err != nil {
|
||||
// log.ZError(c, "marshal config failed", err)
|
||||
// continue
|
||||
// }
|
||||
// ops = append(ops, clientv3.OpPut(etcd.BuildKey(k), string(data)))
|
||||
// }
|
||||
// if len(ops) > 0 {
|
||||
// txn.Then(ops...)
|
||||
// _, err := txn.Commit()
|
||||
// if err != nil {
|
||||
// return errs.WrapMsg(err, "commit etcd txn failed")
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) Restart(c *gin.Context) {
|
||||
// go cm.restart(c)
|
||||
// apiresp.GinSuccess(c, nil)
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) restart(c *gin.Context) {
|
||||
// time.Sleep(waitHttp) // wait for Restart http call return
|
||||
// t := time.Now().Unix()
|
||||
// _, err := cm.client.Put(c, etcd.BuildKey(etcd.RestartKey), strconv.Itoa(int(t)))
|
||||
// if err != nil {
|
||||
// log.ZError(c, "restart etcd put key failed", err)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) SetEnableConfigManager(c *gin.Context) {
|
||||
// if cm.config.Discovery.Enable != config.ETCD {
|
||||
// apiresp.GinError(c, errs.New("only etcd support config manager").Wrap())
|
||||
// return
|
||||
// }
|
||||
// var req apistruct.SetEnableConfigManagerReq
|
||||
// if err := c.BindJSON(&req); err != nil {
|
||||
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||
// return
|
||||
// }
|
||||
// var enableStr string
|
||||
// if req.Enable {
|
||||
// enableStr = etcd.Enable
|
||||
// } else {
|
||||
// enableStr = etcd.Disable
|
||||
// }
|
||||
// resp, err := cm.client.Get(c, etcd.BuildKey(etcd.EnableConfigCenterKey))
|
||||
// if err != nil {
|
||||
// apiresp.GinError(c, errs.WrapMsg(err, "getEnableConfigManager failed"))
|
||||
// return
|
||||
// }
|
||||
// if !(resp.Count > 0 && string(resp.Kvs[0].Value) == etcd.Enable) && req.Enable {
|
||||
// go func() {
|
||||
// time.Sleep(waitHttp) // wait for Restart http call return
|
||||
// err := cm.resetConfig(c, false, clientv3.OpPut(etcd.BuildKey(etcd.EnableConfigCenterKey), enableStr))
|
||||
// if err != nil {
|
||||
// log.ZError(c, "resetConfig failed", err)
|
||||
// }
|
||||
// }()
|
||||
// } else {
|
||||
// _, err = cm.client.Put(c, etcd.BuildKey(etcd.EnableConfigCenterKey), enableStr)
|
||||
// if err != nil {
|
||||
// apiresp.GinError(c, errs.WrapMsg(err, "setEnableConfigManager failed"))
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// apiresp.GinSuccess(c, nil)
|
||||
//}
|
||||
//
|
||||
//func (cm *ConfigManager) GetEnableConfigManager(c *gin.Context) {
|
||||
// resp, err := cm.client.Get(c, etcd.BuildKey(etcd.EnableConfigCenterKey))
|
||||
// if err != nil {
|
||||
// apiresp.GinError(c, errs.WrapMsg(err, "getEnableConfigManager failed"))
|
||||
// return
|
||||
// }
|
||||
// var enable bool
|
||||
// if resp.Count > 0 && string(resp.Kvs[0].Value) == etcd.Enable {
|
||||
// enable = true
|
||||
// }
|
||||
// apiresp.GinSuccess(c, &apistruct.GetEnableConfigManagerResp{Enable: enable})
|
||||
//}
|
||||
@@ -16,58 +16,57 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type ConversationApi struct {
|
||||
Client conversation.ConversationClient
|
||||
}
|
||||
type ConversationApi rpcclient.Conversation
|
||||
|
||||
func NewConversationApi(client conversation.ConversationClient) ConversationApi {
|
||||
return ConversationApi{client}
|
||||
func NewConversationApi(client rpcclient.Conversation) ConversationApi {
|
||||
return ConversationApi(client)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetAllConversations(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetAllConversations, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetAllConversations, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetSortedConversationList(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetSortedConversationList, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetSortedConversationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetConversation(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetConversation, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetConversation, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetConversations(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetConversations, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetConversations, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) SetConversations(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.SetConversations, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.SetConversations, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetConversationOfflinePushUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetConversationOfflinePushUserIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetConversationOfflinePushUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetFullOwnerConversationIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetFullOwnerConversationIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetFullOwnerConversationIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetIncrementalConversation(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetIncrementalConversation, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetIncrementalConversation, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetOwnerConversation(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetOwnerConversation, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetOwnerConversation, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetNotNotifyConversationIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetNotNotifyConversationIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetNotNotifyConversationIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetPinnedConversationIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetPinnedConversationIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetPinnedConversationIDs, o.Client, c)
|
||||
}
|
||||
|
||||
+25
-30
@@ -17,104 +17,99 @@ package api
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type FriendApi struct {
|
||||
Client relation.FriendClient
|
||||
}
|
||||
type FriendApi rpcclient.Friend
|
||||
|
||||
func NewFriendApi(client relation.FriendClient) FriendApi {
|
||||
return FriendApi{client}
|
||||
func NewFriendApi(client rpcclient.Friend) FriendApi {
|
||||
return FriendApi(client)
|
||||
}
|
||||
|
||||
func (o *FriendApi) ApplyToAddFriend(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.ApplyToAddFriend, o.Client)
|
||||
a2r.Call(relation.FriendClient.ApplyToAddFriend, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) RespondFriendApply(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.RespondFriendApply, o.Client)
|
||||
a2r.Call(relation.FriendClient.RespondFriendApply, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) DeleteFriend(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.DeleteFriend, o.Client)
|
||||
a2r.Call(relation.FriendClient.DeleteFriend, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFriendApplyList(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationFriendsApplyTo, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationFriendsApplyTo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetDesignatedFriendsApply(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetDesignatedFriendsApply, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetDesignatedFriendsApply, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetSelfApplyList(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationFriendsApplyFrom, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationFriendsApplyFrom, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFriendList(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetDesignatedFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetDesignatedFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetDesignatedFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) SetFriendRemark(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.SetFriendRemark, o.Client)
|
||||
a2r.Call(relation.FriendClient.SetFriendRemark, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) AddBlack(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.AddBlack, o.Client)
|
||||
a2r.Call(relation.FriendClient.AddBlack, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetPaginationBlacks(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationBlacks, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationBlacks, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetSpecifiedBlacks(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetSpecifiedBlacks, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetSpecifiedBlacks, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) RemoveBlack(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.RemoveBlack, o.Client)
|
||||
a2r.Call(relation.FriendClient.RemoveBlack, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) ImportFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.ImportFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.ImportFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) IsFriend(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.IsFriend, o.Client)
|
||||
a2r.Call(relation.FriendClient.IsFriend, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFriendIDs(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetFriendIDs, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetFriendIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetSpecifiedFriendsInfo, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetSpecifiedFriendsInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) UpdateFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.UpdateFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.UpdateFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetIncrementalFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetIncrementalFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetIncrementalFriends, o.Client, c)
|
||||
}
|
||||
|
||||
// GetIncrementalBlacks is temporarily unused.
|
||||
// Deprecated: This function is currently unused and may be removed in future versions.
|
||||
func (o *FriendApi) GetIncrementalBlacks(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetIncrementalBlacks, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetIncrementalBlacks, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFullFriendUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetFullFriendUserIDs, o.Client)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetSelfUnhandledApplyCount(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetSelfUnhandledApplyCount, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetFullFriendUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
+40
-45
@@ -16,156 +16,151 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type GroupApi struct {
|
||||
Client group.GroupClient
|
||||
}
|
||||
type GroupApi rpcclient.Group
|
||||
|
||||
func NewGroupApi(client group.GroupClient) GroupApi {
|
||||
return GroupApi{client}
|
||||
func NewGroupApi(client rpcclient.Group) GroupApi {
|
||||
return GroupApi(client)
|
||||
}
|
||||
|
||||
func (o *GroupApi) CreateGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.CreateGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.CreateGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) SetGroupInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.SetGroupInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.SetGroupInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) SetGroupInfoEx(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.SetGroupInfoEx, o.Client)
|
||||
a2r.Call(group.GroupClient.SetGroupInfoEx, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) JoinGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.JoinGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.JoinGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) QuitGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.QuitGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.QuitGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) ApplicationGroupResponse(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GroupApplicationResponse, o.Client)
|
||||
a2r.Call(group.GroupClient.GroupApplicationResponse, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) TransferGroupOwner(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.TransferGroupOwner, o.Client)
|
||||
a2r.Call(group.GroupClient.TransferGroupOwner, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetRecvGroupApplicationList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupApplicationList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupApplicationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetUserReqGroupApplicationList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetUserReqApplicationList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetUserReqApplicationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupUsersReqApplicationList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupUsersReqApplicationList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupUsersReqApplicationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetSpecifiedUserGroupRequestInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetSpecifiedUserGroupRequestInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.GetSpecifiedUserGroupRequestInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupsInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupsInfo, o.Client)
|
||||
//a2r.Call(c, group.GroupClient.GetGroupsInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupsInfo))
|
||||
a2r.Call(group.GroupClient.GetGroupsInfo, o.Client, c)
|
||||
//a2r.Call(group.GroupClient.GetGroupsInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupsInfo))
|
||||
}
|
||||
|
||||
func (o *GroupApi) KickGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.KickGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.KickGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupMembersInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupMembersInfo, o.Client)
|
||||
//a2r.Call(c, group.GroupClient.GetGroupMembersInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupMembersInfo))
|
||||
a2r.Call(group.GroupClient.GetGroupMembersInfo, o.Client, c)
|
||||
//a2r.Call(group.GroupClient.GetGroupMembersInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupMembersInfo))
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupMemberList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupMemberList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupMemberList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) InviteUserToGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.InviteUserToGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.InviteUserToGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetJoinedGroupList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetJoinedGroupList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetJoinedGroupList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) DismissGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.DismissGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.DismissGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) MuteGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.MuteGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.MuteGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) CancelMuteGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.CancelMuteGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.CancelMuteGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) MuteGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.MuteGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.MuteGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) CancelMuteGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.CancelMuteGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.CancelMuteGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) SetGroupMemberInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.SetGroupMemberInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.SetGroupMemberInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupAbstractInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupAbstractInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupAbstractInfo, o.Client, c)
|
||||
}
|
||||
|
||||
// func (g *Group) SetGroupMemberNickname(c *gin.Context) {
|
||||
// a2r.Call(c, group.GroupClient.SetGroupMemberNickname, g.userClient)
|
||||
// a2r.Call(group.GroupClient.SetGroupMemberNickname, g.userClient, c)
|
||||
//}
|
||||
//
|
||||
// func (g *Group) GetGroupAllMemberList(c *gin.Context) {
|
||||
// a2r.Call(c, group.GroupClient.GetGroupAllMember, g.userClient)
|
||||
// a2r.Call(group.GroupClient.GetGroupAllMember, g.userClient, c)
|
||||
//}
|
||||
|
||||
func (o *GroupApi) GroupCreateCount(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GroupCreateCount, o.Client)
|
||||
a2r.Call(group.GroupClient.GroupCreateCount, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroups(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroups, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroups, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupMemberUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupMemberUserIDs, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupMemberUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetIncrementalJoinGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetIncrementalJoinGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.GetIncrementalJoinGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetIncrementalGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetIncrementalGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.GetIncrementalGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetIncrementalGroupMemberBatch(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.BatchGetIncrementalGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.BatchGetIncrementalGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetFullGroupMemberUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetFullGroupMemberUserIDs, o.Client)
|
||||
a2r.Call(group.GroupClient.GetFullGroupMemberUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetFullJoinGroupIDs(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetFullJoinGroupIDs, o.Client)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupApplicationUnhandledCount(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupApplicationUnhandledCount, o.Client)
|
||||
a2r.Call(group.GroupClient.GetFullJoinGroupIDs, o.Client, c)
|
||||
}
|
||||
|
||||
+31
-79
@@ -1,9 +1,25 @@
|
||||
// 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.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/openimsdk/tools/utils/network"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -12,21 +28,12 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/tools/mw"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/openimsdk/tools/utils/network"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/discovery/etcd"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/system/program"
|
||||
"github.com/openimsdk/tools/utils/jsonutil"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -35,8 +42,8 @@ type Config struct {
|
||||
Discovery config.Discovery
|
||||
}
|
||||
|
||||
func Start(ctx context.Context, index int, cfg *Config) error {
|
||||
apiPort, err := datautil.GetElemByIndex(cfg.API.Api.Ports, index)
|
||||
func Start(ctx context.Context, index int, config *Config) error {
|
||||
apiPort, err := datautil.GetElemByIndex(config.API.Api.Ports, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -44,14 +51,10 @@ func Start(ctx context.Context, index int, cfg *Config) error {
|
||||
var client discovery.SvcDiscoveryRegistry
|
||||
|
||||
// Determine whether zk is passed according to whether it is a clustered deployment
|
||||
client, err = kdisc.NewDiscoveryRegister(&cfg.Discovery, &cfg.Share, []string{
|
||||
cfg.Share.RpcRegisterName.MessageGateway,
|
||||
})
|
||||
client, err = kdisc.NewDiscoveryRegister(&config.Discovery, &config.Share)
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "failed to register discovery service")
|
||||
}
|
||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||
|
||||
var (
|
||||
netDone = make(chan struct{}, 1)
|
||||
@@ -59,80 +62,29 @@ func Start(ctx context.Context, index int, cfg *Config) error {
|
||||
prometheusPort int
|
||||
)
|
||||
|
||||
router, err := newGinRouter(ctx, client, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
registerIP, err := network.GetRpcRegisterIP("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
getAutoPort := func() (net.Listener, int, error) {
|
||||
registerAddr := net.JoinHostPort(registerIP, "0")
|
||||
listener, err := net.Listen("tcp", registerAddr)
|
||||
if err != nil {
|
||||
return nil, 0, errs.WrapMsg(err, "listen err", "registerAddr", registerAddr)
|
||||
}
|
||||
_, portStr, _ := net.SplitHostPort(listener.Addr().String())
|
||||
port, _ := strconv.Atoi(portStr)
|
||||
return listener, port, nil
|
||||
}
|
||||
|
||||
if cfg.API.Prometheus.AutoSetPorts && cfg.Discovery.Enable != config.ETCD {
|
||||
return errs.New("only etcd support autoSetPorts", "RegisterName", "api").Wrap()
|
||||
}
|
||||
|
||||
if cfg.API.Prometheus.Enable {
|
||||
var (
|
||||
listener net.Listener
|
||||
)
|
||||
|
||||
if cfg.API.Prometheus.AutoSetPorts {
|
||||
listener, prometheusPort, err = getAutoPort()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
etcdClient, ok := client.(*etcd.SvcDiscoveryRegistryImpl)
|
||||
if !ok {
|
||||
return errs.New("only etcd support autoSetPorts").Wrap()
|
||||
}
|
||||
|
||||
target, err := jsonutil.JsonMarshal(prommetrics.BuildDefaultTarget(registerIP, prometheusPort))
|
||||
if err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
err = etcdClient.SetWithLease(ctx, prommetrics.BuildDiscoveryKey(prommetrics.APIKeyName, index), target, prommetrics.TTL)
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "etcd put err")
|
||||
}
|
||||
} else {
|
||||
prometheusPort, err = datautil.GetElemByIndex(cfg.API.Prometheus.Ports, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listener, err = net.Listen("tcp", fmt.Sprintf(":%d", prometheusPort))
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "listen err", "addr", fmt.Sprintf(":%d", prometheusPort))
|
||||
}
|
||||
}
|
||||
|
||||
router := newGinRouter(client, config)
|
||||
if config.API.Prometheus.Enable {
|
||||
go func() {
|
||||
if err := prommetrics.ApiInit(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
prometheusPort, err = datautil.GetElemByIndex(config.API.Prometheus.Ports, index)
|
||||
if err != nil {
|
||||
netErr = err
|
||||
netDone <- struct{}{}
|
||||
return
|
||||
}
|
||||
if err := prommetrics.ApiInit(prometheusPort); err != nil && err != http.ErrServerClosed {
|
||||
netErr = errs.WrapMsg(err, fmt.Sprintf("api prometheus start err: %d", prometheusPort))
|
||||
netDone <- struct{}{}
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
address := net.JoinHostPort(network.GetListenIP(cfg.API.Api.ListenIP), strconv.Itoa(apiPort))
|
||||
address := net.JoinHostPort(network.GetListenIP(config.API.Api.ListenIP), strconv.Itoa(apiPort))
|
||||
|
||||
server := http.Server{Addr: address, Handler: router}
|
||||
log.CInfo(ctx, "API server is initializing", "address", address, "apiPort", apiPort, "prometheusPort", prometheusPort)
|
||||
go func() {
|
||||
err = server.ListenAndServe()
|
||||
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
netErr = errs.WrapMsg(err, fmt.Sprintf("api start err: %s", server.Addr))
|
||||
netDone <- struct{}{}
|
||||
|
||||
|
||||
+68
-95
@@ -2,21 +2,17 @@ package jssdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/tools/log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/protocol/jssdk"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -24,23 +20,22 @@ const (
|
||||
defaultGetActiveConversation = 100
|
||||
)
|
||||
|
||||
func NewJSSdkApi(userClient *rpcli.UserClient, relationClient *rpcli.RelationClient, groupClient *rpcli.GroupClient,
|
||||
conversationClient *rpcli.ConversationClient, msgClient *rpcli.MsgClient) *JSSdk {
|
||||
func NewJSSdkApi(user user.UserClient, friend relation.FriendClient, group group.GroupClient, msg msg.MsgClient, conv conversation.ConversationClient) *JSSdk {
|
||||
return &JSSdk{
|
||||
userClient: userClient,
|
||||
relationClient: relationClient,
|
||||
groupClient: groupClient,
|
||||
conversationClient: conversationClient,
|
||||
msgClient: msgClient,
|
||||
user: user,
|
||||
friend: friend,
|
||||
group: group,
|
||||
msg: msg,
|
||||
conv: conv,
|
||||
}
|
||||
}
|
||||
|
||||
type JSSdk struct {
|
||||
userClient *rpcli.UserClient
|
||||
relationClient *rpcli.RelationClient
|
||||
groupClient *rpcli.GroupClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
msgClient *rpcli.MsgClient
|
||||
user user.UserClient
|
||||
friend relation.FriendClient
|
||||
group group.GroupClient
|
||||
msg msg.MsgClient
|
||||
conv conversation.ConversationClient
|
||||
}
|
||||
|
||||
func (x *JSSdk) GetActiveConversations(c *gin.Context) {
|
||||
@@ -72,11 +67,11 @@ func (x *JSSdk) fillConversations(ctx context.Context, conversations []*jssdk.Co
|
||||
groupMap map[string]*sdkws.GroupInfo
|
||||
)
|
||||
if len(userIDs) > 0 {
|
||||
users, err := x.userClient.GetUsersInfo(ctx, userIDs)
|
||||
users, err := field(ctx, x.user.GetDesignateUsers, &user.GetDesignateUsersReq{UserIDs: userIDs}, (*user.GetDesignateUsersResp).GetUsersInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
friends, err := x.relationClient.GetFriendsInfo(ctx, conversations[0].Conversation.OwnerUserID, userIDs)
|
||||
friends, err := field(ctx, x.friend.GetFriendInfo, &relation.GetFriendInfoReq{OwnerUserID: conversations[0].Conversation.OwnerUserID, FriendUserIDs: userIDs}, (*relation.GetFriendInfoResp).GetFriendInfos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -84,11 +79,11 @@ func (x *JSSdk) fillConversations(ctx context.Context, conversations []*jssdk.Co
|
||||
friendMap = datautil.SliceToMap(friends, (*relation.FriendInfoOnly).GetFriendUserID)
|
||||
}
|
||||
if len(groupIDs) > 0 {
|
||||
groups, err := x.groupClient.GetGroupsInfo(ctx, groupIDs)
|
||||
resp, err := x.group.GetGroupsInfo(ctx, &group.GetGroupsInfoReq{GroupIDs: groupIDs})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupMap = datautil.SliceToMap(groups, (*sdkws.GroupInfo).GetGroupID)
|
||||
groupMap = datautil.SliceToMap(resp.GroupInfos, (*sdkws.GroupInfo).GetGroupID)
|
||||
}
|
||||
for _, c := range conversations {
|
||||
if c.Conversation.GroupID == "" {
|
||||
@@ -106,30 +101,33 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
req.Count = defaultGetActiveConversation
|
||||
}
|
||||
req.OwnerUserID = mcontext.GetOpUserID(ctx)
|
||||
conversationIDs, err := x.conversationClient.GetConversationIDs(ctx, req.OwnerUserID)
|
||||
conversationIDs, err := field(ctx, x.conv.GetConversationIDs,
|
||||
&conversation.GetConversationIDsReq{UserID: req.OwnerUserID}, (*conversation.GetConversationIDsResp).GetConversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(conversationIDs) == 0 {
|
||||
return &jssdk.GetActiveConversationsResp{}, nil
|
||||
}
|
||||
|
||||
activeConversation, err := x.msgClient.GetActiveConversation(ctx, conversationIDs)
|
||||
readSeq, err := field(ctx, x.msg.GetHasReadSeqs,
|
||||
&msg.GetHasReadSeqsReq{UserID: req.OwnerUserID, ConversationIDs: conversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
activeConversation, err := field(ctx, x.msg.GetActiveConversation,
|
||||
&msg.GetActiveConversationReq{ConversationIDs: conversationIDs}, (*msg.GetActiveConversationResp).GetConversations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(activeConversation) == 0 {
|
||||
return &jssdk.GetActiveConversationsResp{}, nil
|
||||
}
|
||||
readSeq, err := x.msgClient.GetHasReadSeqs(ctx, conversationIDs, req.OwnerUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sortConversations := sortActiveConversations{
|
||||
Conversation: activeConversation,
|
||||
}
|
||||
if len(activeConversation) > 1 {
|
||||
pinnedConversationIDs, err := x.conversationClient.GetPinnedConversationIDs(ctx, req.OwnerUserID)
|
||||
pinnedConversationIDs, err := field(ctx, x.conv.GetPinnedConversationIDs,
|
||||
&conversation.GetPinnedConversationIDsReq{UserID: req.OwnerUserID}, (*conversation.GetPinnedConversationIDsResp).GetConversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -137,22 +135,28 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
}
|
||||
sort.Sort(&sortConversations)
|
||||
sortList := sortConversations.Top(int(req.Count))
|
||||
conversations, err := x.conversationClient.GetConversations(ctx, datautil.Slice(sortList, func(c *msg.ActiveConversation) string {
|
||||
return c.ConversationID
|
||||
}), req.OwnerUserID)
|
||||
conversations, err := field(ctx, x.conv.GetConversations,
|
||||
&conversation.GetConversationsReq{
|
||||
OwnerUserID: req.OwnerUserID,
|
||||
ConversationIDs: datautil.Slice(sortList, func(c *msg.ActiveConversation) string {
|
||||
return c.ConversationID
|
||||
})}, (*conversation.GetConversationsResp).GetConversations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgs, err := x.msgClient.GetSeqMessage(ctx, req.OwnerUserID, datautil.Slice(sortList, func(c *msg.ActiveConversation) *msg.ConversationSeqs {
|
||||
return &msg.ConversationSeqs{
|
||||
ConversationID: c.ConversationID,
|
||||
Seqs: []int64{c.MaxSeq},
|
||||
}
|
||||
}))
|
||||
msgs, err := field(ctx, x.msg.GetSeqMessage,
|
||||
&msg.GetSeqMessageReq{
|
||||
UserID: req.OwnerUserID,
|
||||
Conversations: datautil.Slice(sortList, func(c *msg.ActiveConversation) *msg.ConversationSeqs {
|
||||
return &msg.ConversationSeqs{
|
||||
ConversationID: c.ConversationID,
|
||||
Seqs: []int64{c.MaxSeq},
|
||||
}
|
||||
}),
|
||||
}, (*msg.GetSeqMessageResp).GetMsgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x.checkMessagesAndGetLastMessage(ctx, req.OwnerUserID, msgs)
|
||||
conversationMap := datautil.SliceToMap(conversations, func(c *conversation.Conversation) string {
|
||||
return c.ConversationID
|
||||
})
|
||||
@@ -162,15 +166,16 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
var lastMsg *sdkws.MsgData
|
||||
if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
|
||||
resp = append(resp, &jssdk.ConversationMsg{
|
||||
Conversation: conv,
|
||||
LastMsg: msgList.Msgs[0],
|
||||
MaxSeq: c.MaxSeq,
|
||||
ReadSeq: readSeq[c.ConversationID],
|
||||
})
|
||||
lastMsg = msgList.Msgs[0]
|
||||
}
|
||||
|
||||
resp = append(resp, &jssdk.ConversationMsg{
|
||||
Conversation: conv,
|
||||
LastMsg: lastMsg,
|
||||
MaxSeq: c.MaxSeq,
|
||||
ReadSeq: readSeq[c.ConversationID],
|
||||
})
|
||||
}
|
||||
if err := x.fillConversations(ctx, resp); err != nil {
|
||||
return nil, err
|
||||
@@ -190,7 +195,7 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
|
||||
func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversationsReq) (*jssdk.GetConversationsResp, error) {
|
||||
req.OwnerUserID = mcontext.GetOpUserID(ctx)
|
||||
conversations, err := x.conversationClient.GetConversations(ctx, req.ConversationIDs, req.OwnerUserID)
|
||||
conversations, err := field(ctx, x.conv.GetConversations, &conversation.GetConversationsReq{OwnerUserID: req.OwnerUserID, ConversationIDs: req.ConversationIDs}, (*conversation.GetConversationsResp).GetConversations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -200,11 +205,13 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
|
||||
req.ConversationIDs = datautil.Slice(conversations, func(c *conversation.Conversation) string {
|
||||
return c.ConversationID
|
||||
})
|
||||
maxSeqs, err := x.msgClient.GetMaxSeqs(ctx, req.ConversationIDs)
|
||||
maxSeqs, err := field(ctx, x.msg.GetMaxSeqs,
|
||||
&msg.GetMaxSeqsReq{ConversationIDs: req.ConversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
readSeqs, err := x.msgClient.GetHasReadSeqs(ctx, req.ConversationIDs, req.OwnerUserID)
|
||||
readSeqs, err := field(ctx, x.msg.GetHasReadSeqs,
|
||||
&msg.GetHasReadSeqsReq{UserID: req.OwnerUserID, ConversationIDs: req.ConversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -219,23 +226,24 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
|
||||
}
|
||||
var msgs map[string]*sdkws.PullMsgs
|
||||
if len(conversationSeqs) > 0 {
|
||||
msgs, err = x.msgClient.GetSeqMessage(ctx, req.OwnerUserID, conversationSeqs)
|
||||
msgs, err = field(ctx, x.msg.GetSeqMessage,
|
||||
&msg.GetSeqMessageReq{UserID: req.OwnerUserID, Conversations: conversationSeqs}, (*msg.GetSeqMessageResp).GetMsgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
x.checkMessagesAndGetLastMessage(ctx, req.OwnerUserID, msgs)
|
||||
resp := make([]*jssdk.ConversationMsg, 0, len(conversations))
|
||||
for _, c := range conversations {
|
||||
var lastMsg *sdkws.MsgData
|
||||
if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
|
||||
resp = append(resp, &jssdk.ConversationMsg{
|
||||
Conversation: c,
|
||||
LastMsg: msgList.Msgs[0],
|
||||
MaxSeq: maxSeqs[c.ConversationID],
|
||||
ReadSeq: readSeqs[c.ConversationID],
|
||||
})
|
||||
lastMsg = msgList.Msgs[0]
|
||||
}
|
||||
|
||||
resp = append(resp, &jssdk.ConversationMsg{
|
||||
Conversation: c,
|
||||
LastMsg: lastMsg,
|
||||
MaxSeq: maxSeqs[c.ConversationID],
|
||||
ReadSeq: readSeqs[c.ConversationID],
|
||||
})
|
||||
}
|
||||
if err := x.fillConversations(ctx, resp); err != nil {
|
||||
return nil, err
|
||||
@@ -252,38 +260,3 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
|
||||
UnreadCount: unreadCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// This function checks whether the latest MaxSeq message is valid.
|
||||
// If not, it needs to fetch a valid message again.
|
||||
func (x *JSSdk) checkMessagesAndGetLastMessage(ctx context.Context, userID string, messages map[string]*sdkws.PullMsgs) {
|
||||
var conversationIDs []string
|
||||
|
||||
for conversationID, message := range messages {
|
||||
allInValid := true
|
||||
for _, data := range message.Msgs {
|
||||
if data.Status < constant.MsgStatusHasDeleted {
|
||||
allInValid = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// when the conversation has been deleted by the user, the length of message.Msgs is empty
|
||||
if allInValid && len(message.Msgs) > 0 {
|
||||
conversationIDs = append(conversationIDs, conversationID)
|
||||
}
|
||||
}
|
||||
if len(conversationIDs) > 0 {
|
||||
resp, err := x.msgClient.GetLastMessage(ctx, &msg.GetLastMessageReq{
|
||||
UserID: userID,
|
||||
ConversationIDs: conversationIDs,
|
||||
})
|
||||
if err != nil {
|
||||
log.ZError(ctx, "fetchLatestValidMessages", err, "conversationIDs", conversationIDs)
|
||||
return
|
||||
}
|
||||
for conversationID, message := range resp.Msgs {
|
||||
messages[conversationID] = &sdkws.PullMsgs{Msgs: []*sdkws.MsgData{message}}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-37
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/apistruct"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -37,14 +37,16 @@ import (
|
||||
)
|
||||
|
||||
type MessageApi struct {
|
||||
Client msg.MsgClient
|
||||
userClient *rpcli.UserClient
|
||||
imAdminUserID []string
|
||||
*rpcclient.Message
|
||||
validate *validator.Validate
|
||||
userRpcClient *rpcclient.UserRpcClient
|
||||
imAdminUserID []string
|
||||
}
|
||||
|
||||
func NewMessageApi(client msg.MsgClient, userClient *rpcli.UserClient, imAdminUserID []string) MessageApi {
|
||||
return MessageApi{Client: client, userClient: userClient, imAdminUserID: imAdminUserID, validate: validator.New()}
|
||||
func NewMessageApi(msgRpcClient *rpcclient.Message, userRpcClient *rpcclient.User,
|
||||
imAdminUserID []string) MessageApi {
|
||||
return MessageApi{Message: msgRpcClient, validate: validator.New(),
|
||||
userRpcClient: rpcclient.NewUserRpcClientByUser(userRpcClient), imAdminUserID: imAdminUserID}
|
||||
}
|
||||
|
||||
func (*MessageApi) SetOptions(options map[string]bool, value bool) {
|
||||
@@ -106,51 +108,51 @@ func (m *MessageApi) newUserSendMsgReq(_ *gin.Context, params *apistruct.SendMsg
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetSeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetMaxSeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetMaxSeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) PullMsgBySeqs(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.PullMessageBySeqs, m.Client)
|
||||
a2r.Call(msg.MsgClient.PullMessageBySeqs, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) RevokeMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.RevokeMsg, m.Client)
|
||||
a2r.Call(msg.MsgClient.RevokeMsg, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) MarkMsgsAsRead(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.MarkMsgsAsRead, m.Client)
|
||||
a2r.Call(msg.MsgClient.MarkMsgsAsRead, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) MarkConversationAsRead(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.MarkConversationAsRead, m.Client)
|
||||
a2r.Call(msg.MsgClient.MarkConversationAsRead, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetConversationsHasReadAndMaxSeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetConversationsHasReadAndMaxSeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetConversationsHasReadAndMaxSeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) SetConversationHasReadSeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.SetConversationHasReadSeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.SetConversationHasReadSeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) ClearConversationsMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.ClearConversationsMsg, m.Client)
|
||||
a2r.Call(msg.MsgClient.ClearConversationsMsg, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) UserClearAllMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.UserClearAllMsg, m.Client)
|
||||
a2r.Call(msg.MsgClient.UserClearAllMsg, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) DeleteMsgs(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.DeleteMsgs, m.Client)
|
||||
a2r.Call(msg.MsgClient.DeleteMsgs, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) DeleteMsgPhysicalBySeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.DeleteMsgPhysicalBySeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.DeleteMsgPhysicalBySeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) DeleteMsgPhysical(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.DeleteMsgPhysical, m.Client)
|
||||
a2r.Call(msg.MsgClient.DeleteMsgPhysical, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendMsgReq *msg.SendMsgReq, err error) {
|
||||
@@ -174,7 +176,7 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
|
||||
case constant.OANotification:
|
||||
data = apistruct.OANotificationElem{}
|
||||
req.SessionType = constant.NotificationChatType
|
||||
if err = m.userClient.GetNotificationByID(c, req.SendID); err != nil {
|
||||
if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
@@ -281,7 +283,7 @@ func (m *MessageApi) SendBusinessNotification(c *gin.Context) {
|
||||
IsSendMsg: false,
|
||||
ReliabilityLevel: 1,
|
||||
UnreadCount: false,
|
||||
}, nil),
|
||||
}),
|
||||
},
|
||||
}
|
||||
respPb, err := m.Client.SendMsg(c, &sendMsgReq)
|
||||
@@ -308,10 +310,10 @@ func (m *MessageApi) BatchSendMsg(c *gin.Context) {
|
||||
|
||||
var recvIDs []string
|
||||
if req.IsSendAll {
|
||||
var pageNumber int32 = 1
|
||||
const showNumber = 500
|
||||
pageNumber := 1
|
||||
showNumber := 500
|
||||
for {
|
||||
recvIDsPart, err := m.userClient.GetAllUserIDs(c, pageNumber, showNumber)
|
||||
recvIDsPart, err := m.userRpcClient.GetAllUserIDs(c, int32(pageNumber), int32(showNumber))
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
@@ -349,33 +351,25 @@ func (m *MessageApi) BatchSendMsg(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (m *MessageApi) CheckMsgIsSendSuccess(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetSendMsgStatus, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetSendMsgStatus, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetUsersOnlineStatus(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetSendMsgStatus, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetSendMsgStatus, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetActiveUser(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetActiveUser, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetActiveUser, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetActiveGroup(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetActiveGroup, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetActiveGroup, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) SearchMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.SearchMessage, m.Client)
|
||||
a2r.Call(msg.MsgClient.SearchMessage, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetServerTime(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetServerTime, m.Client)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetStreamMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetServerTime, m.Client)
|
||||
}
|
||||
|
||||
func (m *MessageApi) AppendStreamMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetServerTime, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetServerTime, m.Client, c)
|
||||
}
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/tools/apiresp"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/discovery/etcd"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
type PrometheusDiscoveryApi struct {
|
||||
config *Config
|
||||
client discovery.SvcDiscoveryRegistry
|
||||
}
|
||||
|
||||
func NewPrometheusDiscoveryApi(cfg *Config, client discovery.SvcDiscoveryRegistry) *PrometheusDiscoveryApi {
|
||||
api := &PrometheusDiscoveryApi{
|
||||
config: cfg,
|
||||
}
|
||||
if cfg.Discovery.Enable == config.ETCD {
|
||||
api.client = client.(*etcd.SvcDiscoveryRegistryImpl)
|
||||
}
|
||||
return api
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Enable(c *gin.Context) {
|
||||
if p.config.Discovery.Enable != config.ETCD {
|
||||
c.JSON(http.StatusOK, []struct{}{})
|
||||
c.Abort()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) discovery(c *gin.Context, key string) {
|
||||
value, err := p.client.GetKeyWithPrefix(c, prommetrics.BuildDiscoveryKeyPrefix(key))
|
||||
if err != nil {
|
||||
if errors.Is(err, discovery.ErrNotSupported) {
|
||||
c.JSON(http.StatusOK, []struct{}{})
|
||||
return
|
||||
}
|
||||
apiresp.GinError(c, errs.WrapMsg(err, "get key value"))
|
||||
return
|
||||
}
|
||||
if len(value) == 0 {
|
||||
c.JSON(http.StatusOK, []*prommetrics.RespTarget{})
|
||||
return
|
||||
}
|
||||
var resp prommetrics.RespTarget
|
||||
for i := range value {
|
||||
var tmp prommetrics.Target
|
||||
if err = json.Unmarshal(value[i], &tmp); err != nil {
|
||||
apiresp.GinError(c, errs.WrapMsg(err, "json unmarshal err"))
|
||||
return
|
||||
}
|
||||
|
||||
resp.Targets = append(resp.Targets, tmp.Target)
|
||||
resp.Labels = tmp.Labels // default label is fixed. See prommetrics.BuildDefaultTarget
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, []*prommetrics.RespTarget{&resp})
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Api(c *gin.Context) {
|
||||
p.discovery(c, prommetrics.APIKeyName)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) User(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.User)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Group(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.Group)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Msg(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.Msg)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Friend(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.Friend)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Conversation(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.Conversation)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Third(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.Third)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Auth(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.Auth)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) Push(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.Push)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) MessageGateway(c *gin.Context) {
|
||||
p.discovery(c, p.config.Share.RpcRegisterName.MessageGateway)
|
||||
}
|
||||
|
||||
func (p *PrometheusDiscoveryApi) MessageTransfer(c *gin.Context) {
|
||||
p.discovery(c, prommetrics.MessageTransferKeyName)
|
||||
}
|
||||
+43
-85
@@ -1,18 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
pbAuth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"fmt"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/internal/api/jssdk"
|
||||
|
||||
@@ -21,8 +10,15 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/tools/apiresp"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
@@ -52,40 +48,23 @@ func prommetricsGin() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, config *Config) (*gin.Engine, error) {
|
||||
authConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func newGinRouter(disCov discovery.SvcDiscoveryRegistry, config *Config) *gin.Engine {
|
||||
disCov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.New()
|
||||
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
||||
_ = v.RegisterValidation("required_if", RequiredIf)
|
||||
}
|
||||
// init rpc client here
|
||||
userRpc := rpcclient.NewUser(disCov, config.Share.RpcRegisterName.User, config.Share.RpcRegisterName.MessageGateway,
|
||||
config.Share.IMAdminUserID)
|
||||
groupRpc := rpcclient.NewGroup(disCov, config.Share.RpcRegisterName.Group)
|
||||
friendRpc := rpcclient.NewFriend(disCov, config.Share.RpcRegisterName.Friend)
|
||||
messageRpc := rpcclient.NewMessage(disCov, config.Share.RpcRegisterName.Msg)
|
||||
conversationRpc := rpcclient.NewConversation(disCov, config.Share.RpcRegisterName.Conversation)
|
||||
authRpc := rpcclient.NewAuth(disCov, config.Share.RpcRegisterName.Auth)
|
||||
thirdRpc := rpcclient.NewThird(disCov, config.Share.RpcRegisterName.Third, config.API.Prometheus.GrafanaURL)
|
||||
switch config.API.Api.CompressionLevel {
|
||||
case NoCompression:
|
||||
case DefaultCompression:
|
||||
@@ -95,9 +74,10 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
case BestSpeed:
|
||||
r.Use(gzip.Gzip(gzip.BestSpeed))
|
||||
}
|
||||
r.Use(prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(), mw.GinParseOperationID(), GinParseToken(rpcli.NewAuthClient(authConn)))
|
||||
u := NewUserApi(user.NewUserClient(userConn), client, config.Share.RpcRegisterName)
|
||||
m := NewMessageApi(msg.NewMsgClient(msgConn), rpcli.NewUserClient(userConn), config.Share.IMAdminUserID)
|
||||
r.Use(prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(), mw.GinParseOperationID(), GinParseToken(authRpc))
|
||||
u := NewUserApi(*userRpc)
|
||||
m := NewMessageApi(messageRpc, userRpc, config.Share.IMAdminUserID)
|
||||
j := jssdk.NewJSSdkApi(userRpc.Client, friendRpc.Client, groupRpc.Client, messageRpc.Client, conversationRpc.Client)
|
||||
userRouterGroup := r.Group("/user")
|
||||
{
|
||||
userRouterGroup.POST("/user_register", u.UserRegister)
|
||||
@@ -125,9 +105,9 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
userRouterGroup.POST("/search_notification_account", u.SearchNotificationAccount)
|
||||
}
|
||||
// friend routing group
|
||||
friendRouterGroup := r.Group("/friend")
|
||||
{
|
||||
f := NewFriendApi(relation.NewFriendClient(friendConn))
|
||||
friendRouterGroup := r.Group("/friend")
|
||||
f := NewFriendApi(*friendRpc)
|
||||
friendRouterGroup.POST("/delete_friend", f.DeleteFriend)
|
||||
friendRouterGroup.POST("/get_friend_apply_list", f.GetFriendApplyList)
|
||||
friendRouterGroup.POST("/get_designated_friend_apply", f.GetDesignatedFriendsApply)
|
||||
@@ -149,12 +129,10 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
friendRouterGroup.POST("/update_friends", f.UpdateFriends)
|
||||
friendRouterGroup.POST("/get_incremental_friends", f.GetIncrementalFriends)
|
||||
friendRouterGroup.POST("/get_full_friend_user_ids", f.GetFullFriendUserIDs)
|
||||
friendRouterGroup.POST("/get_self_unhandled_apply_count", f.GetSelfUnhandledApplyCount)
|
||||
}
|
||||
|
||||
g := NewGroupApi(group.NewGroupClient(groupConn))
|
||||
g := NewGroupApi(*groupRpc)
|
||||
groupRouterGroup := r.Group("/group")
|
||||
{
|
||||
groupRouterGroup := r.Group("/group")
|
||||
groupRouterGroup.POST("/create_group", g.CreateGroup)
|
||||
groupRouterGroup.POST("/set_group_info", g.SetGroupInfo)
|
||||
groupRouterGroup.POST("/set_group_info_ex", g.SetGroupInfoEx)
|
||||
@@ -186,22 +164,20 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
groupRouterGroup.POST("/get_incremental_group_members_batch", g.GetIncrementalGroupMemberBatch)
|
||||
groupRouterGroup.POST("/get_full_group_member_user_ids", g.GetFullGroupMemberUserIDs)
|
||||
groupRouterGroup.POST("/get_full_join_group_ids", g.GetFullJoinGroupIDs)
|
||||
groupRouterGroup.POST("/get_group_application_unhandled_count", g.GetGroupApplicationUnhandledCount)
|
||||
}
|
||||
// certificate
|
||||
authRouterGroup := r.Group("/auth")
|
||||
{
|
||||
a := NewAuthApi(pbAuth.NewAuthClient(authConn))
|
||||
authRouterGroup := r.Group("/auth")
|
||||
a := NewAuthApi(*authRpc)
|
||||
authRouterGroup.POST("/get_admin_token", a.GetAdminToken)
|
||||
authRouterGroup.POST("/get_user_token", a.GetUserToken)
|
||||
authRouterGroup.POST("/parse_token", a.ParseToken)
|
||||
authRouterGroup.POST("/force_logout", a.ForceLogout)
|
||||
|
||||
}
|
||||
// Third service
|
||||
thirdGroup := r.Group("/third")
|
||||
{
|
||||
t := NewThirdApi(third.NewThirdClient(thirdConn), config.API.Prometheus.GrafanaURL)
|
||||
thirdGroup := r.Group("/third")
|
||||
t := NewThirdApi(*thirdRpc)
|
||||
thirdGroup.GET("/prometheus", t.GetPrometheus)
|
||||
thirdGroup.POST("/fcm_update_token", t.FcmUpdateToken)
|
||||
thirdGroup.POST("/set_app_badge", t.SetAppBadge)
|
||||
@@ -224,8 +200,8 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
objectGroup.GET("/*name", t.ObjectRedirect)
|
||||
}
|
||||
// Message
|
||||
msgGroup := r.Group("/msg")
|
||||
{
|
||||
msgGroup := r.Group("/msg")
|
||||
msgGroup.POST("/newest_seq", m.GetSeq)
|
||||
msgGroup.POST("/search_msg", m.SearchMsg)
|
||||
msgGroup.POST("/send_msg", m.SendMessage)
|
||||
@@ -248,9 +224,9 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
msgGroup.POST("/get_server_time", m.GetServerTime)
|
||||
}
|
||||
// Conversation
|
||||
conversationGroup := r.Group("/conversation")
|
||||
{
|
||||
c := NewConversationApi(conversation.NewConversationClient(conversationConn))
|
||||
conversationGroup := r.Group("/conversation")
|
||||
c := NewConversationApi(*conversationRpc)
|
||||
conversationGroup.POST("/get_sorted_conversation_list", c.GetSortedConversationList)
|
||||
conversationGroup.POST("/get_all_conversations", c.GetAllConversations)
|
||||
conversationGroup.POST("/get_conversation", c.GetConversation)
|
||||
@@ -264,40 +240,22 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
conversationGroup.POST("/get_pinned_conversation_ids", c.GetPinnedConversationIDs)
|
||||
}
|
||||
|
||||
statisticsGroup := r.Group("/statistics")
|
||||
{
|
||||
statisticsGroup := r.Group("/statistics")
|
||||
statisticsGroup.POST("/user/register", u.UserRegisterCount)
|
||||
statisticsGroup.POST("/user/active", m.GetActiveUser)
|
||||
statisticsGroup.POST("/group/create", g.GroupCreateCount)
|
||||
statisticsGroup.POST("/group/active", m.GetActiveGroup)
|
||||
}
|
||||
|
||||
{
|
||||
j := jssdk.NewJSSdkApi(rpcli.NewUserClient(userConn), rpcli.NewRelationClient(friendConn),
|
||||
rpcli.NewGroupClient(groupConn), rpcli.NewConversationClient(conversationConn), rpcli.NewMsgClient(msgConn))
|
||||
jssdk := r.Group("/jssdk")
|
||||
jssdk.POST("/get_conversations", j.GetConversations)
|
||||
jssdk.POST("/get_active_conversations", j.GetActiveConversations)
|
||||
}
|
||||
{
|
||||
pd := NewPrometheusDiscoveryApi(config, client)
|
||||
proDiscoveryGroup := r.Group("/prometheus_discovery", pd.Enable)
|
||||
proDiscoveryGroup.GET("/api", pd.Api)
|
||||
proDiscoveryGroup.GET("/user", pd.User)
|
||||
proDiscoveryGroup.GET("/group", pd.Group)
|
||||
proDiscoveryGroup.GET("/msg", pd.Msg)
|
||||
proDiscoveryGroup.GET("/friend", pd.Friend)
|
||||
proDiscoveryGroup.GET("/conversation", pd.Conversation)
|
||||
proDiscoveryGroup.GET("/third", pd.Third)
|
||||
proDiscoveryGroup.GET("/auth", pd.Auth)
|
||||
proDiscoveryGroup.GET("/push", pd.Push)
|
||||
proDiscoveryGroup.GET("/msg_gateway", pd.MessageGateway)
|
||||
proDiscoveryGroup.GET("/msg_transfer", pd.MessageTransfer)
|
||||
}
|
||||
return r, nil
|
||||
jssdk := r.Group("/jssdk")
|
||||
jssdk.POST("/get_conversations", j.GetConversations)
|
||||
jssdk.POST("/get_active_conversations", j.GetActiveConversations)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func GinParseToken(authClient *rpcli.AuthClient) gin.HandlerFunc {
|
||||
func GinParseToken(authRPC *rpcclient.Auth) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
switch c.Request.Method {
|
||||
case http.MethodPost:
|
||||
@@ -315,7 +273,7 @@ func GinParseToken(authClient *rpcli.AuthClient) gin.HandlerFunc {
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
resp, err := authClient.ParseToken(c, token)
|
||||
resp, err := authRPC.ParseToken(c, token)
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
c.Abort()
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type StatisticsApi rpcclient.User
|
||||
|
||||
func NewStatisticsApi(client rpcclient.User) StatisticsApi {
|
||||
return StatisticsApi(client)
|
||||
}
|
||||
|
||||
func (s *StatisticsApi) UserRegister(c *gin.Context) {
|
||||
a2r.Call(user.UserClient.UserRegisterCount, s.Client, c)
|
||||
}
|
||||
+17
-19
@@ -24,27 +24,25 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
)
|
||||
|
||||
type ThirdApi struct {
|
||||
GrafanaUrl string
|
||||
Client third.ThirdClient
|
||||
}
|
||||
type ThirdApi rpcclient.Third
|
||||
|
||||
func NewThirdApi(client third.ThirdClient, grafanaUrl string) ThirdApi {
|
||||
return ThirdApi{Client: client, GrafanaUrl: grafanaUrl}
|
||||
func NewThirdApi(client rpcclient.Third) ThirdApi {
|
||||
return ThirdApi(client)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) FcmUpdateToken(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.FcmUpdateToken, o.Client)
|
||||
a2r.Call(third.ThirdClient.FcmUpdateToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) SetAppBadge(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.SetAppBadge, o.Client)
|
||||
a2r.Call(third.ThirdClient.SetAppBadge, o.Client, c)
|
||||
}
|
||||
|
||||
// #################### s3 ####################
|
||||
@@ -79,44 +77,44 @@ func setURLPrefix(c *gin.Context, urlPrefix *string) error {
|
||||
}
|
||||
|
||||
func (o *ThirdApi) PartLimit(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.PartLimit, o.Client)
|
||||
a2r.Call(third.ThirdClient.PartLimit, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) PartSize(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.PartSize, o.Client)
|
||||
a2r.Call(third.ThirdClient.PartSize, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) InitiateMultipartUpload(c *gin.Context) {
|
||||
opt := setURLPrefixOption(third.ThirdClient.InitiateMultipartUpload, func(req *third.InitiateMultipartUploadReq) error {
|
||||
return setURLPrefix(c, &req.UrlPrefix)
|
||||
})
|
||||
a2r.Call(c, third.ThirdClient.InitiateMultipartUpload, o.Client, opt)
|
||||
a2r.Call(third.ThirdClient.InitiateMultipartUpload, o.Client, c, opt)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) AuthSign(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.AuthSign, o.Client)
|
||||
a2r.Call(third.ThirdClient.AuthSign, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) CompleteMultipartUpload(c *gin.Context) {
|
||||
opt := setURLPrefixOption(third.ThirdClient.CompleteMultipartUpload, func(req *third.CompleteMultipartUploadReq) error {
|
||||
return setURLPrefix(c, &req.UrlPrefix)
|
||||
})
|
||||
a2r.Call(c, third.ThirdClient.CompleteMultipartUpload, o.Client, opt)
|
||||
a2r.Call(third.ThirdClient.CompleteMultipartUpload, o.Client, c, opt)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) AccessURL(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.AccessURL, o.Client)
|
||||
a2r.Call(third.ThirdClient.AccessURL, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) InitiateFormData(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.InitiateFormData, o.Client)
|
||||
a2r.Call(third.ThirdClient.InitiateFormData, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) CompleteFormData(c *gin.Context) {
|
||||
opt := setURLPrefixOption(third.ThirdClient.CompleteFormData, func(req *third.CompleteFormDataReq) error {
|
||||
return setURLPrefix(c, &req.UrlPrefix)
|
||||
})
|
||||
a2r.Call(c, third.ThirdClient.CompleteFormData, o.Client, opt)
|
||||
a2r.Call(third.ThirdClient.CompleteFormData, o.Client, c, opt)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
|
||||
@@ -158,15 +156,15 @@ func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
|
||||
|
||||
// #################### logs ####################.
|
||||
func (o *ThirdApi) UploadLogs(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.UploadLogs, o.Client)
|
||||
a2r.Call(third.ThirdClient.UploadLogs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) DeleteLogs(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.DeleteLogs, o.Client)
|
||||
a2r.Call(third.ThirdClient.DeleteLogs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) SearchLogs(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.SearchLogs, o.Client)
|
||||
a2r.Call(third.ThirdClient.SearchLogs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) GetPrometheus(c *gin.Context) {
|
||||
|
||||
+26
-31
@@ -16,57 +16,52 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
"github.com/openimsdk/tools/apiresp"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
type UserApi struct {
|
||||
Client user.UserClient
|
||||
discov discovery.SvcDiscoveryRegistry
|
||||
config config.RpcRegisterName
|
||||
}
|
||||
type UserApi rpcclient.User
|
||||
|
||||
func NewUserApi(client user.UserClient, discov discovery.SvcDiscoveryRegistry, config config.RpcRegisterName) UserApi {
|
||||
return UserApi{Client: client, discov: discov, config: config}
|
||||
func NewUserApi(client rpcclient.User) UserApi {
|
||||
return UserApi(client)
|
||||
}
|
||||
|
||||
func (u *UserApi) UserRegister(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UserRegister, u.Client)
|
||||
a2r.Call(user.UserClient.UserRegister, u.Client, c)
|
||||
}
|
||||
|
||||
// UpdateUserInfo is deprecated. Use UpdateUserInfoEx
|
||||
func (u *UserApi) UpdateUserInfo(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UpdateUserInfo, u.Client)
|
||||
a2r.Call(user.UserClient.UpdateUserInfo, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) UpdateUserInfoEx(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UpdateUserInfoEx, u.Client)
|
||||
a2r.Call(user.UserClient.UpdateUserInfoEx, u.Client, c)
|
||||
}
|
||||
func (u *UserApi) SetGlobalRecvMessageOpt(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.SetGlobalRecvMessageOpt, u.Client)
|
||||
a2r.Call(user.UserClient.SetGlobalRecvMessageOpt, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) GetUsersPublicInfo(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetDesignateUsers, u.Client)
|
||||
a2r.Call(user.UserClient.GetDesignateUsers, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) GetAllUsersID(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetAllUserID, u.Client)
|
||||
a2r.Call(user.UserClient.GetAllUserID, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) AccountCheck(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.AccountCheck, u.Client)
|
||||
a2r.Call(user.UserClient.AccountCheck, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) GetUsers(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetPaginationUsers, u.Client)
|
||||
a2r.Call(user.UserClient.GetPaginationUsers, u.Client, c)
|
||||
}
|
||||
|
||||
// GetUsersOnlineStatus Get user online status.
|
||||
@@ -76,7 +71,7 @@ func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
}
|
||||
conns, err := u.discov.GetConns(c, u.config.MessageGateway)
|
||||
conns, err := u.Discov.GetConns(c, u.MessageGateWayRpcName)
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
@@ -127,7 +122,7 @@ func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (u *UserApi) UserRegisterCount(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UserRegisterCount, u.Client)
|
||||
a2r.Call(user.UserClient.UserRegisterCount, u.Client, c)
|
||||
}
|
||||
|
||||
// GetUsersOnlineTokenDetail Get user online token details.
|
||||
@@ -140,7 +135,7 @@ func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) {
|
||||
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||
return
|
||||
}
|
||||
conns, err := u.discov.GetConns(c, u.config.MessageGateway)
|
||||
conns, err := u.Discov.GetConns(c, u.MessageGateWayRpcName)
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
@@ -193,52 +188,52 @@ func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) {
|
||||
|
||||
// SubscriberStatus Presence status of subscribed users.
|
||||
func (u *UserApi) SubscriberStatus(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.SubscribeOrCancelUsersStatus, u.Client)
|
||||
a2r.Call(user.UserClient.SubscribeOrCancelUsersStatus, u.Client, c)
|
||||
}
|
||||
|
||||
// GetUserStatus Get the online status of the user.
|
||||
func (u *UserApi) GetUserStatus(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetUserStatus, u.Client)
|
||||
a2r.Call(user.UserClient.GetUserStatus, u.Client, c)
|
||||
}
|
||||
|
||||
// GetSubscribeUsersStatus Get the online status of subscribers.
|
||||
func (u *UserApi) GetSubscribeUsersStatus(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetSubscribeUsersStatus, u.Client)
|
||||
a2r.Call(user.UserClient.GetSubscribeUsersStatus, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandAdd user general function add.
|
||||
func (u *UserApi) ProcessUserCommandAdd(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandAdd, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandAdd, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandDelete user general function delete.
|
||||
func (u *UserApi) ProcessUserCommandDelete(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandDelete, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandDelete, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandUpdate user general function update.
|
||||
func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandUpdate, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandUpdate, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandGet user general function get.
|
||||
func (u *UserApi) ProcessUserCommandGet(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandGet, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandGet user general function get all.
|
||||
func (u *UserApi) ProcessUserCommandGetAll(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandGetAll, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandGetAll, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) AddNotificationAccount(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.AddNotificationAccount, u.Client)
|
||||
a2r.Call(user.UserClient.AddNotificationAccount, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) UpdateNotificationAccountInfo(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UpdateNotificationAccountInfo, u.Client)
|
||||
a2r.Call(user.UserClient.UpdateNotificationAccountInfo, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) SearchNotificationAccount(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.SearchNotificationAccount, u.Client)
|
||||
a2r.Call(user.UserClient.SearchNotificationAccount, u.Client, c)
|
||||
}
|
||||
|
||||
+153
-13
@@ -16,7 +16,9 @@ package msggateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -30,6 +32,7 @@ import (
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -62,7 +65,7 @@ type PingPongHandler func(string) error
|
||||
|
||||
type Client struct {
|
||||
w *sync.Mutex
|
||||
conn ClientConn
|
||||
conn LongConn
|
||||
PlatformID int `json:"platformID"`
|
||||
IsCompress bool `json:"isCompress"`
|
||||
UserID string `json:"userID"`
|
||||
@@ -81,10 +84,10 @@ type Client struct {
|
||||
}
|
||||
|
||||
// ResetClient updates the client's state with new connection and context information.
|
||||
func (c *Client) ResetClient(ctx *UserConnContext, conn ClientConn, longConnServer LongConnServer) {
|
||||
func (c *Client) ResetClient(ctx *UserConnContext, conn LongConn, longConnServer LongConnServer) {
|
||||
c.w = new(sync.Mutex)
|
||||
c.conn = conn
|
||||
c.PlatformID = ctx.GetPlatformID()
|
||||
c.PlatformID = stringutil.StringToInt(ctx.GetPlatformID())
|
||||
c.IsCompress = ctx.GetCompression()
|
||||
c.IsBackground = ctx.GetBackground()
|
||||
c.UserID = ctx.GetUserID()
|
||||
@@ -108,35 +111,78 @@ func (c *Client) ResetClient(ctx *UserConnContext, conn ClientConn, longConnServ
|
||||
c.subUserIDs = make(map[string]struct{})
|
||||
}
|
||||
|
||||
func (c *Client) pingHandler(appData string) error {
|
||||
if err := c.conn.SetReadDeadline(pongWait); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.ZDebug(c.ctx, "ping Handler Success.", "appData", appData)
|
||||
return c.writePongMsg(appData)
|
||||
}
|
||||
|
||||
func (c *Client) pongHandler(_ string) error {
|
||||
if err := c.conn.SetReadDeadline(pongWait); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readMessage continuously reads messages from the connection.
|
||||
func (c *Client) readMessage() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
c.closedErr = ErrPanic
|
||||
log.ZPanic(c.ctx, "socket have panic err:", errs.ErrPanic(r))
|
||||
fmt.Println("socket have panic err:", r, string(debug.Stack()))
|
||||
}
|
||||
c.close()
|
||||
}()
|
||||
|
||||
c.conn.SetReadLimit(maxMessageSize)
|
||||
_ = c.conn.SetReadDeadline(pongWait)
|
||||
c.conn.SetPongHandler(c.pongHandler)
|
||||
c.conn.SetPingHandler(c.pingHandler)
|
||||
c.activeHeartbeat(c.hbCtx)
|
||||
|
||||
for {
|
||||
log.ZDebug(c.ctx, "readMessage")
|
||||
message, returnErr := c.conn.ReadMessage()
|
||||
messageType, message, returnErr := c.conn.ReadMessage()
|
||||
if returnErr != nil {
|
||||
log.ZWarn(c.ctx, "readMessage", returnErr)
|
||||
log.ZWarn(c.ctx, "readMessage", returnErr, "messageType", messageType)
|
||||
c.closedErr = returnErr
|
||||
return
|
||||
}
|
||||
|
||||
log.ZDebug(c.ctx, "readMessage", "messageType", messageType)
|
||||
if c.closed.Load() {
|
||||
// The scenario where the connection has just been closed, but the coroutine has not exited
|
||||
c.closedErr = ErrConnClosed
|
||||
return
|
||||
}
|
||||
|
||||
parseDataErr := c.handleMessage(message)
|
||||
if parseDataErr != nil {
|
||||
c.closedErr = parseDataErr
|
||||
switch messageType {
|
||||
case MessageBinary:
|
||||
_ = c.conn.SetReadDeadline(pongWait)
|
||||
parseDataErr := c.handleMessage(message)
|
||||
if parseDataErr != nil {
|
||||
c.closedErr = parseDataErr
|
||||
return
|
||||
}
|
||||
case MessageText:
|
||||
_ = c.conn.SetReadDeadline(pongWait)
|
||||
parseDataErr := c.handlerTextMessage(message)
|
||||
if parseDataErr != nil {
|
||||
c.closedErr = parseDataErr
|
||||
return
|
||||
}
|
||||
case PingMessage:
|
||||
err := c.writePongMsg("")
|
||||
log.ZError(c.ctx, "writePongMsg", err)
|
||||
|
||||
case CloseMessage:
|
||||
c.closedErr = ErrClientClosed
|
||||
return
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,8 +237,6 @@ func (c *Client) handleMessage(message []byte) error {
|
||||
resp, messageErr = c.longConnServer.GetSeqMessage(ctx, binaryReq)
|
||||
case WSGetConvMaxReadSeq:
|
||||
resp, messageErr = c.longConnServer.GetConversationsHasReadAndMaxSeq(ctx, binaryReq)
|
||||
case WsPullConvLastMessage:
|
||||
resp, messageErr = c.longConnServer.GetLastMessage(ctx, binaryReq)
|
||||
case WsLogoutMsg:
|
||||
resp, messageErr = c.longConnServer.UserLogout(ctx, binaryReq)
|
||||
case WsSetBackgroundStatus:
|
||||
@@ -311,13 +355,109 @@ func (c *Client) writeBinaryMsg(resp Resp) error {
|
||||
c.w.Lock()
|
||||
defer c.w.Unlock()
|
||||
|
||||
err = c.conn.SetWriteDeadline(writeWait)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IsCompress {
|
||||
resultBuf, compressErr := c.longConnServer.CompressWithPool(encodedBuf)
|
||||
if compressErr != nil {
|
||||
return compressErr
|
||||
}
|
||||
return c.conn.WriteMessage(resultBuf)
|
||||
return c.conn.WriteMessage(MessageBinary, resultBuf)
|
||||
}
|
||||
|
||||
return c.conn.WriteMessage(encodedBuf)
|
||||
return c.conn.WriteMessage(MessageBinary, encodedBuf)
|
||||
}
|
||||
|
||||
// Actively initiate Heartbeat when platform in Web.
|
||||
func (c *Client) activeHeartbeat(ctx context.Context) {
|
||||
if c.PlatformID == constant.WebPlatformID {
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.ZPanic(ctx, "activeHeartbeat Panic", r)
|
||||
}
|
||||
}()
|
||||
log.ZDebug(ctx, "server initiative send heartbeat start.")
|
||||
ticker := time.NewTicker(pingPeriod)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if err := c.writePingMsg(); err != nil {
|
||||
log.ZWarn(c.ctx, "send Ping Message error.", err)
|
||||
return
|
||||
}
|
||||
case <-c.hbCtx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
func (c *Client) writePingMsg() error {
|
||||
if c.closed.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.w.Lock()
|
||||
defer c.w.Unlock()
|
||||
|
||||
err := c.conn.SetWriteDeadline(writeWait)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.conn.WriteMessage(PingMessage, nil)
|
||||
}
|
||||
|
||||
func (c *Client) writePongMsg(appData string) error {
|
||||
log.ZDebug(c.ctx, "write Pong Msg in Server", "appData", appData)
|
||||
if c.closed.Load() {
|
||||
log.ZWarn(c.ctx, "is closed in server", nil, "appdata", appData, "closed err", c.closedErr)
|
||||
return nil
|
||||
}
|
||||
|
||||
c.w.Lock()
|
||||
defer c.w.Unlock()
|
||||
|
||||
err := c.conn.SetWriteDeadline(writeWait)
|
||||
if err != nil {
|
||||
log.ZWarn(c.ctx, "SetWriteDeadline in Server have error", errs.Wrap(err), "writeWait", writeWait, "appData", appData)
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
err = c.conn.WriteMessage(PongMessage, []byte(appData))
|
||||
if err != nil {
|
||||
log.ZWarn(c.ctx, "Write Message have error", errs.Wrap(err), "Pong msg", PongMessage)
|
||||
}
|
||||
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (c *Client) handlerTextMessage(b []byte) error {
|
||||
var msg TextMessage
|
||||
if err := json.Unmarshal(b, &msg); err != nil {
|
||||
return err
|
||||
}
|
||||
switch msg.Type {
|
||||
case TextPong:
|
||||
return nil
|
||||
case TextPing:
|
||||
msg.Type = TextPong
|
||||
msgData, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.w.Lock()
|
||||
defer c.w.Unlock()
|
||||
if err := c.conn.SetWriteDeadline(writeWait); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.conn.WriteMessage(MessageText, msgData)
|
||||
default:
|
||||
return fmt.Errorf("not support message type %s", msg.Type)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
package msggateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
var ErrWriteFull = fmt.Errorf("websocket write buffer full,close connection")
|
||||
|
||||
type ClientConn interface {
|
||||
ReadMessage() ([]byte, error)
|
||||
WriteMessage(message []byte) error
|
||||
Close() error
|
||||
}
|
||||
|
||||
type websocketMessage struct {
|
||||
MessageType int
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func NewWebSocketClientConn(conn *websocket.Conn, readLimit int64, readTimeout time.Duration, pingInterval time.Duration) ClientConn {
|
||||
c := &websocketClientConn{
|
||||
readTimeout: readTimeout,
|
||||
conn: conn,
|
||||
writer: make(chan *websocketMessage, 256),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
if readLimit > 0 {
|
||||
c.conn.SetReadLimit(readLimit)
|
||||
}
|
||||
c.conn.SetPingHandler(c.pingHandler)
|
||||
c.conn.SetPongHandler(c.pongHandler)
|
||||
|
||||
go c.loopSend()
|
||||
if pingInterval > 0 {
|
||||
go c.doPing(pingInterval)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type websocketClientConn struct {
|
||||
readTimeout time.Duration
|
||||
conn *websocket.Conn
|
||||
writer chan *websocketMessage
|
||||
done chan struct{}
|
||||
err atomic.Pointer[error]
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) ReadMessage() ([]byte, error) {
|
||||
buf, err := c.readMessage()
|
||||
if err != nil {
|
||||
return nil, c.closeBy(fmt.Errorf("read message %w", err))
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) WriteMessage(message []byte) error {
|
||||
return c.writeMessage(websocket.BinaryMessage, message)
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) Close() error {
|
||||
_ = c.closeBy(fmt.Errorf("websocket connection closed"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) closeBy(err error) error {
|
||||
if !c.err.CompareAndSwap(nil, &err) {
|
||||
return *c.err.Load()
|
||||
}
|
||||
close(c.done)
|
||||
log.ZWarn(context.Background(), "websocket connection closed", err, "remoteAddr", c.conn.RemoteAddr(),
|
||||
"chan length", len(c.writer))
|
||||
_ = c.conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) writeMessage(messageType int, data []byte) error {
|
||||
if errPtr := c.err.Load(); errPtr != nil {
|
||||
return *errPtr
|
||||
}
|
||||
select {
|
||||
case c.writer <- &websocketMessage{MessageType: messageType, Data: data}:
|
||||
return nil
|
||||
default:
|
||||
return c.closeBy(ErrWriteFull)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) loopSend() {
|
||||
var err error
|
||||
for {
|
||||
select {
|
||||
case <-c.done:
|
||||
return
|
||||
case msg := <-c.writer:
|
||||
switch msg.MessageType {
|
||||
case websocket.TextMessage, websocket.BinaryMessage:
|
||||
err = c.conn.WriteMessage(msg.MessageType, msg.Data)
|
||||
default:
|
||||
err = c.conn.WriteControl(msg.MessageType, msg.Data, time.Time{})
|
||||
}
|
||||
if err != nil {
|
||||
_ = c.closeBy(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) setReadDeadline() error {
|
||||
deadline := time.Now().Add(c.readTimeout)
|
||||
return c.conn.SetReadDeadline(deadline)
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) readMessage() ([]byte, error) {
|
||||
for {
|
||||
if err := c.setReadDeadline(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messageType, buf, err := c.conn.ReadMessage()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch messageType {
|
||||
case websocket.BinaryMessage:
|
||||
return buf, nil
|
||||
case websocket.TextMessage:
|
||||
if err := c.onReadTextMessage(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case websocket.PingMessage:
|
||||
if err := c.pingHandler(string(buf)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case websocket.PongMessage:
|
||||
if err := c.pongHandler(string(buf)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case websocket.CloseMessage:
|
||||
if len(buf) == 0 {
|
||||
return nil, errors.New("websocket connection closed by peer")
|
||||
}
|
||||
return nil, fmt.Errorf("websocket connection closed by peer, data %s", string(buf))
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown websocket message type %d", messageType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) onReadTextMessage(buf []byte) error {
|
||||
var msg struct {
|
||||
Type string `json:"type"`
|
||||
Body json.RawMessage `json:"body"`
|
||||
}
|
||||
if err := json.Unmarshal(buf, &msg); err != nil {
|
||||
return err
|
||||
}
|
||||
switch msg.Type {
|
||||
case TextPong:
|
||||
return nil
|
||||
case TextPing:
|
||||
msg.Type = TextPong
|
||||
msgData, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.writeMessage(websocket.TextMessage, msgData)
|
||||
default:
|
||||
return fmt.Errorf("not support text message type %s", msg.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) pingHandler(appData string) error {
|
||||
log.ZWarn(context.Background(), "ping handler recv ping", nil, "remoteAddr", c.conn.RemoteAddr(), "appData", appData)
|
||||
if err := c.setReadDeadline(); err != nil {
|
||||
return err
|
||||
}
|
||||
err := c.conn.WriteControl(websocket.PongMessage, []byte(appData), time.Now().Add(time.Second*1))
|
||||
if err != nil {
|
||||
log.ZWarn(context.Background(), "ping handler write pong error", err, "remoteAddr", c.conn.RemoteAddr(), "appData", appData)
|
||||
}
|
||||
log.ZWarn(context.Background(), "ping handler write pong success", nil, "remoteAddr", c.conn.RemoteAddr(), "appData", appData)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) pongHandler(string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *websocketClientConn) doPing(d time.Duration) {
|
||||
ticker := time.NewTicker(d)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-c.done:
|
||||
return
|
||||
case <-ticker.C:
|
||||
if err := c.writeMessage(websocket.PingMessage, nil); err != nil {
|
||||
_ = c.closeBy(fmt.Errorf("send ping %w", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,6 @@ const (
|
||||
WSSendSignalMsg = 1004
|
||||
WSPullMsg = 1005
|
||||
WSGetConvMaxReadSeq = 1006
|
||||
WsPullConvLastMessage = 1007
|
||||
WSPushMsg = 2001
|
||||
WSKickOnlineMsg = 2002
|
||||
WsLogoutMsg = 2003
|
||||
|
||||
+82
-133
@@ -15,31 +15,18 @@
|
||||
package msggateway
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/tools/utils/encrypt"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"github.com/openimsdk/tools/utils/timeutil"
|
||||
)
|
||||
|
||||
type UserConnContextInfo struct {
|
||||
Token string `json:"token"`
|
||||
UserID string `json:"userID"`
|
||||
PlatformID int `json:"platformID"`
|
||||
OperationID string `json:"operationID"`
|
||||
Compression string `json:"compression"`
|
||||
SDKType string `json:"sdkType"`
|
||||
SendResponse bool `json:"sendResponse"`
|
||||
Background bool `json:"background"`
|
||||
}
|
||||
|
||||
type UserConnContext struct {
|
||||
RespWriter http.ResponseWriter
|
||||
Req *http.Request
|
||||
@@ -47,7 +34,6 @@ type UserConnContext struct {
|
||||
Method string
|
||||
RemoteAddr string
|
||||
ConnID string
|
||||
info *UserConnContextInfo
|
||||
}
|
||||
|
||||
func (c *UserConnContext) Deadline() (deadline time.Time, ok bool) {
|
||||
@@ -71,7 +57,7 @@ func (c *UserConnContext) Value(key any) any {
|
||||
case constant.ConnID:
|
||||
return c.GetConnID()
|
||||
case constant.OpUserPlatform:
|
||||
return c.GetPlatformID()
|
||||
return constant.PlatformIDToName(stringutil.StringToInt(c.GetPlatformID()))
|
||||
case constant.RemoteAddr:
|
||||
return c.RemoteAddr
|
||||
default:
|
||||
@@ -96,91 +82,30 @@ func newContext(respWriter http.ResponseWriter, req *http.Request) *UserConnCont
|
||||
|
||||
func newTempContext() *UserConnContext {
|
||||
return &UserConnContext{
|
||||
Req: &http.Request{URL: &url.URL{}},
|
||||
info: &UserConnContextInfo{},
|
||||
Req: &http.Request{URL: &url.URL{}},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *UserConnContext) ParseEssentialArgs() error {
|
||||
query := c.Req.URL.Query()
|
||||
if data := query.Get("v"); data != "" {
|
||||
return c.parseByJson(data)
|
||||
} else {
|
||||
return c.parseByQuery(query, c.Req.Header)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *UserConnContext) parseByQuery(query url.Values, header http.Header) error {
|
||||
info := UserConnContextInfo{
|
||||
Token: query.Get(Token),
|
||||
UserID: query.Get(WsUserID),
|
||||
OperationID: query.Get(OperationID),
|
||||
Compression: query.Get(Compression),
|
||||
SDKType: query.Get(SDKType),
|
||||
}
|
||||
platformID, err := strconv.Atoi(query.Get(PlatformID))
|
||||
if err != nil {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("platformID is not int")
|
||||
}
|
||||
info.PlatformID = platformID
|
||||
if val := query.Get(SendResponse); val != "" {
|
||||
ok, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("isMsgResp is not bool")
|
||||
}
|
||||
info.SendResponse = ok
|
||||
}
|
||||
if info.Compression == "" {
|
||||
info.Compression = header.Get(Compression)
|
||||
}
|
||||
background, err := strconv.ParseBool(query.Get(BackgroundStatus))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info.Background = background
|
||||
return c.checkInfo(&info)
|
||||
}
|
||||
|
||||
func (c *UserConnContext) parseByJson(data string) error {
|
||||
reqInfo, err := base64.RawURLEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("data is not base64")
|
||||
}
|
||||
var info UserConnContextInfo
|
||||
if err := json.Unmarshal(reqInfo, &info); err != nil {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("data is not json", "info", err.Error())
|
||||
}
|
||||
return c.checkInfo(&info)
|
||||
}
|
||||
|
||||
func (c *UserConnContext) checkInfo(info *UserConnContextInfo) error {
|
||||
if info.OperationID == "" {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("operationID is empty")
|
||||
}
|
||||
if info.Token == "" {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("token is empty")
|
||||
}
|
||||
if info.UserID == "" {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("sendID is empty")
|
||||
}
|
||||
if _, ok := constant.PlatformID2Name[info.PlatformID]; !ok {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("platformID is invalid")
|
||||
}
|
||||
switch info.SDKType {
|
||||
case "":
|
||||
info.SDKType = GoSDK
|
||||
case GoSDK, JsSDK:
|
||||
default:
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("sdkType is invalid")
|
||||
}
|
||||
c.info = info
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetRemoteAddr() string {
|
||||
return c.RemoteAddr
|
||||
}
|
||||
|
||||
func (c *UserConnContext) Query(key string) (string, bool) {
|
||||
var value string
|
||||
if value = c.Req.URL.Query().Get(key); value == "" {
|
||||
return value, false
|
||||
}
|
||||
return value, true
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetHeader(key string) (string, bool) {
|
||||
var value string
|
||||
if value = c.Req.Header.Get(key); value == "" {
|
||||
return value, false
|
||||
}
|
||||
return value, true
|
||||
}
|
||||
|
||||
func (c *UserConnContext) SetHeader(key, value string) {
|
||||
c.RespWriter.Header().Set(key, value)
|
||||
}
|
||||
@@ -194,69 +119,93 @@ func (c *UserConnContext) GetConnID() string {
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetUserID() string {
|
||||
if c == nil || c.info == nil {
|
||||
return ""
|
||||
}
|
||||
return c.info.UserID
|
||||
return c.Req.URL.Query().Get(WsUserID)
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetPlatformID() int {
|
||||
if c == nil || c.info == nil {
|
||||
return 0
|
||||
}
|
||||
return c.info.PlatformID
|
||||
func (c *UserConnContext) GetPlatformID() string {
|
||||
return c.Req.URL.Query().Get(PlatformID)
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetOperationID() string {
|
||||
if c == nil || c.info == nil {
|
||||
return ""
|
||||
}
|
||||
return c.info.OperationID
|
||||
return c.Req.URL.Query().Get(OperationID)
|
||||
}
|
||||
|
||||
func (c *UserConnContext) SetOperationID(operationID string) {
|
||||
if c.info == nil {
|
||||
c.info = &UserConnContextInfo{}
|
||||
}
|
||||
c.info.OperationID = operationID
|
||||
values := c.Req.URL.Query()
|
||||
values.Set(OperationID, operationID)
|
||||
c.Req.URL.RawQuery = values.Encode()
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetToken() string {
|
||||
if c == nil || c.info == nil {
|
||||
return ""
|
||||
}
|
||||
return c.info.Token
|
||||
return c.Req.URL.Query().Get(Token)
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetCompression() bool {
|
||||
return c != nil && c.info != nil && c.info.Compression == GzipCompressionProtocol
|
||||
compression, exists := c.Query(Compression)
|
||||
if exists && compression == GzipCompressionProtocol {
|
||||
return true
|
||||
} else {
|
||||
compression, exists := c.GetHeader(Compression)
|
||||
if exists && compression == GzipCompressionProtocol {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetSDKType() string {
|
||||
if c == nil || c.info == nil {
|
||||
return GoSDK
|
||||
}
|
||||
switch c.info.SDKType {
|
||||
case "", GoSDK:
|
||||
return GoSDK
|
||||
case JsSDK:
|
||||
return JsSDK
|
||||
default:
|
||||
return ""
|
||||
sdkType := c.Req.URL.Query().Get(SDKType)
|
||||
if sdkType == "" {
|
||||
sdkType = GoSDK
|
||||
}
|
||||
return sdkType
|
||||
}
|
||||
|
||||
func (c *UserConnContext) ShouldSendResp() bool {
|
||||
return c != nil && c.info != nil && c.info.SendResponse
|
||||
errResp, exists := c.Query(SendResponse)
|
||||
if exists {
|
||||
b, err := strconv.ParseBool(errResp)
|
||||
if err != nil {
|
||||
return false
|
||||
} else {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *UserConnContext) SetToken(token string) {
|
||||
if c.info == nil {
|
||||
c.info = &UserConnContextInfo{}
|
||||
}
|
||||
c.info.Token = token
|
||||
c.Req.URL.RawQuery = Token + "=" + token
|
||||
}
|
||||
|
||||
func (c *UserConnContext) GetBackground() bool {
|
||||
return c != nil && c.info != nil && c.info.Background
|
||||
b, err := strconv.ParseBool(c.Req.URL.Query().Get(BackgroundStatus))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return b
|
||||
}
|
||||
func (c *UserConnContext) ParseEssentialArgs() error {
|
||||
_, exists := c.Query(Token)
|
||||
if !exists {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("token is empty")
|
||||
}
|
||||
_, exists = c.Query(WsUserID)
|
||||
if !exists {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("sendID is empty")
|
||||
}
|
||||
platformIDStr, exists := c.Query(PlatformID)
|
||||
if !exists {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("platformID is empty")
|
||||
}
|
||||
_, err := strconv.Atoi(platformIDStr)
|
||||
if err != nil {
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("platformID is not int")
|
||||
}
|
||||
switch sdkType, _ := c.Query(SDKType); sdkType {
|
||||
case "", GoSDK, JsSDK:
|
||||
default:
|
||||
return servererrs.ErrConnArgsErr.WrapMsg("sdkType is not go or js")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,11 +18,10 @@ import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -36,15 +35,9 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) InitServer(ctx context.Context, config *Config, disCov discovery.SvcDiscoveryRegistry, server *grpc.Server) error {
|
||||
userConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.userClient = rpcli.NewUserClient(userConn)
|
||||
if err := s.LongConnServer.SetDiscoveryRegistry(ctx, disCov, config); err != nil {
|
||||
return err
|
||||
}
|
||||
s.LongConnServer.SetDiscoveryRegistry(disCov, config)
|
||||
msggateway.RegisterMsgGatewayServer(server, s)
|
||||
s.userRcp = rpcclient.NewUserRpcClient(disCov, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
if s.ready != nil {
|
||||
return s.ready(s)
|
||||
}
|
||||
@@ -54,14 +47,10 @@ func (s *Server) InitServer(ctx context.Context, config *Config, disCov discover
|
||||
func (s *Server) Start(ctx context.Context, index int, conf *Config) error {
|
||||
return startrpc.Start(ctx, &conf.Discovery, &conf.MsgGateway.Prometheus, conf.MsgGateway.ListenIP,
|
||||
conf.MsgGateway.RPC.RegisterIP,
|
||||
conf.MsgGateway.RPC.AutoSetPorts,
|
||||
conf.MsgGateway.RPC.Ports, index,
|
||||
conf.Share.RpcRegisterName.MessageGateway,
|
||||
&conf.Share,
|
||||
conf,
|
||||
[]string{
|
||||
conf.Share.RpcRegisterName.MessageGateway,
|
||||
},
|
||||
s.InitServer,
|
||||
)
|
||||
}
|
||||
@@ -73,16 +62,17 @@ type Server struct {
|
||||
config *Config
|
||||
pushTerminal map[int]struct{}
|
||||
ready func(srv *Server) error
|
||||
userRcp rpcclient.UserRpcClient
|
||||
queue *memamq.MemoryQueue
|
||||
userClient *rpcli.UserClient
|
||||
}
|
||||
|
||||
func (s *Server) SetLongConnServer(LongConnServer LongConnServer) {
|
||||
s.LongConnServer = LongConnServer
|
||||
}
|
||||
|
||||
func NewServer(longConnServer LongConnServer, conf *Config, ready func(srv *Server) error) *Server {
|
||||
func NewServer(rpcPort int, longConnServer LongConnServer, conf *Config, ready func(srv *Server) error) *Server {
|
||||
s := &Server{
|
||||
rpcPort: rpcPort,
|
||||
LongConnServer: longConnServer,
|
||||
pushTerminal: make(map[int]struct{}),
|
||||
config: conf,
|
||||
@@ -94,6 +84,10 @@ func NewServer(longConnServer LongConnServer, conf *Config, ready func(srv *Serv
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Server) OnlinePushMsg(context context.Context, req *msggateway.OnlinePushMsgReq) (*msggateway.OnlinePushMsgResp, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *Server) GetUsersOnlineStatus(ctx context.Context, req *msggateway.GetUsersOnlineStatusReq) (*msggateway.GetUsersOnlineStatusResp, error) {
|
||||
if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("only app manager")
|
||||
@@ -127,6 +121,11 @@ func (s *Server) GetUsersOnlineStatus(ctx context.Context, req *msggateway.GetUs
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (s *Server) OnlineBatchPushOneMsg(ctx context.Context, req *msggateway.OnlineBatchPushOneMsgReq) (*msggateway.OnlineBatchPushOneMsgResp, error) {
|
||||
// todo implement
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *Server) pushToUser(ctx context.Context, userID string, msgData *sdkws.MsgData) *msggateway.SingleMsgToUserResults {
|
||||
clients, ok := s.LongConnServer.GetUserAllCons(userID)
|
||||
if !ok {
|
||||
@@ -244,7 +243,6 @@ func (s *Server) MultiTerminalLoginCheck(ctx context.Context, req *msggateway.Mu
|
||||
tempUserCtx.SetOperationID(mcontext.GetOperationID(ctx))
|
||||
client := &Client{}
|
||||
client.ctx = tempUserCtx
|
||||
client.token = req.Token
|
||||
client.UserID = req.UserID
|
||||
client.PlatformID = int(req.PlatformID)
|
||||
i := &kickHandler{
|
||||
|
||||
@@ -16,13 +16,13 @@ package msggateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -35,13 +35,16 @@ type Config struct {
|
||||
|
||||
// Start run ws server.
|
||||
func Start(ctx context.Context, index int, conf *Config) error {
|
||||
log.CInfo(ctx, "MSG-GATEWAY server is initializing", "autoSetPorts", conf.MsgGateway.RPC.AutoSetPorts,
|
||||
"rpcPorts", conf.MsgGateway.RPC.Ports,
|
||||
log.CInfo(ctx, "MSG-GATEWAY server is initializing", "rpcPorts", conf.MsgGateway.RPC.Ports,
|
||||
"wsPort", conf.MsgGateway.LongConnSvr.Ports, "prometheusPorts", conf.MsgGateway.Prometheus.Ports)
|
||||
wsPort, err := datautil.GetElemByIndex(conf.MsgGateway.LongConnSvr.Ports, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rpcPort, err := datautil.GetElemByIndex(conf.MsgGateway.RPC.Ports, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rdb, err := redisutil.NewRedisClient(ctx, conf.RedisConfig.Build())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -54,10 +57,9 @@ func Start(ctx context.Context, index int, conf *Config) error {
|
||||
WithMessageMaxMsgLength(conf.MsgGateway.LongConnSvr.WebsocketMaxMsgLen),
|
||||
)
|
||||
|
||||
hubServer := NewServer(longServer, conf, func(srv *Server) error {
|
||||
var err error
|
||||
longServer.online, err = rpccache.NewOnlineCache(srv.userClient, nil, rdb, false, longServer.subscriberUserOnlineStatusChanges)
|
||||
return err
|
||||
hubServer := NewServer(rpcPort, longServer, conf, func(srv *Server) error {
|
||||
longServer.online, _ = rpccache.NewOnlineCache(srv.userRcp, nil, rdb, false, longServer.subscriberUserOnlineStatusChanges)
|
||||
return nil
|
||||
})
|
||||
|
||||
go longServer.ChangeOnlineStatus(4)
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
// 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.
|
||||
|
||||
package msggateway
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/apiresp"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
type LongConn interface {
|
||||
// Close this connection
|
||||
Close() error
|
||||
// WriteMessage Write message to connection,messageType means data type,can be set binary(2) and text(1).
|
||||
WriteMessage(messageType int, message []byte) error
|
||||
// ReadMessage Read message from connection.
|
||||
ReadMessage() (int, []byte, error)
|
||||
// SetReadDeadline sets the read deadline on the underlying network connection,
|
||||
// after a read has timed out, will return an error.
|
||||
SetReadDeadline(timeout time.Duration) error
|
||||
// SetWriteDeadline sets to write deadline when send message,when read has timed out,will return error.
|
||||
SetWriteDeadline(timeout time.Duration) error
|
||||
// Dial Try to dial a connection,url must set auth args,header can control compress data
|
||||
Dial(urlStr string, requestHeader http.Header) (*http.Response, error)
|
||||
// IsNil Whether the connection of the current long connection is nil
|
||||
IsNil() bool
|
||||
// SetConnNil Set the connection of the current long connection to nil
|
||||
SetConnNil()
|
||||
// SetReadLimit sets the maximum size for a message read from the peer.bytes
|
||||
SetReadLimit(limit int64)
|
||||
SetPongHandler(handler PingPongHandler)
|
||||
SetPingHandler(handler PingPongHandler)
|
||||
// GenerateLongConn Check the connection of the current and when it was sent are the same
|
||||
GenerateLongConn(w http.ResponseWriter, r *http.Request) error
|
||||
}
|
||||
type GWebSocket struct {
|
||||
protocolType int
|
||||
conn *websocket.Conn
|
||||
handshakeTimeout time.Duration
|
||||
writeBufferSize int
|
||||
}
|
||||
|
||||
func newGWebSocket(protocolType int, handshakeTimeout time.Duration, wbs int) *GWebSocket {
|
||||
return &GWebSocket{protocolType: protocolType, handshakeTimeout: handshakeTimeout, writeBufferSize: wbs}
|
||||
}
|
||||
|
||||
func (d *GWebSocket) Close() error {
|
||||
return d.conn.Close()
|
||||
}
|
||||
|
||||
func (d *GWebSocket) GenerateLongConn(w http.ResponseWriter, r *http.Request) error {
|
||||
upgrader := &websocket.Upgrader{
|
||||
HandshakeTimeout: d.handshakeTimeout,
|
||||
CheckOrigin: func(r *http.Request) bool { return true },
|
||||
}
|
||||
if d.writeBufferSize > 0 { // default is 4kb.
|
||||
upgrader.WriteBufferSize = d.writeBufferSize
|
||||
}
|
||||
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
// The upgrader.Upgrade method usually returns enough error messages to diagnose problems that may occur during the upgrade
|
||||
return errs.WrapMsg(err, "GenerateLongConn: WebSocket upgrade failed")
|
||||
}
|
||||
d.conn = conn
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *GWebSocket) WriteMessage(messageType int, message []byte) error {
|
||||
// d.setSendConn(d.conn)
|
||||
return d.conn.WriteMessage(messageType, message)
|
||||
}
|
||||
|
||||
// func (d *GWebSocket) setSendConn(sendConn *websocket.Conn) {
|
||||
// d.sendConn = sendConn
|
||||
//}
|
||||
|
||||
func (d *GWebSocket) ReadMessage() (int, []byte, error) {
|
||||
return d.conn.ReadMessage()
|
||||
}
|
||||
|
||||
func (d *GWebSocket) SetReadDeadline(timeout time.Duration) error {
|
||||
return d.conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
}
|
||||
|
||||
func (d *GWebSocket) SetWriteDeadline(timeout time.Duration) error {
|
||||
if timeout <= 0 {
|
||||
return errs.New("timeout must be greater than 0")
|
||||
}
|
||||
|
||||
// TODO SetWriteDeadline Future add error handling
|
||||
if err := d.conn.SetWriteDeadline(time.Now().Add(timeout)); err != nil {
|
||||
return errs.WrapMsg(err, "GWebSocket.SetWriteDeadline failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *GWebSocket) Dial(urlStr string, requestHeader http.Header) (*http.Response, error) {
|
||||
conn, httpResp, err := websocket.DefaultDialer.Dial(urlStr, requestHeader)
|
||||
if err != nil {
|
||||
return httpResp, errs.WrapMsg(err, "GWebSocket.Dial failed", "url", urlStr)
|
||||
}
|
||||
d.conn = conn
|
||||
return httpResp, nil
|
||||
}
|
||||
|
||||
func (d *GWebSocket) IsNil() bool {
|
||||
return d.conn == nil
|
||||
//
|
||||
// if d.conn != nil {
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
}
|
||||
|
||||
func (d *GWebSocket) SetConnNil() {
|
||||
d.conn = nil
|
||||
}
|
||||
|
||||
func (d *GWebSocket) SetReadLimit(limit int64) {
|
||||
d.conn.SetReadLimit(limit)
|
||||
}
|
||||
|
||||
func (d *GWebSocket) SetPongHandler(handler PingPongHandler) {
|
||||
d.conn.SetPongHandler(handler)
|
||||
}
|
||||
|
||||
func (d *GWebSocket) SetPingHandler(handler PingPongHandler) {
|
||||
d.conn.SetPingHandler(handler)
|
||||
}
|
||||
|
||||
func (d *GWebSocket) RespondWithError(err error, w http.ResponseWriter, r *http.Request) error {
|
||||
if err := d.GenerateLongConn(w, r); err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := json.Marshal(apiresp.ParseError(err))
|
||||
if err != nil {
|
||||
_ = d.Close()
|
||||
return errs.WrapMsg(err, "json marshal failed")
|
||||
}
|
||||
|
||||
if err := d.WriteMessage(MessageText, data); err != nil {
|
||||
_ = d.Close()
|
||||
return errs.WrapMsg(err, "WriteMessage failed")
|
||||
}
|
||||
_ = d.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *GWebSocket) RespondWithSuccess() error {
|
||||
data, err := json.Marshal(apiresp.ParseError(nil))
|
||||
if err != nil {
|
||||
_ = d.Close()
|
||||
return errs.WrapMsg(err, "json marshal failed")
|
||||
}
|
||||
|
||||
if err := d.WriteMessage(MessageText, data); err != nil {
|
||||
_ = d.Close()
|
||||
return errs.WrapMsg(err, "WriteMessage failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -17,15 +17,17 @@ package msggateway
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"sync"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/push"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/utils/jsonutil"
|
||||
)
|
||||
@@ -100,34 +102,34 @@ func (r *Resp) String() string {
|
||||
}
|
||||
|
||||
type MessageHandler interface {
|
||||
GetSeq(ctx context.Context, data *Req) ([]byte, error)
|
||||
SendMessage(ctx context.Context, data *Req) ([]byte, error)
|
||||
SendSignalMessage(ctx context.Context, data *Req) ([]byte, error)
|
||||
PullMessageBySeqList(ctx context.Context, data *Req) ([]byte, error)
|
||||
GetConversationsHasReadAndMaxSeq(ctx context.Context, data *Req) ([]byte, error)
|
||||
GetSeqMessage(ctx context.Context, data *Req) ([]byte, error)
|
||||
UserLogout(ctx context.Context, data *Req) ([]byte, error)
|
||||
SetUserDeviceBackground(ctx context.Context, data *Req) ([]byte, bool, error)
|
||||
GetLastMessage(ctx context.Context, data *Req) ([]byte, error)
|
||||
GetSeq(context context.Context, data *Req) ([]byte, error)
|
||||
SendMessage(context context.Context, data *Req) ([]byte, error)
|
||||
SendSignalMessage(context context.Context, data *Req) ([]byte, error)
|
||||
PullMessageBySeqList(context context.Context, data *Req) ([]byte, error)
|
||||
GetConversationsHasReadAndMaxSeq(context context.Context, data *Req) ([]byte, error)
|
||||
GetSeqMessage(context context.Context, data *Req) ([]byte, error)
|
||||
UserLogout(context context.Context, data *Req) ([]byte, error)
|
||||
SetUserDeviceBackground(context context.Context, data *Req) ([]byte, bool, error)
|
||||
}
|
||||
|
||||
var _ MessageHandler = (*GrpcHandler)(nil)
|
||||
|
||||
type GrpcHandler struct {
|
||||
validate *validator.Validate
|
||||
msgClient *rpcli.MsgClient
|
||||
pushClient *rpcli.PushMsgServiceClient
|
||||
msgRpcClient *rpcclient.MessageRpcClient
|
||||
pushClient *rpcclient.PushRpcClient
|
||||
validate *validator.Validate
|
||||
}
|
||||
|
||||
func NewGrpcHandler(validate *validator.Validate, msgClient *rpcli.MsgClient, pushClient *rpcli.PushMsgServiceClient) *GrpcHandler {
|
||||
func NewGrpcHandler(validate *validator.Validate, client discovery.SvcDiscoveryRegistry, rpcRegisterName *config.RpcRegisterName) *GrpcHandler {
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, rpcRegisterName.Msg)
|
||||
pushRpcClient := rpcclient.NewPushRpcClient(client, rpcRegisterName.Push)
|
||||
return &GrpcHandler{
|
||||
validate: validate,
|
||||
msgClient: msgClient,
|
||||
pushClient: pushClient,
|
||||
msgRpcClient: &msgRpcClient,
|
||||
pushClient: &pushRpcClient, validate: validate,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
req := sdkws.GetMaxSeqReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "GetSeq: error unmarshaling request", "action", "unmarshal", "dataType", "GetMaxSeqReq")
|
||||
@@ -135,7 +137,7 @@ func (g *GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
if err := g.validate.Struct(&req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "GetSeq: validation failed", "action", "validate", "dataType", "GetMaxSeqReq")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.GetMaxSeq(ctx, &req)
|
||||
resp, err := g.msgRpcClient.GetMaxSeq(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -148,7 +150,7 @@ func (g *GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
|
||||
// SendMessage handles the sending of messages through gRPC. It unmarshals the request data,
|
||||
// validates the message, and then sends it using the message RPC client.
|
||||
func (g *GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
var msgData sdkws.MsgData
|
||||
if err := proto.Unmarshal(data.Data, &msgData); err != nil {
|
||||
return nil, errs.WrapMsg(err, "SendMessage: error unmarshaling message data", "action", "unmarshal", "dataType", "MsgData")
|
||||
@@ -159,7 +161,7 @@ func (g *GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error
|
||||
}
|
||||
|
||||
req := msg.SendMsgReq{MsgData: &msgData}
|
||||
resp, err := g.msgClient.MsgClient.SendMsg(ctx, &req)
|
||||
resp, err := g.msgRpcClient.SendMsg(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -172,8 +174,8 @@ func (g *GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) SendSignalMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
resp, err := g.msgClient.MsgClient.SendMsg(ctx, nil)
|
||||
func (g GrpcHandler) SendSignalMessage(context context.Context, data *Req) ([]byte, error) {
|
||||
resp, err := g.msgRpcClient.SendMsg(context, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -184,7 +186,7 @@ func (g *GrpcHandler) SendSignalMessage(ctx context.Context, data *Req) ([]byte,
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) PullMessageBySeqList(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) PullMessageBySeqList(context context.Context, data *Req) ([]byte, error) {
|
||||
req := sdkws.PullMessageBySeqsReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "err proto unmarshal", "action", "unmarshal", "dataType", "PullMessageBySeqsReq")
|
||||
@@ -192,7 +194,7 @@ func (g *GrpcHandler) PullMessageBySeqList(ctx context.Context, data *Req) ([]by
|
||||
if err := g.validate.Struct(data); err != nil {
|
||||
return nil, errs.WrapMsg(err, "validation failed", "action", "validate", "dataType", "PullMessageBySeqsReq")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.PullMessageBySeqs(ctx, &req)
|
||||
resp, err := g.msgRpcClient.PullMessageBySeqList(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -203,7 +205,7 @@ func (g *GrpcHandler) PullMessageBySeqList(ctx context.Context, data *Req) ([]by
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) GetConversationsHasReadAndMaxSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) GetConversationsHasReadAndMaxSeq(context context.Context, data *Req) ([]byte, error) {
|
||||
req := msg.GetConversationsHasReadAndMaxSeqReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "err proto unmarshal", "action", "unmarshal", "dataType", "GetConversationsHasReadAndMaxSeq")
|
||||
@@ -211,7 +213,7 @@ func (g *GrpcHandler) GetConversationsHasReadAndMaxSeq(ctx context.Context, data
|
||||
if err := g.validate.Struct(data); err != nil {
|
||||
return nil, errs.WrapMsg(err, "validation failed", "action", "validate", "dataType", "GetConversationsHasReadAndMaxSeq")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.GetConversationsHasReadAndMaxSeq(ctx, &req)
|
||||
resp, err := g.msgRpcClient.GetConversationsHasReadAndMaxSeq(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -222,7 +224,7 @@ func (g *GrpcHandler) GetConversationsHasReadAndMaxSeq(ctx context.Context, data
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) GetSeqMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) GetSeqMessage(context context.Context, data *Req) ([]byte, error) {
|
||||
req := msg.GetSeqMessageReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "error unmarshaling request", "action", "unmarshal", "dataType", "GetSeqMessage")
|
||||
@@ -230,7 +232,7 @@ func (g *GrpcHandler) GetSeqMessage(ctx context.Context, data *Req) ([]byte, err
|
||||
if err := g.validate.Struct(data); err != nil {
|
||||
return nil, errs.WrapMsg(err, "validation failed", "action", "validate", "dataType", "GetSeqMessage")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.GetSeqMessage(ctx, &req)
|
||||
resp, err := g.msgRpcClient.GetSeqMessage(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -241,12 +243,12 @@ func (g *GrpcHandler) GetSeqMessage(ctx context.Context, data *Req) ([]byte, err
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) UserLogout(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) UserLogout(context context.Context, data *Req) ([]byte, error) {
|
||||
req := push.DelUserPushTokenReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "error unmarshaling request", "action", "unmarshal", "dataType", "DelUserPushTokenReq")
|
||||
}
|
||||
resp, err := g.pushClient.PushMsgServiceClient.DelUserPushToken(ctx, &req)
|
||||
resp, err := g.pushClient.DelUserPushToken(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -257,7 +259,7 @@ func (g *GrpcHandler) UserLogout(ctx context.Context, data *Req) ([]byte, error)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) SetUserDeviceBackground(ctx context.Context, data *Req) ([]byte, bool, error) {
|
||||
func (g GrpcHandler) SetUserDeviceBackground(_ context.Context, data *Req) ([]byte, bool, error) {
|
||||
req := sdkws.SetAppBackgroundStatusReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, false, errs.WrapMsg(err, "error unmarshaling request", "action", "unmarshal", "dataType", "SetAppBackgroundStatusReq")
|
||||
@@ -267,15 +269,3 @@ func (g *GrpcHandler) SetUserDeviceBackground(ctx context.Context, data *Req) ([
|
||||
}
|
||||
return nil, req.IsBackground, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) GetLastMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
var req msg.GetLastMessageReq
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := g.msgClient.GetLastMessage(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proto.Marshal(resp)
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func (ws *WsServer) ChangeOnlineStatus(concurrent int) {
|
||||
opIdCtx := mcontext.SetOperationID(context.Background(), operationIDPrefix+strconv.FormatInt(count.Add(1), 10))
|
||||
ctx, cancel := context.WithTimeout(opIdCtx, time.Second*5)
|
||||
defer cancel()
|
||||
if err := ws.userClient.SetUserOnlineStatus(ctx, req); err != nil {
|
||||
if _, err := ws.userClient.Client.SetUserOnlineStatus(ctx, req); err != nil {
|
||||
log.ZError(ctx, "update user online status", err)
|
||||
}
|
||||
for _, ss := range req.Status {
|
||||
|
||||
@@ -2,42 +2,36 @@ package msggateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
pbAuth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/tools/apiresp"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
pbAuth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
var wsSuccessResponse, _ = json.Marshal(&apiresp.ApiResponse{})
|
||||
|
||||
type LongConnServer interface {
|
||||
Run(done chan error) error
|
||||
wsHandler(w http.ResponseWriter, r *http.Request)
|
||||
GetUserAllCons(userID string) ([]*Client, bool)
|
||||
GetUserPlatformCons(userID string, platform int) ([]*Client, bool, bool)
|
||||
Validate(s any) error
|
||||
SetDiscoveryRegistry(ctx context.Context, client discovery.SvcDiscoveryRegistry, config *Config) error
|
||||
SetDiscoveryRegistry(client discovery.SvcDiscoveryRegistry, config *Config)
|
||||
KickUserConn(client *Client) error
|
||||
UnRegister(c *Client)
|
||||
SetKickHandlerInfo(i *kickHandler)
|
||||
@@ -47,7 +41,6 @@ type LongConnServer interface {
|
||||
}
|
||||
|
||||
type WsServer struct {
|
||||
websocket *websocket.Upgrader
|
||||
msgGatewayConfig *Config
|
||||
port int
|
||||
wsMaxConnNum int64
|
||||
@@ -63,13 +56,13 @@ type WsServer struct {
|
||||
handshakeTimeout time.Duration
|
||||
writeBufferSize int
|
||||
validate *validator.Validate
|
||||
userClient *rpcclient.UserRpcClient
|
||||
authClient *rpcclient.Auth
|
||||
disCov discovery.SvcDiscoveryRegistry
|
||||
Compressor
|
||||
//Encoder
|
||||
MessageHandler
|
||||
webhookClient *webhook.Client
|
||||
userClient *rpcli.UserClient
|
||||
authClient *rpcli.AuthClient
|
||||
}
|
||||
|
||||
type kickHandler struct {
|
||||
@@ -78,28 +71,12 @@ type kickHandler struct {
|
||||
newClient *Client
|
||||
}
|
||||
|
||||
func (ws *WsServer) SetDiscoveryRegistry(ctx context.Context, disCov discovery.SvcDiscoveryRegistry, config *Config) error {
|
||||
userConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pushConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Push)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.userClient = rpcli.NewUserClient(userConn)
|
||||
ws.authClient = rpcli.NewAuthClient(authConn)
|
||||
ws.MessageHandler = NewGrpcHandler(ws.validate, rpcli.NewMsgClient(msgConn), rpcli.NewPushMsgServiceClient(pushConn))
|
||||
func (ws *WsServer) SetDiscoveryRegistry(disCov discovery.SvcDiscoveryRegistry, config *Config) {
|
||||
ws.MessageHandler = NewGrpcHandler(ws.validate, disCov, &config.Share.RpcRegisterName)
|
||||
u := rpcclient.NewUserRpcClient(disCov, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
ws.authClient = rpcclient.NewAuth(disCov, config.Share.RpcRegisterName.Auth)
|
||||
ws.userClient = &u
|
||||
ws.disCov = disCov
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (ws *WsServer) SetUserOnlineStatus(ctx context.Context, client *Client, status int32) {
|
||||
@@ -137,13 +114,9 @@ func NewWsServer(msgGatewayConfig *Config, opts ...Option) *WsServer {
|
||||
o(&config)
|
||||
}
|
||||
//userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
upgrader := &websocket.Upgrader{
|
||||
HandshakeTimeout: config.handshakeTimeout,
|
||||
CheckOrigin: func(r *http.Request) bool { return true },
|
||||
}
|
||||
|
||||
v := validator.New()
|
||||
return &WsServer{
|
||||
websocket: upgrader,
|
||||
msgGatewayConfig: msgGatewayConfig,
|
||||
port: config.port,
|
||||
wsMaxConnNum: config.maxConnNum,
|
||||
@@ -223,19 +196,15 @@ func (ws *WsServer) sendUserOnlineInfoToOtherNode(ctx context.Context, client *C
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(conns) == 0 || (len(conns) == 1 && ws.disCov.IsSelfNode(conns[0])) {
|
||||
return nil
|
||||
}
|
||||
|
||||
wg := errgroup.Group{}
|
||||
wg.SetLimit(concurrentRequest)
|
||||
|
||||
// Online push user online message to other node
|
||||
for _, v := range conns {
|
||||
v := v
|
||||
log.ZDebug(ctx, "sendUserOnlineInfoToOtherNode conn")
|
||||
if ws.disCov.IsSelfNode(v) {
|
||||
log.ZDebug(ctx, "Filter out this node")
|
||||
log.ZDebug(ctx, " sendUserOnlineInfoToOtherNode conn ", "target", v.Target())
|
||||
if v.Target() == ws.disCov.GetSelfConnTarget() {
|
||||
log.ZDebug(ctx, "Filter out this node", "node", v.Target())
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -246,7 +215,7 @@ func (ws *WsServer) sendUserOnlineInfoToOtherNode(ctx context.Context, client *C
|
||||
PlatformID: int32(client.PlatformID), Token: client.token,
|
||||
})
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "MultiTerminalLoginCheck err", err)
|
||||
log.ZWarn(ctx, "MultiTerminalLoginCheck err", err, "node", v.Target())
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -342,56 +311,22 @@ func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClients []*Clien
|
||||
[]string{newClient.ctx.GetOperationID(), newClient.ctx.GetUserID(),
|
||||
constant.PlatformIDToName(newClient.PlatformID), newClient.ctx.GetConnID()},
|
||||
)
|
||||
if err := ws.authClient.KickTokens(ctx, kickTokens); err != nil {
|
||||
if _, err := ws.authClient.KickTokens(ctx, kickTokens); err != nil {
|
||||
log.ZWarn(newClient.ctx, "kickTokens err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// If reconnect: When multiple msgGateway instances are deployed, a client may disconnect from instance A and reconnect to instance B.
|
||||
// During this process, instance A might still be executing, resulting in two clients with the same token existing simultaneously.
|
||||
// This situation needs to be filtered to prevent duplicate clients.
|
||||
checkSameTokenFunc := func(oldClients []*Client) []*Client {
|
||||
var clientsNeedToKick []*Client
|
||||
|
||||
for _, c := range oldClients {
|
||||
if c.token == newClient.token {
|
||||
log.ZDebug(newClient.ctx, "token is same, not kick",
|
||||
"userID", newClient.UserID,
|
||||
"platformID", newClient.PlatformID,
|
||||
"token", newClient.token)
|
||||
continue
|
||||
}
|
||||
|
||||
clientsNeedToKick = append(clientsNeedToKick, c)
|
||||
}
|
||||
|
||||
return clientsNeedToKick
|
||||
}
|
||||
|
||||
switch ws.msgGatewayConfig.Share.MultiLogin.Policy {
|
||||
case constant.DefalutNotKick:
|
||||
case constant.PCAndOther:
|
||||
if constant.PlatformIDToClass(newClient.PlatformID) == constant.TerminalPC {
|
||||
return
|
||||
}
|
||||
clients, ok := ws.clients.GetAll(newClient.UserID)
|
||||
clientOK = ok
|
||||
oldClients = make([]*Client, 0, len(clients))
|
||||
for _, c := range clients {
|
||||
if constant.PlatformIDToClass(c.PlatformID) == constant.TerminalPC {
|
||||
continue
|
||||
}
|
||||
oldClients = append(oldClients, c)
|
||||
}
|
||||
|
||||
fallthrough
|
||||
case constant.AllLoginButSameTermKick:
|
||||
if !clientOK {
|
||||
return
|
||||
}
|
||||
|
||||
oldClients = checkSameTokenFunc(oldClients)
|
||||
|
||||
ws.clients.DeleteClients(newClient.UserID, oldClients)
|
||||
for _, c := range oldClients {
|
||||
err := c.KickOnlineMessage()
|
||||
@@ -403,12 +338,7 @@ func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClients []*Clien
|
||||
[]string{newClient.ctx.GetOperationID(), newClient.ctx.GetUserID(),
|
||||
constant.PlatformIDToName(newClient.PlatformID), newClient.ctx.GetConnID()},
|
||||
)
|
||||
req := &pbAuth.InvalidateTokenReq{
|
||||
PreservedToken: newClient.token,
|
||||
UserID: newClient.UserID,
|
||||
PlatformID: int32(newClient.PlatformID),
|
||||
}
|
||||
if err := ws.authClient.InvalidateToken(ctx, req); err != nil {
|
||||
if _, err := ws.authClient.InvalidateToken(ctx, newClient.token, newClient.UserID, newClient.PlatformID); err != nil {
|
||||
log.ZWarn(newClient.ctx, "InvalidateToken err", err, "userID", newClient.UserID,
|
||||
"platformID", newClient.PlatformID)
|
||||
}
|
||||
@@ -417,15 +347,14 @@ func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClients []*Clien
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var kickClients []*Client
|
||||
var (
|
||||
kickClients []*Client
|
||||
)
|
||||
for _, client := range clients {
|
||||
if constant.PlatformIDToClass(client.PlatformID) == constant.PlatformIDToClass(newClient.PlatformID) {
|
||||
kickClients = append(kickClients, client)
|
||||
}
|
||||
}
|
||||
kickClients = checkSameTokenFunc(kickClients)
|
||||
|
||||
kickTokenFunc(kickClients)
|
||||
}
|
||||
}
|
||||
@@ -449,39 +378,16 @@ func (ws *WsServer) unregisterClient(client *Client) {
|
||||
// validateRespWithRequest checks if the response matches the expected userID and platformID.
|
||||
func (ws *WsServer) validateRespWithRequest(ctx *UserConnContext, resp *pbAuth.ParseTokenResp) error {
|
||||
userID := ctx.GetUserID()
|
||||
platformID := ctx.GetPlatformID()
|
||||
platformID := stringutil.StringToInt32(ctx.GetPlatformID())
|
||||
if resp.UserID != userID {
|
||||
return servererrs.ErrTokenInvalid.WrapMsg(fmt.Sprintf("token uid %s != userID %s", resp.UserID, userID))
|
||||
}
|
||||
if int(resp.PlatformID) != platformID {
|
||||
if resp.PlatformID != platformID {
|
||||
return servererrs.ErrTokenInvalid.WrapMsg(fmt.Sprintf("token platform %d != platformID %d", resp.PlatformID, platformID))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ws *WsServer) handlerError(ctx *UserConnContext, w http.ResponseWriter, r *http.Request, err error) {
|
||||
if !ctx.ShouldSendResp() {
|
||||
httpError(ctx, err)
|
||||
return
|
||||
}
|
||||
// the browser cannot get the response of upgrade failure
|
||||
data, err := json.Marshal(apiresp.ParseError(err))
|
||||
if err != nil {
|
||||
log.ZError(ctx, "json marshal failed", err)
|
||||
return
|
||||
}
|
||||
conn, upgradeErr := ws.websocket.Upgrade(w, r, nil)
|
||||
if upgradeErr != nil {
|
||||
log.ZWarn(ctx, "websocket upgrade failed", upgradeErr, "respErr", err, "resp", string(data))
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
|
||||
log.ZWarn(ctx, "WriteMessage failed", err, "respErr", err, "resp", string(data))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Create a new connection context
|
||||
connContext := newContext(w, r)
|
||||
@@ -489,7 +395,7 @@ func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Check if the current number of online user connections exceeds the maximum limit
|
||||
if ws.onlineUserConnNum.Load() >= ws.wsMaxConnNum {
|
||||
// If it exceeds the maximum connection number, return an error via HTTP and stop processing
|
||||
ws.handlerError(connContext, w, r, servererrs.ErrConnOverMaxNumLimit.WrapMsg("over max conn num limit"))
|
||||
httpError(connContext, servererrs.ErrConnOverMaxNumLimit.WrapMsg("over max conn num limit"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -497,14 +403,26 @@ func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err := connContext.ParseEssentialArgs()
|
||||
if err != nil {
|
||||
// If there's an error during parsing, return an error via HTTP and stop processing
|
||||
ws.handlerError(connContext, w, r, err)
|
||||
|
||||
httpError(connContext, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Call the authentication client to parse the Token obtained from the context
|
||||
resp, err := ws.authClient.ParseToken(connContext, connContext.GetToken())
|
||||
if err != nil {
|
||||
ws.handlerError(connContext, w, r, err)
|
||||
// If there's an error parsing the Token, decide whether to send the error message via WebSocket based on the context flag
|
||||
shouldSendError := connContext.ShouldSendResp()
|
||||
if shouldSendError {
|
||||
// Create a WebSocket connection object and attempt to send the error message via WebSocket
|
||||
wsLongConn := newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
|
||||
if err := wsLongConn.RespondWithError(err, w, r); err == nil {
|
||||
// If the error message is successfully sent via WebSocket, stop processing
|
||||
return
|
||||
}
|
||||
}
|
||||
// If sending via WebSocket is not required or fails, return the error via HTTP and stop processing
|
||||
httpError(connContext, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -512,30 +430,32 @@ func (ws *WsServer) wsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err = ws.validateRespWithRequest(connContext, resp)
|
||||
if err != nil {
|
||||
// If validation fails, return an error via HTTP and stop processing
|
||||
ws.handlerError(connContext, w, r, err)
|
||||
httpError(connContext, err)
|
||||
return
|
||||
}
|
||||
conn, err := ws.websocket.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.ZWarn(connContext, "websocket upgrade failed", err)
|
||||
return
|
||||
}
|
||||
if connContext.ShouldSendResp() {
|
||||
if err := conn.WriteMessage(websocket.TextMessage, wsSuccessResponse); err != nil {
|
||||
log.ZWarn(connContext, "WriteMessage first response", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.ZDebug(connContext, "new conn", "token", connContext.GetToken())
|
||||
|
||||
var pingInterval time.Duration
|
||||
if connContext.GetPlatformID() == constant.WebPlatformID {
|
||||
pingInterval = pingPeriod
|
||||
log.ZDebug(connContext, "new conn", "token", connContext.GetToken())
|
||||
// Create a WebSocket long connection object
|
||||
wsLongConn := newGWebSocket(WebSocket, ws.handshakeTimeout, ws.writeBufferSize)
|
||||
if err := wsLongConn.GenerateLongConn(w, r); err != nil {
|
||||
//If the creation of the long connection fails, the error is handled internally during the handshake process.
|
||||
log.ZWarn(connContext, "long connection fails", err)
|
||||
return
|
||||
} else {
|
||||
// Check if a normal response should be sent via WebSocket
|
||||
shouldSendSuccessResp := connContext.ShouldSendResp()
|
||||
if shouldSendSuccessResp {
|
||||
// Attempt to send a success message through WebSocket
|
||||
if err := wsLongConn.RespondWithSuccess(); err != nil {
|
||||
// If the success message is successfully sent, end further processing
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve a client object from the client pool, reset its state, and associate it with the current WebSocket long connection
|
||||
client := ws.clientPool.Get().(*Client)
|
||||
client.ResetClient(connContext, NewWebSocketClientConn(conn, maxMessageSize, pongWait, pingInterval), ws)
|
||||
client.ResetClient(connContext, wsLongConn, ws)
|
||||
|
||||
// Register the client with the server and start message processing
|
||||
ws.registerChan <- client
|
||||
|
||||
@@ -18,17 +18,11 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/openimsdk/tools/discovery/etcd"
|
||||
"github.com/openimsdk/tools/utils/jsonutil"
|
||||
"github.com/openimsdk/tools/utils/network"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
||||
@@ -36,10 +30,10 @@ import (
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
|
||||
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
discRegister "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mw"
|
||||
@@ -60,17 +54,16 @@ type MsgTransfer struct {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
MsgTransfer conf.MsgTransfer
|
||||
RedisConfig conf.Redis
|
||||
MongodbConfig conf.Mongo
|
||||
KafkaConfig conf.Kafka
|
||||
Share conf.Share
|
||||
WebhooksConfig conf.Webhooks
|
||||
Discovery conf.Discovery
|
||||
MsgTransfer config.MsgTransfer
|
||||
RedisConfig config.Redis
|
||||
MongodbConfig config.Mongo
|
||||
KafkaConfig config.Kafka
|
||||
Share config.Share
|
||||
WebhooksConfig config.Webhooks
|
||||
Discovery config.Discovery
|
||||
}
|
||||
|
||||
func Start(ctx context.Context, index int, config *Config) error {
|
||||
|
||||
log.CInfo(ctx, "MSG-TRANSFER server is initializing", "prometheusPorts",
|
||||
config.MsgTransfer.Prometheus.Ports, "index", index)
|
||||
|
||||
@@ -82,18 +75,18 @@ func Start(ctx context.Context, index int, config *Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := discRegister.NewDiscoveryRegister(&config.Discovery, &config.Share, nil)
|
||||
client, err := discRegister.NewDiscoveryRegister(&config.Discovery, &config.Share)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||
|
||||
msgModel := redis.NewMsgCache(rdb)
|
||||
msgDocModel, err := mgo.NewMsgMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgModel := redis.NewMsgCache(rdb, msgDocModel)
|
||||
seqConversation, err := mgo.NewSeqConversationMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -108,7 +101,9 @@ func Start(ctx context.Context, index int, config *Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
historyCH, err := NewOnlineHistoryRedisConsumerHandler(ctx, client, config, msgTransferDatabase)
|
||||
conversationRpcClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
historyCH, err := NewOnlineHistoryRedisConsumerHandler(&config.KafkaConfig, msgTransferDatabase, &conversationRpcClient, &groupRpcClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -124,7 +119,7 @@ func Start(ctx context.Context, index int, config *Config) error {
|
||||
return msgTransfer.Start(index, config)
|
||||
}
|
||||
|
||||
func (m *MsgTransfer) Start(index int, cfg *Config) error {
|
||||
func (m *MsgTransfer) Start(index int, config *Config) error {
|
||||
m.ctx, m.cancel = context.WithCancel(context.Background())
|
||||
var (
|
||||
netDone = make(chan struct{}, 1)
|
||||
@@ -139,74 +134,21 @@ func (m *MsgTransfer) Start(index int, cfg *Config) error {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := kdisc.NewDiscoveryRegister(&cfg.Discovery, &cfg.Share, nil)
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "failed to register discovery service")
|
||||
}
|
||||
|
||||
registerIP, err := network.GetRpcRegisterIP("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
getAutoPort := func() (net.Listener, int, error) {
|
||||
registerAddr := net.JoinHostPort(registerIP, "0")
|
||||
listener, err := net.Listen("tcp", registerAddr)
|
||||
if err != nil {
|
||||
return nil, 0, errs.WrapMsg(err, "listen err", "registerAddr", registerAddr)
|
||||
}
|
||||
_, portStr, _ := net.SplitHostPort(listener.Addr().String())
|
||||
port, _ := strconv.Atoi(portStr)
|
||||
return listener, port, nil
|
||||
}
|
||||
|
||||
if cfg.MsgTransfer.Prometheus.AutoSetPorts && cfg.Discovery.Enable != conf.ETCD {
|
||||
return errs.New("only etcd support autoSetPorts", "RegisterName", "api").Wrap()
|
||||
}
|
||||
|
||||
if cfg.MsgTransfer.Prometheus.Enable {
|
||||
var (
|
||||
listener net.Listener
|
||||
prometheusPort int
|
||||
)
|
||||
|
||||
if cfg.MsgTransfer.Prometheus.AutoSetPorts {
|
||||
listener, prometheusPort, err = getAutoPort()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
etcdClient, ok := client.(*etcd.SvcDiscoveryRegistryImpl)
|
||||
if !ok {
|
||||
return errs.New("only etcd support autoSetPorts").Wrap()
|
||||
}
|
||||
|
||||
target, err := jsonutil.JsonMarshal(prommetrics.BuildDefaultTarget(registerIP, prometheusPort))
|
||||
if err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
err = etcdClient.SetWithLease(context.TODO(), prommetrics.BuildDiscoveryKey(prommetrics.MessageTransferKeyName, index), target, prommetrics.TTL)
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "etcd put err")
|
||||
}
|
||||
} else {
|
||||
prometheusPort, err = datautil.GetElemByIndex(cfg.MsgTransfer.Prometheus.Ports, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listener, err = net.Listen("tcp", fmt.Sprintf(":%d", prometheusPort))
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "listen err", "addr", fmt.Sprintf(":%d", prometheusPort))
|
||||
}
|
||||
}
|
||||
|
||||
if config.MsgTransfer.Prometheus.Enable {
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.ZPanic(m.ctx, "MsgTransfer Start Panic", errs.ErrPanic(r))
|
||||
log.ZPanic(m.ctx, "MsgTransfer Start Panic", r)
|
||||
}
|
||||
}()
|
||||
if err := prommetrics.TransferInit(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
prometheusPort, err := datautil.GetElemByIndex(config.MsgTransfer.Prometheus.Ports, index)
|
||||
if err != nil {
|
||||
netErr = err
|
||||
netDone <- struct{}{}
|
||||
return
|
||||
}
|
||||
|
||||
if err := prommetrics.TransferInit(prometheusPort); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
netErr = errs.WrapMsg(err, "prometheus start error", "prometheusPort", prometheusPort)
|
||||
netDone <- struct{}{}
|
||||
}
|
||||
|
||||
@@ -23,26 +23,23 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
|
||||
"github.com/go-redis/redis"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/tools/batcher"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbconv "github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/mq/kafka"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -72,32 +69,21 @@ type OnlineHistoryRedisConsumerHandler struct {
|
||||
redisMessageBatches *batcher.Batcher[sarama.ConsumerMessage]
|
||||
|
||||
msgTransferDatabase controller.MsgTransferDatabase
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient
|
||||
groupRpcClient *rpcclient.GroupRpcClient
|
||||
conversationUserHasReadChan chan *userHasReadSeq
|
||||
wg sync.WaitGroup
|
||||
|
||||
groupClient *rpcli.GroupClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
}
|
||||
|
||||
func NewOnlineHistoryRedisConsumerHandler(ctx context.Context, client discovery.SvcDiscoveryRegistry, config *Config, database controller.MsgTransferDatabase) (*OnlineHistoryRedisConsumerHandler, error) {
|
||||
kafkaConf := config.KafkaConfig
|
||||
func NewOnlineHistoryRedisConsumerHandler(kafkaConf *config.Kafka, database controller.MsgTransferDatabase,
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient) (*OnlineHistoryRedisConsumerHandler, error) {
|
||||
historyConsumerGroup, err := kafka.NewMConsumerGroup(kafkaConf.Build(), kafkaConf.ToRedisGroupID, []string{kafkaConf.ToRedisTopic}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var och OnlineHistoryRedisConsumerHandler
|
||||
och.msgTransferDatabase = database
|
||||
och.conversationUserHasReadChan = make(chan *userHasReadSeq, hasReadChanBuffer)
|
||||
och.groupClient = rpcli.NewGroupClient(groupConn)
|
||||
och.conversationClient = rpcli.NewConversationClient(conversationConn)
|
||||
och.wg.Add(1)
|
||||
|
||||
b := batcher.New[sarama.ConsumerMessage](
|
||||
@@ -117,21 +103,25 @@ func NewOnlineHistoryRedisConsumerHandler(ctx context.Context, client discovery.
|
||||
}
|
||||
b.Do = och.do
|
||||
och.redisMessageBatches = b
|
||||
och.conversationRpcClient = conversationRpcClient
|
||||
och.groupRpcClient = groupRpcClient
|
||||
och.historyConsumerGroup = historyConsumerGroup
|
||||
|
||||
return &och, nil
|
||||
return &och, err
|
||||
}
|
||||
func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, channelID int, val *batcher.Msg[sarama.ConsumerMessage]) {
|
||||
ctx = mcontext.WithTriggerIDContext(ctx, val.TriggerID())
|
||||
ctxMessages := och.parseConsumerMessages(ctx, val.Val())
|
||||
ctx = withAggregationCtx(ctx, ctxMessages)
|
||||
log.ZInfo(ctx, "msg arrived channel", "channel id", channelID, "msgList length", len(ctxMessages), "key", val.Key())
|
||||
log.ZInfo(ctx, "msg arrived channel", "channel id", channelID, "msgList length", len(ctxMessages),
|
||||
"key", val.Key())
|
||||
och.doSetReadSeq(ctx, ctxMessages)
|
||||
|
||||
storageMsgList, notStorageMsgList, storageNotificationList, notStorageNotificationList :=
|
||||
och.categorizeMessageLists(ctxMessages)
|
||||
log.ZDebug(ctx, "number of categorized messages", "storageMsgList", len(storageMsgList), "notStorageMsgList",
|
||||
len(notStorageMsgList), "storageNotificationList", len(storageNotificationList), "notStorageNotificationList", len(notStorageNotificationList))
|
||||
len(notStorageMsgList), "storageNotificationList", len(storageNotificationList), "notStorageNotificationList",
|
||||
len(notStorageNotificationList))
|
||||
|
||||
conversationIDMsg := msgprocessor.GetChatConversationIDByMsg(ctxMessages[0].message)
|
||||
conversationIDNotification := msgprocessor.GetNotificationConversationIDByMsg(ctxMessages[0].message)
|
||||
@@ -141,48 +131,53 @@ func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, channelID
|
||||
|
||||
func (och *OnlineHistoryRedisConsumerHandler) doSetReadSeq(ctx context.Context, msgs []*ContextMsg) {
|
||||
|
||||
// Outer map: conversationID -> (userID -> maxHasReadSeq)
|
||||
conversationUserSeq := make(map[string]map[string]int64)
|
||||
|
||||
var conversationID string
|
||||
var userSeqMap map[string]int64
|
||||
for _, msg := range msgs {
|
||||
if msg.message.ContentType != constant.HasReadReceipt {
|
||||
continue
|
||||
}
|
||||
var elem sdkws.NotificationElem
|
||||
if err := json.Unmarshal(msg.message.Content, &elem); err != nil {
|
||||
log.ZWarn(ctx, "Unmarshal NotificationElem error", err, "msg", msg)
|
||||
log.ZWarn(ctx, "handlerConversationRead Unmarshal NotificationElem msg err", err, "msg", msg)
|
||||
continue
|
||||
}
|
||||
var tips sdkws.MarkAsReadTips
|
||||
if err := json.Unmarshal([]byte(elem.Detail), &tips); err != nil {
|
||||
log.ZWarn(ctx, "Unmarshal MarkAsReadTips error", err, "msg", msg)
|
||||
log.ZWarn(ctx, "handlerConversationRead Unmarshal MarkAsReadTips msg err", err, "msg", msg)
|
||||
continue
|
||||
}
|
||||
if len(tips.ConversationID) == 0 || tips.HasReadSeq < 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Calculate the max seq from tips.Seqs
|
||||
for _, seq := range tips.Seqs {
|
||||
if tips.HasReadSeq < seq {
|
||||
tips.HasReadSeq = seq
|
||||
//The conversation ID for each batch of messages processed by the batcher is the same.
|
||||
conversationID = tips.ConversationID
|
||||
if len(tips.Seqs) > 0 {
|
||||
for _, seq := range tips.Seqs {
|
||||
if tips.HasReadSeq < seq {
|
||||
tips.HasReadSeq = seq
|
||||
}
|
||||
}
|
||||
clear(tips.Seqs)
|
||||
tips.Seqs = nil
|
||||
}
|
||||
if tips.HasReadSeq < 0 {
|
||||
continue
|
||||
}
|
||||
if userSeqMap == nil {
|
||||
userSeqMap = make(map[string]int64)
|
||||
}
|
||||
|
||||
if _, ok := conversationUserSeq[tips.ConversationID]; !ok {
|
||||
conversationUserSeq[tips.ConversationID] = make(map[string]int64)
|
||||
}
|
||||
if conversationUserSeq[tips.ConversationID][tips.MarkAsReadUserID] < tips.HasReadSeq {
|
||||
conversationUserSeq[tips.ConversationID][tips.MarkAsReadUserID] = tips.HasReadSeq
|
||||
if userSeqMap[tips.MarkAsReadUserID] > tips.HasReadSeq {
|
||||
continue
|
||||
}
|
||||
userSeqMap[tips.MarkAsReadUserID] = tips.HasReadSeq
|
||||
}
|
||||
log.ZInfo(ctx, "doSetReadSeq", "conversationUserSeq", conversationUserSeq)
|
||||
|
||||
// persist to db
|
||||
for convID, userSeqMap := range conversationUserSeq {
|
||||
if err := och.msgTransferDatabase.SetHasReadSeqToDB(ctx, convID, userSeqMap); err != nil {
|
||||
log.ZWarn(ctx, "SetHasReadSeqToDB error", err, "conversationID", convID, "userSeqMap", userSeqMap)
|
||||
}
|
||||
if userSeqMap == nil {
|
||||
return
|
||||
}
|
||||
if len(conversationID) == 0 {
|
||||
log.ZWarn(ctx, "conversation err", nil, "conversationID", conversationID)
|
||||
}
|
||||
if err := och.msgTransferDatabase.SetHasReadSeqToDB(ctx, conversationID, userSeqMap); err != nil {
|
||||
log.ZWarn(ctx, "set read seq to db error", err, "conversationID", conversationID, "userSeqMap", userSeqMap)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -286,32 +281,26 @@ func (och *OnlineHistoryRedisConsumerHandler) handleMsg(ctx context.Context, key
|
||||
}
|
||||
|
||||
if isNewConversation {
|
||||
ctx := storageList[0].ctx
|
||||
switch msg.SessionType {
|
||||
case constant.ReadGroupChatType:
|
||||
log.ZDebug(ctx, "group chat first create conversation", "conversationID",
|
||||
conversationID)
|
||||
|
||||
userIDs, err := och.groupClient.GetGroupMemberUserIDs(ctx, msg.GroupID)
|
||||
userIDs, err := och.groupRpcClient.GetGroupMemberIDs(ctx, msg.GroupID)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "get group member ids error", err, "conversationID",
|
||||
conversationID)
|
||||
} else {
|
||||
log.ZInfo(ctx, "GetGroupMemberIDs end")
|
||||
|
||||
if err := och.conversationClient.CreateGroupChatConversations(ctx, msg.GroupID, userIDs); err != nil {
|
||||
if err := och.conversationRpcClient.GroupChatFirstCreateConversation(ctx,
|
||||
msg.GroupID, userIDs); err != nil {
|
||||
log.ZWarn(ctx, "single chat first create conversation error", err,
|
||||
"conversationID", conversationID)
|
||||
}
|
||||
}
|
||||
case constant.SingleChatType, constant.NotificationChatType:
|
||||
req := &pbconv.CreateSingleChatConversationsReq{
|
||||
RecvID: msg.RecvID,
|
||||
SendID: msg.SendID,
|
||||
ConversationID: conversationID,
|
||||
ConversationType: msg.SessionType,
|
||||
}
|
||||
if err := och.conversationClient.CreateSingleChatConversations(ctx, req); err != nil {
|
||||
if err := och.conversationRpcClient.SingleChatFirstCreateConversation(ctx, msg.RecvID,
|
||||
msg.SendID, conversationID, msg.SessionType); err != nil {
|
||||
log.ZWarn(ctx, "single chat or notification first create conversation error", err,
|
||||
"conversationID", conversationID, "sessionType", msg.SessionType)
|
||||
}
|
||||
@@ -360,7 +349,7 @@ func (och *OnlineHistoryRedisConsumerHandler) handleNotification(ctx context.Con
|
||||
func (och *OnlineHistoryRedisConsumerHandler) HandleUserHasReadSeqMessages(ctx context.Context) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.ZPanic(ctx, "HandleUserHasReadSeqMessages Panic", errs.ErrPanic(r))
|
||||
log.ZPanic(ctx, "HandleUserHasReadSeqMessages Panic", r)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||
pbmsg "github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mq/kafka"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -73,21 +73,31 @@ func (mc *OnlineHistoryMongoConsumerHandler) handleChatWs2Mongo(ctx context.Cont
|
||||
} else {
|
||||
prommetrics.MsgInsertMongoSuccessCounter.Inc()
|
||||
}
|
||||
//var seqs []int64
|
||||
//for _, msg := range msgFromMQ.MsgData {
|
||||
// seqs = append(seqs, msg.Seq)
|
||||
//}
|
||||
//if err := mc.msgTransferDatabase.DeleteMessagesFromCache(ctx, msgFromMQ.ConversationID, seqs); err != nil {
|
||||
// log.ZError(ctx, "remove cache msg from redis err", err, "msg",
|
||||
// msgFromMQ.MsgData, "conversationID", msgFromMQ.ConversationID)
|
||||
//}
|
||||
var seqs []int64
|
||||
for _, msg := range msgFromMQ.MsgData {
|
||||
seqs = append(seqs, msg.Seq)
|
||||
}
|
||||
err = mc.msgTransferDatabase.DeleteMessagesFromCache(ctx, msgFromMQ.ConversationID, seqs)
|
||||
if err != nil {
|
||||
log.ZError(
|
||||
ctx,
|
||||
"remove cache msg from redis err",
|
||||
err,
|
||||
"msg",
|
||||
msgFromMQ.MsgData,
|
||||
"conversationID",
|
||||
msgFromMQ.ConversationID,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (*OnlineHistoryMongoConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
|
||||
func (*OnlineHistoryMongoConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
func (*OnlineHistoryMongoConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
|
||||
func (mc *OnlineHistoryMongoConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error { // an instance in the consumer group
|
||||
func (mc *OnlineHistoryMongoConsumerHandler) ConsumeClaim(
|
||||
sess sarama.ConsumerGroupSession,
|
||||
claim sarama.ConsumerGroupClaim,
|
||||
) error { // an instance in the consumer group
|
||||
log.ZDebug(context.Background(), "online new session msg come", "highWaterMarkOffset",
|
||||
claim.HighWaterMarkOffset(), "topic", claim.Topic(), "partition", claim.Partition())
|
||||
for msg := range claim.Messages() {
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
func NewClient() *Dummy {
|
||||
@@ -26,12 +25,10 @@ func NewClient() *Dummy {
|
||||
}
|
||||
|
||||
type Dummy struct {
|
||||
v atomic.Bool
|
||||
}
|
||||
|
||||
func (d *Dummy) Push(ctx context.Context, userIDs []string, title, content string, opts *options.Opts) error {
|
||||
if d.v.CompareAndSwap(false, true) {
|
||||
log.ZWarn(ctx, "dummy push", nil, "ps", "the offline push is not configured. to configure it, please go to config/openim-push.yml")
|
||||
}
|
||||
log.ZDebug(ctx, "dummy push")
|
||||
log.ZWarn(ctx, "Dummy push", nil, "ps", "The offline push is not configured. To configure it, please go to config/openim-push.yml.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush"
|
||||
"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbpush "github.com/openimsdk/protocol/push"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mq/kafka"
|
||||
"github.com/openimsdk/tools/utils/jsonutil"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -2,8 +2,6 @@ package push
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
@@ -11,6 +9,7 @@ import (
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/grpc"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type OnlinePusher interface {
|
||||
@@ -161,7 +160,7 @@ func (k *K8sStaticConsistentHash) GetConnsAndOnlinePush(ctx context.Context, msg
|
||||
}
|
||||
}
|
||||
log.ZDebug(ctx, "genUsers send hosts struct:", "usersHost", usersHost)
|
||||
var usersConns = make(map[grpc.ClientConnInterface][]string)
|
||||
var usersConns = make(map[*grpc.ClientConn][]string)
|
||||
for host, userIds := range usersHost {
|
||||
tconn, _ := k.disCov.GetConn(ctx, host)
|
||||
usersConns[tconn] = userIds
|
||||
|
||||
@@ -32,8 +32,11 @@ type Config struct {
|
||||
LocalCacheConfig config.LocalCache
|
||||
Discovery config.Discovery
|
||||
FcmConfigPath string
|
||||
}
|
||||
|
||||
runTimeEnv string
|
||||
func (p pushServer) PushMsg(ctx context.Context, req *pbpush.PushMsgReq) (*pbpush.PushMsgResp, error) {
|
||||
//todo reserved Interface
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p pushServer) DelUserPushToken(ctx context.Context,
|
||||
@@ -57,7 +60,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
|
||||
database := controller.NewPushDatabase(cacheModel, &config.KafkaConfig)
|
||||
|
||||
consumer, err := NewConsumerHandler(ctx, config, database, offlinePusher, rdb, client)
|
||||
consumer, err := NewConsumerHandler(config, database, offlinePusher, rdb, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,21 +3,20 @@ package push
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush"
|
||||
"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/util/conversationutil"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
@@ -26,6 +25,7 @@ import (
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/mq/kafka"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/openimsdk/tools/utils/jsonutil"
|
||||
"github.com/openimsdk/tools/utils/timeutil"
|
||||
@@ -41,15 +41,14 @@ type ConsumerHandler struct {
|
||||
onlineCache *rpccache.OnlineCache
|
||||
groupLocalCache *rpccache.GroupLocalCache
|
||||
conversationLocalCache *rpccache.ConversationLocalCache
|
||||
msgRpcClient rpcclient.MessageRpcClient
|
||||
conversationRpcClient rpcclient.ConversationRpcClient
|
||||
groupRpcClient rpcclient.GroupRpcClient
|
||||
webhookClient *webhook.Client
|
||||
config *Config
|
||||
userClient *rpcli.UserClient
|
||||
groupClient *rpcli.GroupClient
|
||||
msgClient *rpcli.MsgClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
}
|
||||
|
||||
func NewConsumerHandler(ctx context.Context, config *Config, database controller.PushDatabase, offlinePusher offlinepush.OfflinePusher, rdb redis.UniversalClient,
|
||||
func NewConsumerHandler(config *Config, database controller.PushDatabase, offlinePusher offlinepush.OfflinePusher, rdb redis.UniversalClient,
|
||||
client discovery.SvcDiscoveryRegistry) (*ConsumerHandler, error) {
|
||||
var consumerHandler ConsumerHandler
|
||||
var err error
|
||||
@@ -58,35 +57,20 @@ func NewConsumerHandler(ctx context.Context, config *Config, database controller
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
consumerHandler.userClient = rpcli.NewUserClient(userConn)
|
||||
consumerHandler.groupClient = rpcli.NewGroupClient(groupConn)
|
||||
consumerHandler.msgClient = rpcli.NewMsgClient(msgConn)
|
||||
consumerHandler.conversationClient = rpcli.NewConversationClient(conversationConn)
|
||||
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
|
||||
consumerHandler.offlinePusher = offlinePusher
|
||||
consumerHandler.onlinePusher = NewOnlinePusher(client, config)
|
||||
consumerHandler.groupLocalCache = rpccache.NewGroupLocalCache(consumerHandler.groupClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.conversationLocalCache = rpccache.NewConversationLocalCache(consumerHandler.conversationClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.groupRpcClient = rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
consumerHandler.groupLocalCache = rpccache.NewGroupLocalCache(consumerHandler.groupRpcClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.msgRpcClient = rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
consumerHandler.conversationRpcClient = rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
consumerHandler.conversationLocalCache = rpccache.NewConversationLocalCache(consumerHandler.conversationRpcClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.webhookClient = webhook.NewWebhookClient(config.WebhooksConfig.URL)
|
||||
consumerHandler.config = config
|
||||
consumerHandler.pushDatabase = database
|
||||
consumerHandler.onlineCache, err = rpccache.NewOnlineCache(consumerHandler.userClient, consumerHandler.groupLocalCache, rdb, config.RpcConfig.FullUserCache, nil)
|
||||
consumerHandler.onlineCache, err = rpccache.NewOnlineCache(userRpcClient, consumerHandler.groupLocalCache, rdb, config.RpcConfig.FullUserCache, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,7 +126,6 @@ func (c *ConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim s
|
||||
|
||||
for msg := range claim.Messages() {
|
||||
ctx := c.pushConsumerGroup.GetContextFromMsg(msg)
|
||||
ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUserID[0])
|
||||
c.handleMs2PsChat(ctx, msg.Value)
|
||||
sess.MarkMessage(msg, "")
|
||||
}
|
||||
@@ -154,24 +137,24 @@ func (c *ConsumerHandler) Push2User(ctx context.Context, userIDs []string, msg *
|
||||
log.ZInfo(ctx, "Get msg from msg_transfer And push msg", "userIDs", userIDs, "msg", msg.String())
|
||||
defer func(duration time.Time) {
|
||||
t := time.Since(duration)
|
||||
log.ZInfo(ctx, "Get msg from msg_transfer And push msg end", "msg", msg.String(), "time cost", t)
|
||||
log.ZInfo(ctx, "Get msg from msg_transfer And push msg", "msg", msg.String(), "time cost", t)
|
||||
}(time.Now())
|
||||
if err := c.webhookBeforeOnlinePush(ctx, &c.config.WebhooksConfig.BeforeOnlinePush, userIDs, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZInfo(ctx, "webhookBeforeOnlinePush end")
|
||||
|
||||
wsResults, err := c.GetConnsAndOnlinePush(ctx, msg, userIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.ZDebug(ctx, "single and notification push result", "result", wsResults, "msg", msg, "push_to_userID", userIDs)
|
||||
log.ZInfo(ctx, "single and notification push end")
|
||||
log.ZInfo(ctx, "single and notification push result", "result", wsResults, "msg", msg, "push_to_userID", userIDs)
|
||||
|
||||
if !c.shouldPushOffline(ctx, msg) {
|
||||
return nil
|
||||
}
|
||||
log.ZInfo(ctx, "pushOffline start")
|
||||
log.ZInfo(ctx, "shouldPushOffline end")
|
||||
|
||||
for _, v := range wsResults {
|
||||
//message sender do not need offline push
|
||||
@@ -190,14 +173,14 @@ func (c *ConsumerHandler) Push2User(ctx context.Context, userIDs []string, msg *
|
||||
if err = c.webhookBeforeOfflinePush(ctx, &c.config.WebhooksConfig.BeforeOfflinePush, needOfflinePushUserID, msg, &offlinePushUserID); err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZInfo(ctx, "webhookBeforeOfflinePush end")
|
||||
|
||||
if len(offlinePushUserID) > 0 {
|
||||
needOfflinePushUserID = offlinePushUserID
|
||||
}
|
||||
err = c.offlinePushMsg(ctx, msg, needOfflinePushUserID)
|
||||
if err != nil {
|
||||
log.ZDebug(ctx, "offlinePushMsg failed", err, "needOfflinePushUserID", needOfflinePushUserID, "msg", msg)
|
||||
log.ZWarn(ctx, "offlinePushMsg failed", err, "needOfflinePushUserID length", len(needOfflinePushUserID), "msg", msg)
|
||||
log.ZWarn(ctx, "offlinePushMsg failed", err, "needOfflinePushUserID", needOfflinePushUserID, "msg", msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -209,10 +192,7 @@ func (c *ConsumerHandler) shouldPushOffline(_ context.Context, msg *sdkws.MsgDat
|
||||
if !isOfflinePush {
|
||||
return false
|
||||
}
|
||||
switch msg.ContentType {
|
||||
case constant.RoomParticipantsConnectedNotification:
|
||||
return false
|
||||
case constant.RoomParticipantsDisconnectedNotification:
|
||||
if msg.ContentType == constant.SignalingNotification {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -255,24 +235,26 @@ func (c *ConsumerHandler) Push2Group(ctx context.Context, groupID string, msg *s
|
||||
&pushToUserIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZInfo(ctx, "webhookBeforeGroupOnlinePush end")
|
||||
|
||||
err = c.groupMessagesHandler(ctx, groupID, &pushToUserIDs, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZInfo(ctx, "groupMessagesHandler end")
|
||||
|
||||
wsResults, err := c.GetConnsAndOnlinePush(ctx, msg, pushToUserIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.ZDebug(ctx, "group push result", "result", wsResults, "msg", msg)
|
||||
log.ZInfo(ctx, "online group push end")
|
||||
log.ZInfo(ctx, "group push result", "result", wsResults, "msg", msg)
|
||||
|
||||
if !c.shouldPushOffline(ctx, msg) {
|
||||
return nil
|
||||
}
|
||||
needOfflinePushUserIDs := c.onlinePusher.GetOnlinePushFailedUserIDs(ctx, msg, wsResults, &pushToUserIDs)
|
||||
log.ZInfo(ctx, "GetOnlinePushFailedUserIDs end")
|
||||
//filter some user, like don not disturb or don't need offline push etc.
|
||||
needOfflinePushUserIDs, err = c.filterGroupMessageOfflinePush(ctx, groupID, msg, needOfflinePushUserIDs)
|
||||
if err != nil {
|
||||
@@ -300,11 +282,9 @@ func (c *ConsumerHandler) asyncOfflinePush(ctx context.Context, needOfflinePushU
|
||||
needOfflinePushUserIDs = offlinePushUserIDs
|
||||
}
|
||||
if err := c.pushDatabase.MsgToOfflinePushMQ(ctx, conversationutil.GenConversationUniqueKeyForSingle(msg.SendID, msg.RecvID), needOfflinePushUserIDs, msg); err != nil {
|
||||
log.ZDebug(ctx, "Msg To OfflinePush MQ error", err, "needOfflinePushUserIDs",
|
||||
log.ZError(ctx, "Msg To OfflinePush MQ error", err, "needOfflinePushUserIDs",
|
||||
needOfflinePushUserIDs, "msg", msg)
|
||||
log.ZWarn(ctx, "Msg To OfflinePush MQ error", err, "needOfflinePushUserIDs length",
|
||||
len(needOfflinePushUserIDs), "msg", msg)
|
||||
prommetrics.GroupChatMsgProcessFailedCounter.Inc()
|
||||
prommetrics.SingleChatMsgProcessFailedCounter.Inc()
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -347,7 +327,7 @@ func (c *ConsumerHandler) groupMessagesHandler(ctx context.Context, groupID stri
|
||||
ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUserID[0])
|
||||
}
|
||||
defer func(groupID string) {
|
||||
if err := c.groupClient.DismissGroup(ctx, groupID, true); err != nil {
|
||||
if err = c.groupRpcClient.DismissGroup(ctx, groupID); err != nil {
|
||||
log.ZError(ctx, "DismissGroup Notification clear members", err, "groupID", groupID)
|
||||
}
|
||||
}(groupID)
|
||||
@@ -373,7 +353,10 @@ func (c *ConsumerHandler) offlinePushMsg(ctx context.Context, msg *sdkws.MsgData
|
||||
|
||||
func (c *ConsumerHandler) filterGroupMessageOfflinePush(ctx context.Context, groupID string, msg *sdkws.MsgData,
|
||||
offlinePushUserIDs []string) (userIDs []string, err error) {
|
||||
needOfflinePushUserIDs, err := c.conversationClient.GetConversationOfflinePushUserIDs(ctx, conversationutil.GenGroupConversationID(groupID), offlinePushUserIDs)
|
||||
|
||||
//todo local cache Obtain the difference set through local comparison.
|
||||
needOfflinePushUserIDs, err := c.conversationRpcClient.GetConversationOfflinePushUserIDs(
|
||||
ctx, conversationutil.GenGroupConversationID(groupID), offlinePushUserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -427,11 +410,12 @@ func (c *ConsumerHandler) getOfflinePushInfos(msg *sdkws.MsgData) (title, conten
|
||||
|
||||
func (c *ConsumerHandler) DeleteMemberAndSetConversationSeq(ctx context.Context, groupID string, userIDs []string) error {
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := c.msgClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
maxSeq, err := c.msgRpcClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.conversationClient.SetConversationMaxSeq(ctx, conversationID, userIDs, maxSeq)
|
||||
|
||||
return c.conversationRpcClient.SetConversationMaxSeq(ctx, userIDs, conversationID, maxSeq)
|
||||
}
|
||||
|
||||
func unmarshalNotificationElem(bytes []byte, t any) error {
|
||||
@@ -439,5 +423,6 @@ func unmarshalNotificationElem(bytes []byte, t any) error {
|
||||
if err := json.Unmarshal(bytes, ¬ification); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal([]byte(notification.Detail), t)
|
||||
}
|
||||
|
||||
+13
-18
@@ -18,8 +18,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
redis2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
@@ -30,6 +28,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
pbauth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
@@ -43,9 +42,9 @@ import (
|
||||
type authServer struct {
|
||||
pbauth.UnimplementedAuthServer
|
||||
authDatabase controller.AuthDatabase
|
||||
userRpcClient *rpcclient.UserRpcClient
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry
|
||||
config *Config
|
||||
userClient *rpcli.UserClient
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -60,11 +59,9 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
pbauth.RegisterAuthServer(server, &authServer{
|
||||
userRpcClient: &userRpcClient,
|
||||
RegisterCenter: client,
|
||||
authDatabase: controller.NewAuthDatabase(
|
||||
redis2.NewTokenCacheModel(rdb, config.RpcConfig.TokenPolicy.Expire),
|
||||
@@ -73,8 +70,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
config.Share.MultiLogin,
|
||||
config.Share.IMAdminUserID,
|
||||
),
|
||||
config: config,
|
||||
userClient: rpcli.NewUserClient(userConn),
|
||||
config: config,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -90,7 +86,7 @@ func (s *authServer) GetAdminToken(ctx context.Context, req *pbauth.GetAdminToke
|
||||
|
||||
}
|
||||
|
||||
if err := s.userClient.CheckUser(ctx, []string{req.UserID}); err != nil {
|
||||
if _, err := s.userRpcClient.GetUserInfo(ctx, req.UserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -119,13 +115,9 @@ func (s *authServer) GetUserToken(ctx context.Context, req *pbauth.GetUserTokenR
|
||||
if authverify.IsManagerUserID(req.UserID, s.config.Share.IMAdminUserID) {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("don't get Admin token")
|
||||
}
|
||||
user, err := s.userClient.GetUserInfo(ctx, req.UserID)
|
||||
if err != nil {
|
||||
if _, err := s.userRpcClient.GetUserInfo(ctx, req.UserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user.AppMangerLevel >= constant.AppNotificationAdmin {
|
||||
return nil, errs.ErrArgs.WrapMsg("app account can`t get token")
|
||||
}
|
||||
token, err := s.authDatabase.CreateToken(ctx, req.UserID, int(req.PlatformID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -138,7 +130,7 @@ func (s *authServer) GetUserToken(ctx context.Context, req *pbauth.GetUserTokenR
|
||||
func (s *authServer) parseToken(ctx context.Context, tokensString string) (claims *tokenverify.Claims, err error) {
|
||||
claims, err = tokenverify.GetClaimFromToken(tokensString, authverify.Secret(s.config.Share.Secret))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
isAdmin := authverify.IsManagerUserID(claims.UserID, s.config.Share.IMAdminUserID)
|
||||
if isAdmin {
|
||||
@@ -164,7 +156,10 @@ func (s *authServer) parseToken(ctx context.Context, tokensString string) (claim
|
||||
return nil, servererrs.ErrTokenNotExist.Wrap()
|
||||
}
|
||||
|
||||
func (s *authServer) ParseToken(ctx context.Context, req *pbauth.ParseTokenReq) (resp *pbauth.ParseTokenResp, err error) {
|
||||
func (s *authServer) ParseToken(
|
||||
ctx context.Context,
|
||||
req *pbauth.ParseTokenReq,
|
||||
) (resp *pbauth.ParseTokenResp, err error) {
|
||||
resp = &pbauth.ParseTokenResp{}
|
||||
claims, err := s.parseToken(ctx, req.Token)
|
||||
if err != nil {
|
||||
@@ -192,7 +187,7 @@ func (s *authServer) forceKickOff(ctx context.Context, userID string, platformID
|
||||
return err
|
||||
}
|
||||
for _, v := range conns {
|
||||
log.ZDebug(ctx, "forceKickOff", "userID", userID, "platformID", platformID)
|
||||
log.ZDebug(ctx, "forceKickOff", "conn", v.Target())
|
||||
client := msggateway.NewMsgGatewayClient(v)
|
||||
kickReq := &msggateway.KickUserOfflineReq{KickUserIDList: []string{userID}, PlatformID: platformID}
|
||||
_, err := client.KickUserOffline(ctx, kickReq)
|
||||
|
||||
@@ -16,23 +16,23 @@ package conversation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
pbmsg "github.com/openimsdk/protocol/msg"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
dbModel "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -46,14 +46,13 @@ import (
|
||||
|
||||
type conversationServer struct {
|
||||
pbconversation.UnimplementedConversationServer
|
||||
msgRpcClient *rpcclient.MessageRpcClient
|
||||
user *rpcclient.UserRpcClient
|
||||
groupRpcClient *rpcclient.GroupRpcClient
|
||||
conversationDatabase controller.ConversationDatabase
|
||||
|
||||
conversationNotificationSender *ConversationNotificationSender
|
||||
config *Config
|
||||
|
||||
userClient *rpcli.UserClient
|
||||
msgClient *rpcli.MsgClient
|
||||
groupClient *rpcli.GroupClient
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -79,27 +78,17 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgClient := rpcli.NewMsgClient(msgConn)
|
||||
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
pbconversation.RegisterConversationServer(server, &conversationServer{
|
||||
conversationNotificationSender: NewConversationNotificationSender(&config.NotificationConfig, msgClient),
|
||||
msgRpcClient: &msgRpcClient,
|
||||
user: &userRpcClient,
|
||||
conversationNotificationSender: NewConversationNotificationSender(&config.NotificationConfig, &msgRpcClient),
|
||||
groupRpcClient: &groupRpcClient,
|
||||
conversationDatabase: controller.NewConversationDatabase(conversationDB,
|
||||
redis.NewConversationRedis(rdb, &config.LocalCacheConfig, redis.GetRocksCacheOptions(), conversationDB), mgocli.GetTx()),
|
||||
userClient: rpcli.NewUserClient(userConn),
|
||||
groupClient: rpcli.NewGroupClient(groupConn),
|
||||
msgClient: msgClient,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -136,12 +125,13 @@ func (c *conversationServer) GetSortedConversationList(ctx context.Context, req
|
||||
if len(conversations) == 0 {
|
||||
return nil, errs.ErrRecordNotFound.Wrap()
|
||||
}
|
||||
maxSeqs, err := c.msgClient.GetMaxSeqs(ctx, conversationIDs)
|
||||
|
||||
maxSeqs, err := c.msgRpcClient.GetMaxSeqs(ctx, conversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chatLogs, err := c.msgClient.GetMsgByConversationIDs(ctx, conversationIDs, maxSeqs)
|
||||
chatLogs, err := c.msgRpcClient.GetMsgByConversationIDs(ctx, conversationIDs, maxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -151,7 +141,7 @@ func (c *conversationServer) GetSortedConversationList(ctx context.Context, req
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasReadSeqs, err := c.msgClient.GetHasReadSeqs(ctx, conversationIDs, req.UserID)
|
||||
hasReadSeqs, err := c.msgRpcClient.GetHasReadSeqs(ctx, req.UserID, conversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -168,18 +158,7 @@ func (c *conversationServer) GetSortedConversationList(ctx context.Context, req
|
||||
conversation_notPinTime := make(map[int64]string)
|
||||
for _, v := range conversations {
|
||||
conversationID := v.ConversationID
|
||||
var time int64
|
||||
if _, ok := conversationMsg[conversationID]; ok {
|
||||
time = conversationMsg[conversationID].MsgInfo.LatestMsgRecvTime
|
||||
} else {
|
||||
conversationMsg[conversationID] = &pbconversation.ConversationElem{
|
||||
ConversationID: conversationID,
|
||||
IsPinned: v.IsPinned,
|
||||
MsgInfo: nil,
|
||||
}
|
||||
time = v.CreateTime.UnixMilli()
|
||||
}
|
||||
|
||||
time := conversationMsg[conversationID].MsgInfo.LatestMsgRecvTime
|
||||
conversationMsg[conversationID].RecvMsgOpt = v.RecvMsgOpt
|
||||
if v.IsPinned {
|
||||
conversationMsg[conversationID].IsPinned = v.IsPinned
|
||||
@@ -231,7 +210,6 @@ func (c *conversationServer) getConversations(ctx context.Context, ownerUserID s
|
||||
return convert.ConversationsDB2Pb(conversations), nil
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func (c *conversationServer) SetConversation(ctx context.Context, req *pbconversation.SetConversationReq) (*pbconversation.SetConversationResp, error) {
|
||||
var conversation dbModel.Conversation
|
||||
if err := datautil.CopyStructFields(&conversation, req.Conversation); err != nil {
|
||||
@@ -252,7 +230,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
|
||||
}
|
||||
|
||||
if req.Conversation.ConversationType == constant.WriteGroupChatType {
|
||||
groupInfo, err := c.groupClient.GetGroupInfo(ctx, req.Conversation.GroupID)
|
||||
groupInfo, err := c.groupRpcClient.GetGroupInfo(ctx, req.Conversation.GroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -376,15 +354,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
|
||||
needUpdateUsersList = append(needUpdateUsersList, userID)
|
||||
}
|
||||
}
|
||||
if len(m) != 0 && len(needUpdateUsersList) != 0 {
|
||||
if err := c.conversationDatabase.SetUsersConversationFieldTx(ctx, needUpdateUsersList, &conversation, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range needUpdateUsersList {
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, v, []string{req.Conversation.ConversationID})
|
||||
}
|
||||
}
|
||||
if req.Conversation.IsPrivateChat != nil && req.Conversation.ConversationType != constant.ReadGroupChatType {
|
||||
var conversations []*dbModel.Conversation
|
||||
for _, ownerUserID := range req.UserIDs {
|
||||
@@ -402,6 +372,16 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
|
||||
c.conversationNotificationSender.ConversationSetPrivateNotification(ctx, userID, req.Conversation.UserID,
|
||||
req.Conversation.IsPrivateChat.Value, req.Conversation.ConversationID)
|
||||
}
|
||||
} else {
|
||||
if len(m) != 0 && len(needUpdateUsersList) != 0 {
|
||||
if err := c.conversationDatabase.SetUsersConversationFieldTx(ctx, needUpdateUsersList, &conversation, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range needUpdateUsersList {
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, v, []string{req.Conversation.ConversationID})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &pbconversation.SetConversationsResp{}, nil
|
||||
@@ -456,14 +436,14 @@ func (c *conversationServer) CreateGroupChatConversations(ctx context.Context, r
|
||||
return nil, err
|
||||
}
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, req.GroupID)
|
||||
if err := c.msgClient.SetUserConversationMaxSeq(ctx, conversationID, req.UserIDs, 0); err != nil {
|
||||
if _, err := c.msgRpcClient.Client.SetUserConversationMaxSeq(ctx, &pbmsg.SetUserConversationMaxSeqReq{ConversationID: conversationID, OwnerUserID: req.UserIDs, MaxSeq: 0}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pbconversation.CreateGroupChatConversationsResp{}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbconversation.SetConversationMaxSeqReq) (*pbconversation.SetConversationMaxSeqResp, error) {
|
||||
if err := c.msgClient.SetUserConversationMaxSeq(ctx, req.ConversationID, req.OwnerUserID, req.MaxSeq); err != nil {
|
||||
if _, err := c.msgRpcClient.Client.SetUserConversationMaxSeq(ctx, &pbmsg.SetUserConversationMaxSeqReq{ConversationID: req.ConversationID, OwnerUserID: req.OwnerUserID, MaxSeq: req.MaxSeq}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.OwnerUserID, req.ConversationID,
|
||||
@@ -477,7 +457,7 @@ func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbc
|
||||
}
|
||||
|
||||
func (c *conversationServer) SetConversationMinSeq(ctx context.Context, req *pbconversation.SetConversationMinSeqReq) (*pbconversation.SetConversationMinSeqResp, error) {
|
||||
if err := c.msgClient.SetUserConversationMin(ctx, req.ConversationID, req.OwnerUserID, req.MinSeq); err != nil {
|
||||
if _, err := c.msgRpcClient.Client.SetUserConversationMinSeq(ctx, &pbmsg.SetUserConversationMinSeqReq{ConversationID: req.ConversationID, OwnerUserID: req.OwnerUserID, MinSeq: req.MinSeq}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.OwnerUserID, req.ConversationID,
|
||||
@@ -587,7 +567,7 @@ func (c *conversationServer) getConversationInfo(
|
||||
}
|
||||
}
|
||||
if len(sendIDs) != 0 {
|
||||
sendInfos, err := c.userClient.GetUsersInfo(ctx, sendIDs)
|
||||
sendInfos, err := c.user.GetUsersInfo(ctx, sendIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -596,7 +576,7 @@ func (c *conversationServer) getConversationInfo(
|
||||
}
|
||||
}
|
||||
if len(groupIDs) != 0 {
|
||||
groupInfos, err := c.groupClient.GetGroupsInfo(ctx, groupIDs)
|
||||
groupInfos, err := c.groupRpcClient.GetGroupInfos(ctx, groupIDs, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -773,51 +753,3 @@ func (c *conversationServer) GetPinnedConversationIDs(ctx context.Context, req *
|
||||
}
|
||||
return &pbconversation.GetPinnedConversationIDsResp{ConversationIDs: conversationIDs}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) ClearUserConversationMsg(ctx context.Context, req *pbconversation.ClearUserConversationMsgReq) (*pbconversation.ClearUserConversationMsgResp, error) {
|
||||
conversations, err := c.conversationDatabase.FindRandConversation(ctx, req.Timestamp, int(req.Limit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
latestMsgDestructTime := time.UnixMilli(req.Timestamp)
|
||||
for i, conversation := range conversations {
|
||||
if conversation.IsMsgDestruct == false || conversation.MsgDestructTime == 0 {
|
||||
continue
|
||||
}
|
||||
seq, err := c.msgClient.GetLastMessageSeqByTime(ctx, conversation.ConversationID, req.Timestamp-(conversation.MsgDestructTime*1000))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if seq <= 0 {
|
||||
log.ZDebug(ctx, "ClearUserConversationMsg GetLastMessageSeqByTime seq <= 0", "index", i, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID, "msgDestructTime", conversation.MsgDestructTime, "seq", seq)
|
||||
if err := c.setConversationMinSeqAndLatestMsgDestructTime(ctx, conversation.ConversationID, conversation.OwnerUserID, -1, latestMsgDestructTime); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
seq++
|
||||
if err := c.setConversationMinSeqAndLatestMsgDestructTime(ctx, conversation.ConversationID, conversation.OwnerUserID, seq, latestMsgDestructTime); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "ClearUserConversationMsg set min seq", "index", i, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID, "seq", seq, "msgDestructTime", conversation.MsgDestructTime)
|
||||
}
|
||||
return &pbconversation.ClearUserConversationMsgResp{Count: int32(len(conversations))}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) setConversationMinSeqAndLatestMsgDestructTime(ctx context.Context, conversationID string, ownerUserID string, minSeq int64, latestMsgDestructTime time.Time) error {
|
||||
update := map[string]any{
|
||||
"latest_msg_destruct_time": latestMsgDestructTime,
|
||||
}
|
||||
if minSeq >= 0 {
|
||||
if err := c.msgClient.SetUserConversationMin(ctx, conversationID, []string{ownerUserID}, minSeq); err != nil {
|
||||
return err
|
||||
}
|
||||
update["min_seq"] = minSeq
|
||||
}
|
||||
|
||||
if err := c.conversationDatabase.UpdateUsersConversationField(ctx, []string{ownerUserID}, conversationID, update); err != nil {
|
||||
return err
|
||||
}
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, ownerUserID, []string{conversationID})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,23 +17,18 @@ package conversation
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
type ConversationNotificationSender struct {
|
||||
*notification.NotificationSender
|
||||
*rpcclient.NotificationSender
|
||||
}
|
||||
|
||||
func NewConversationNotificationSender(conf *config.Notification, msgClient *rpcli.MsgClient) *ConversationNotificationSender {
|
||||
return &ConversationNotificationSender{notification.NewNotificationSender(conf, notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msgClient.SendMsg(ctx, req)
|
||||
}))}
|
||||
func NewConversationNotificationSender(conf *config.Notification, msgRpcClient *rpcclient.MessageRpcClient) *ConversationNotificationSender {
|
||||
return &ConversationNotificationSender{rpcclient.NewNotificationSender(conf, rpcclient.WithRpcClient(msgRpcClient))}
|
||||
}
|
||||
|
||||
// SetPrivate invote.
|
||||
|
||||
@@ -23,7 +23,7 @@ func (c *conversationServer) GetFullOwnerConversationIDs(ctx context.Context, re
|
||||
conversationIDs = nil
|
||||
}
|
||||
return &conversation.GetFullOwnerConversationIDsResp{
|
||||
Version: uint64(vl.Version),
|
||||
Version: idHash,
|
||||
VersionID: vl.ID.Hex(),
|
||||
Equal: req.IdHash == idHash,
|
||||
ConversationIDs: conversationIDs,
|
||||
|
||||
@@ -33,9 +33,6 @@ func (s *groupServer) GetGroupInfoCache(ctx context.Context, req *pbgroup.GetGro
|
||||
}
|
||||
|
||||
func (s *groupServer) GetGroupMemberCache(ctx context.Context, req *pbgroup.GetGroupMemberCacheReq) (*pbgroup.GetGroupMemberCacheResp, error) {
|
||||
if err := s.checkAdminOrInGroup(ctx, req.GroupID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
members, err := s.db.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -16,7 +16,6 @@ package group
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
pbgroup "github.com/openimsdk/protocol/group"
|
||||
@@ -56,52 +55,41 @@ func UpdateGroupInfoMap(ctx context.Context, group *sdkws.GroupInfoForSet) map[s
|
||||
return m
|
||||
}
|
||||
|
||||
func UpdateGroupInfoExMap(ctx context.Context, group *pbgroup.SetGroupInfoExReq) (m map[string]any, normalFlag, groupNameFlag, notificationFlag bool, err error) {
|
||||
m = make(map[string]any)
|
||||
func UpdateGroupInfoExMap(ctx context.Context, group *pbgroup.SetGroupInfoExReq) (map[string]any, error) {
|
||||
m := make(map[string]any)
|
||||
|
||||
if group.GroupName != nil {
|
||||
if strings.TrimSpace(group.GroupName.Value) != "" {
|
||||
if group.GroupName.Value != "" {
|
||||
m["group_name"] = group.GroupName.Value
|
||||
groupNameFlag = true
|
||||
} else {
|
||||
return nil, normalFlag, notificationFlag, groupNameFlag, errs.ErrArgs.WrapMsg("group name is empty")
|
||||
return nil, errs.ErrArgs.WrapMsg("group name is empty")
|
||||
}
|
||||
}
|
||||
|
||||
if group.Notification != nil {
|
||||
notificationFlag = true
|
||||
group.Notification.Value = strings.TrimSpace(group.Notification.Value) // if Notification only contains spaces, set it to empty string
|
||||
|
||||
m["notification"] = group.Notification.Value
|
||||
m["notification_user_id"] = mcontext.GetOpUserID(ctx)
|
||||
m["notification_update_time"] = time.Now()
|
||||
m["notification_user_id"] = mcontext.GetOpUserID(ctx)
|
||||
}
|
||||
if group.Introduction != nil {
|
||||
m["introduction"] = group.Introduction.Value
|
||||
normalFlag = true
|
||||
}
|
||||
if group.FaceURL != nil {
|
||||
m["face_url"] = group.FaceURL.Value
|
||||
normalFlag = true
|
||||
}
|
||||
if group.NeedVerification != nil {
|
||||
m["need_verification"] = group.NeedVerification.Value
|
||||
normalFlag = true
|
||||
}
|
||||
if group.LookMemberInfo != nil {
|
||||
m["look_member_info"] = group.LookMemberInfo.Value
|
||||
normalFlag = true
|
||||
}
|
||||
if group.ApplyMemberFriend != nil {
|
||||
m["apply_member_friend"] = group.ApplyMemberFriend.Value
|
||||
normalFlag = true
|
||||
}
|
||||
if group.Ex != nil {
|
||||
m["ex"] = group.Ex.Value
|
||||
normalFlag = true
|
||||
}
|
||||
|
||||
return m, normalFlag, groupNameFlag, notificationFlag, nil
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func UpdateGroupStatusMap(status int) map[string]any {
|
||||
|
||||
+356
-436
File diff suppressed because it is too large
Load Diff
+104
-165
@@ -18,11 +18,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
@@ -31,8 +26,8 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbgroup "github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
@@ -43,6 +38,7 @@ import (
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GroupApplicationReceiver
|
||||
@@ -51,38 +47,36 @@ const (
|
||||
adminReceiver
|
||||
)
|
||||
|
||||
func NewNotificationSender(db controller.GroupDatabase, config *Config, userClient *rpcli.UserClient, msgClient *rpcli.MsgClient, conversationClient *rpcli.ConversationClient) *NotificationSender {
|
||||
return &NotificationSender{
|
||||
NotificationSender: notification.NewNotificationSender(&config.NotificationConfig,
|
||||
notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msgClient.SendMsg(ctx, req)
|
||||
}),
|
||||
notification.WithUserRpcClient(userClient.GetUserInfo),
|
||||
),
|
||||
getUsersInfo: func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error) {
|
||||
users, err := userClient.GetUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.Slice(users, func(e *sdkws.UserInfo) common_user.CommonUser { return e }), nil
|
||||
},
|
||||
func NewGroupNotificationSender(
|
||||
db controller.GroupDatabase,
|
||||
msgRpcClient *rpcclient.MessageRpcClient,
|
||||
userRpcClient *rpcclient.UserRpcClient,
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient,
|
||||
config *Config,
|
||||
fn func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error),
|
||||
) *GroupNotificationSender {
|
||||
return &GroupNotificationSender{
|
||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithRpcClient(msgRpcClient), rpcclient.WithUserRpcClient(userRpcClient)),
|
||||
getUsersInfo: fn,
|
||||
db: db,
|
||||
config: config,
|
||||
msgClient: msgClient,
|
||||
conversationClient: conversationClient,
|
||||
|
||||
conversationRpcClient: conversationRpcClient,
|
||||
msgRpcClient: msgRpcClient,
|
||||
}
|
||||
}
|
||||
|
||||
type NotificationSender struct {
|
||||
*notification.NotificationSender
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||
db controller.GroupDatabase
|
||||
config *Config
|
||||
msgClient *rpcli.MsgClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
type GroupNotificationSender struct {
|
||||
*rpcclient.NotificationSender
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error)
|
||||
db controller.GroupDatabase
|
||||
config *Config
|
||||
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient
|
||||
msgRpcClient *rpcclient.MessageRpcClient
|
||||
}
|
||||
|
||||
func (g *NotificationSender) PopulateGroupMember(ctx context.Context, members ...*model.GroupMember) error {
|
||||
func (g *GroupNotificationSender) PopulateGroupMember(ctx context.Context, members ...*model.GroupMember) error {
|
||||
if len(members) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -97,7 +91,7 @@ func (g *NotificationSender) PopulateGroupMember(ctx context.Context, members ..
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userMap := make(map[string]common_user.CommonUser)
|
||||
userMap := make(map[string]notification.CommonUser)
|
||||
for i, user := range users {
|
||||
userMap[user.GetUserID()] = users[i]
|
||||
}
|
||||
@@ -117,7 +111,7 @@ func (g *NotificationSender) PopulateGroupMember(ctx context.Context, members ..
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) {
|
||||
func (g *GroupNotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) {
|
||||
users, err := g.getUsersInfo(ctx, []string{userID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -133,7 +127,7 @@ func (g *NotificationSender) getUser(ctx context.Context, userID string) (*sdkws
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupInfo(ctx context.Context, groupID string) (*sdkws.GroupInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID string) (*sdkws.GroupInfo, error) {
|
||||
gm, err := g.db.TakeGroup(ctx, groupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -154,7 +148,7 @@ func (g *NotificationSender) getGroupInfo(ctx context.Context, groupID string) (
|
||||
return convert.Db2PbGroupInfo(gm, ownerUserID, num), nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
|
||||
members, err := g.db.FindGroupMembers(ctx, groupID, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -170,7 +164,7 @@ func (g *NotificationSender) getGroupMembers(ctx context.Context, groupID string
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupMemberMap(ctx context.Context, groupID string, userIDs []string) (map[string]*sdkws.GroupMemberFullInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupMemberMap(ctx context.Context, groupID string, userIDs []string) (map[string]*sdkws.GroupMemberFullInfo, error) {
|
||||
members, err := g.getGroupMembers(ctx, groupID, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -182,7 +176,7 @@ func (g *NotificationSender) getGroupMemberMap(ctx context.Context, groupID stri
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupMember(ctx context.Context, groupID string, userID string) (*sdkws.GroupMemberFullInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupMember(ctx context.Context, groupID string, userID string) (*sdkws.GroupMemberFullInfo, error) {
|
||||
members, err := g.getGroupMembers(ctx, groupID, []string{userID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -193,7 +187,7 @@ func (g *NotificationSender) getGroupMember(ctx context.Context, groupID string,
|
||||
return members[0], nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) {
|
||||
func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) {
|
||||
members, err := g.db.FindGroupMemberRoleLevels(ctx, groupID, []int32{constant.GroupOwner, constant.GroupAdmin})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -205,7 +199,7 @@ func (g *NotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, gr
|
||||
return datautil.Slice(members, fn), nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
|
||||
func (g *GroupNotificationSender) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
|
||||
return &sdkws.GroupMemberFullInfo{
|
||||
GroupID: member.GroupID,
|
||||
UserID: member.UserID,
|
||||
@@ -222,7 +216,7 @@ func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMember, appMang
|
||||
}
|
||||
}
|
||||
|
||||
/* func (g *NotificationSender) getUsersInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error) {
|
||||
/* func (g *GroupNotificationSender) getUsersInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error) {
|
||||
users, err := g.getUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -234,17 +228,17 @@ func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMember, appMang
|
||||
return result, nil
|
||||
} */
|
||||
|
||||
func (g *NotificationSender) fillOpUser(ctx context.Context, targetUser **sdkws.GroupMemberFullInfo, groupID string) (err error) {
|
||||
return g.fillUserByUserID(ctx, mcontext.GetOpUserID(ctx), targetUser, groupID)
|
||||
func (g *GroupNotificationSender) fillOpUser(ctx context.Context, opUser **sdkws.GroupMemberFullInfo, groupID string) (err error) {
|
||||
return g.fillOpUserByUserID(ctx, mcontext.GetOpUserID(ctx), opUser, groupID)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) fillUserByUserID(ctx context.Context, userID string, targetUser **sdkws.GroupMemberFullInfo, groupID string) error {
|
||||
if targetUser == nil {
|
||||
func (g *GroupNotificationSender) fillOpUserByUserID(ctx context.Context, userID string, opUser **sdkws.GroupMemberFullInfo, groupID string) error {
|
||||
if opUser == nil {
|
||||
return errs.ErrInternalServer.WrapMsg("**sdkws.GroupMemberFullInfo is nil")
|
||||
}
|
||||
if groupID != "" {
|
||||
if authverify.IsManagerUserID(userID, g.config.Share.IMAdminUserID) {
|
||||
*targetUser = &sdkws.GroupMemberFullInfo{
|
||||
*opUser = &sdkws.GroupMemberFullInfo{
|
||||
GroupID: groupID,
|
||||
UserID: userID,
|
||||
RoleLevel: constant.GroupAdmin,
|
||||
@@ -253,7 +247,7 @@ func (g *NotificationSender) fillUserByUserID(ctx context.Context, userID string
|
||||
} else {
|
||||
member, err := g.db.TakeGroupMember(ctx, groupID, userID)
|
||||
if err == nil {
|
||||
*targetUser = g.groupMemberDB2PB(member, 0)
|
||||
*opUser = g.groupMemberDB2PB(member, 0)
|
||||
} else if !(errors.Is(err, mongo.ErrNoDocuments) || errs.ErrRecordNotFound.Is(err)) {
|
||||
return err
|
||||
}
|
||||
@@ -263,8 +257,8 @@ func (g *NotificationSender) fillUserByUserID(ctx context.Context, userID string
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *targetUser == nil {
|
||||
*targetUser = &sdkws.GroupMemberFullInfo{
|
||||
if *opUser == nil {
|
||||
*opUser = &sdkws.GroupMemberFullInfo{
|
||||
GroupID: groupID,
|
||||
UserID: userID,
|
||||
Nickname: user.Nickname,
|
||||
@@ -272,20 +266,19 @@ func (g *NotificationSender) fillUserByUserID(ctx context.Context, userID string
|
||||
OperatorUserID: userID,
|
||||
}
|
||||
} else {
|
||||
if (*targetUser).Nickname == "" {
|
||||
(*targetUser).Nickname = user.Nickname
|
||||
if (*opUser).Nickname == "" {
|
||||
(*opUser).Nickname = user.Nickname
|
||||
}
|
||||
if (*targetUser).FaceURL == "" {
|
||||
(*targetUser).FaceURL = user.FaceURL
|
||||
if (*opUser).FaceURL == "" {
|
||||
(*opUser).FaceURL = user.FaceURL
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) setVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string) {
|
||||
func (g *GroupNotificationSender) setVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string) {
|
||||
versions := versionctx.GetVersionLog(ctx).Get()
|
||||
for i := len(versions) - 1; i >= 0; i-- {
|
||||
coll := versions[i]
|
||||
for _, coll := range versions {
|
||||
if coll.Name == collName && coll.Doc.DID == id {
|
||||
*version = uint64(coll.Doc.Version)
|
||||
*versionID = coll.Doc.ID.Hex()
|
||||
@@ -294,7 +287,7 @@ func (g *NotificationSender) setVersion(ctx context.Context, version *uint64, ve
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) setSortVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string, sortVersion *uint64) {
|
||||
func (g *GroupNotificationSender) setSortVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string, sortVersion *uint64) {
|
||||
versions := versionctx.GetVersionLog(ctx).Get()
|
||||
for _, coll := range versions {
|
||||
if coll.Name == collName && coll.Doc.DID == id {
|
||||
@@ -309,7 +302,7 @@ func (g *NotificationSender) setSortVersion(ctx context.Context, version *uint64
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips, SendMessage *bool) {
|
||||
func (g *GroupNotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -320,10 +313,10 @@ func (g *NotificationSender) GroupCreatedNotification(ctx context.Context, tips
|
||||
return
|
||||
}
|
||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupCreatedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupCreatedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupInfoSetNotification(ctx context.Context, tips *sdkws.GroupInfoSetTips) {
|
||||
func (g *GroupNotificationSender) GroupInfoSetNotification(ctx context.Context, tips *sdkws.GroupInfoSetTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -334,10 +327,10 @@ func (g *NotificationSender) GroupInfoSetNotification(ctx context.Context, tips
|
||||
return
|
||||
}
|
||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNotification, tips, notification.WithRpcGetUserName())
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNotification, tips, rpcclient.WithRpcGetUserName())
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupInfoSetNameNotification(ctx context.Context, tips *sdkws.GroupInfoSetNameTips) {
|
||||
func (g *GroupNotificationSender) GroupInfoSetNameNotification(ctx context.Context, tips *sdkws.GroupInfoSetNameTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -351,7 +344,7 @@ func (g *NotificationSender) GroupInfoSetNameNotification(ctx context.Context, t
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNameNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Context, tips *sdkws.GroupInfoSetAnnouncementTips, sendMessage *bool) {
|
||||
func (g *GroupNotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Context, tips *sdkws.GroupInfoSetAnnouncementTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -362,49 +355,16 @@ func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Co
|
||||
return
|
||||
}
|
||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetAnnouncementNotification, tips, notification.WithRpcGetUserName(), notification.WithSendMessage(sendMessage))
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetAnnouncementNotification, tips, rpcclient.WithRpcGetUserName())
|
||||
}
|
||||
|
||||
func (g *NotificationSender) uuid() string {
|
||||
return uuid.New().String()
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupRequest(ctx context.Context, groupID string, userID string) (*sdkws.GroupRequest, error) {
|
||||
request, err := g.db.TakeGroupRequest(ctx, groupID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
users, err := g.getUsersInfo(ctx, []string{userID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(users) == 0 {
|
||||
return nil, servererrs.ErrUserIDNotFound.WrapMsg(fmt.Sprintf("user %s not found", userID))
|
||||
}
|
||||
info, ok := users[0].(*sdkws.UserInfo)
|
||||
if !ok {
|
||||
info = &sdkws.UserInfo{
|
||||
UserID: users[0].GetUserID(),
|
||||
Nickname: users[0].GetNickname(),
|
||||
FaceURL: users[0].GetFaceURL(),
|
||||
Ex: users[0].GetEx(),
|
||||
}
|
||||
}
|
||||
return convert.Db2PbGroupRequest(request, info, nil), nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbgroup.JoinGroupReq, dbReq *model.GroupRequest) {
|
||||
func (g *GroupNotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbgroup.JoinGroupReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err)
|
||||
}
|
||||
}()
|
||||
request, err := g.getGroupRequest(ctx, dbReq.GroupID, dbReq.UserID)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "JoinGroupApplicationNotification getGroupRequest", err, "dbReq", dbReq)
|
||||
return
|
||||
}
|
||||
var group *sdkws.GroupInfo
|
||||
group, err = g.getGroupInfo(ctx, req.GroupID)
|
||||
if err != nil {
|
||||
@@ -420,19 +380,13 @@ func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Contex
|
||||
return
|
||||
}
|
||||
userIDs = append(userIDs, req.InviterUserID, mcontext.GetOpUserID(ctx))
|
||||
tips := &sdkws.JoinGroupApplicationTips{
|
||||
Group: group,
|
||||
Applicant: user,
|
||||
ReqMsg: req.ReqMessage,
|
||||
Uuid: g.uuid(),
|
||||
Request: request,
|
||||
}
|
||||
tips := &sdkws.JoinGroupApplicationTips{Group: group, Applicant: user, ReqMsg: req.ReqMessage}
|
||||
for _, userID := range datautil.Distinct(userIDs) {
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.JoinGroupApplicationNotification, tips)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) MemberQuitNotification(ctx context.Context, member *sdkws.GroupMemberFullInfo) {
|
||||
func (g *GroupNotificationSender) MemberQuitNotification(ctx context.Context, member *sdkws.GroupMemberFullInfo) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -449,18 +403,13 @@ func (g *NotificationSender) MemberQuitNotification(ctx context.Context, member
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), member.GroupID, constant.MemberQuitNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err)
|
||||
}
|
||||
}()
|
||||
request, err := g.getGroupRequest(ctx, req.GroupID, req.FromUserID)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "GroupApplicationAcceptedNotification getGroupRequest", err, "req", req)
|
||||
return
|
||||
}
|
||||
var group *sdkws.GroupInfo
|
||||
group, err = g.getGroupInfo(ctx, req.GroupID)
|
||||
if err != nil {
|
||||
@@ -476,15 +425,8 @@ func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Co
|
||||
if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil {
|
||||
return
|
||||
}
|
||||
uid := g.uuid()
|
||||
for _, userID := range append(userIDs, req.FromUserID) {
|
||||
tips := &sdkws.GroupApplicationAcceptedTips{
|
||||
Group: group,
|
||||
OpUser: opUser,
|
||||
HandleMsg: req.HandledMsg,
|
||||
Uuid: uid,
|
||||
Request: request,
|
||||
}
|
||||
tips := &sdkws.GroupApplicationAcceptedTips{Group: group, OpUser: opUser, HandleMsg: req.HandledMsg}
|
||||
if userID == req.FromUserID {
|
||||
tips.ReceiverAs = applicantReceiver
|
||||
} else {
|
||||
@@ -494,18 +436,13 @@ func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Co
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err)
|
||||
}
|
||||
}()
|
||||
request, err := g.getGroupRequest(ctx, req.GroupID, req.FromUserID)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "GroupApplicationAcceptedNotification getGroupRequest", err, "req", req)
|
||||
return
|
||||
}
|
||||
var group *sdkws.GroupInfo
|
||||
group, err = g.getGroupInfo(ctx, req.GroupID)
|
||||
if err != nil {
|
||||
@@ -521,15 +458,8 @@ func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Co
|
||||
if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil {
|
||||
return
|
||||
}
|
||||
uid := g.uuid()
|
||||
for _, userID := range append(userIDs, req.FromUserID) {
|
||||
tips := &sdkws.GroupApplicationRejectedTips{
|
||||
Group: group,
|
||||
OpUser: opUser,
|
||||
HandleMsg: req.HandledMsg,
|
||||
Uuid: uid,
|
||||
Request: request,
|
||||
}
|
||||
tips := &sdkws.GroupApplicationAcceptedTips{Group: group, OpUser: opUser, HandleMsg: req.HandledMsg}
|
||||
if userID == req.FromUserID {
|
||||
tips.ReceiverAs = applicantReceiver
|
||||
} else {
|
||||
@@ -539,7 +469,7 @@ func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Co
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupOwnerTransferredNotification(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) {
|
||||
func (g *GroupNotificationSender) GroupOwnerTransferredNotification(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -570,7 +500,7 @@ func (g *NotificationSender) GroupOwnerTransferredNotification(ctx context.Conte
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupOwnerTransferredNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips, SendMessage *bool) {
|
||||
func (g *GroupNotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -581,14 +511,10 @@ func (g *NotificationSender) MemberKickedNotification(ctx context.Context, tips
|
||||
return
|
||||
}
|
||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.MemberKickedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.MemberKickedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx context.Context, groupID string, SendMessage *bool, invitedOpUserID string, entrantUserID ...string) error {
|
||||
return g.groupApplicationAgreeMemberEnterNotification(ctx, groupID, SendMessage, invitedOpUserID, entrantUserID...)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) groupApplicationAgreeMemberEnterNotification(ctx context.Context, groupID string, SendMessage *bool, invitedOpUserID string, entrantUserID ...string) error {
|
||||
func (g *GroupNotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx context.Context, groupID string, invitedOpUserID string, entrantUserID ...string) error {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -598,15 +524,20 @@ func (g *NotificationSender) groupApplicationAgreeMemberEnterNotification(ctx co
|
||||
|
||||
if !g.config.RpcConfig.EnableHistoryForNewMembers {
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := g.msgClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
maxSeq, err := g.msgRpcClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.msgClient.SetUserConversationsMinSeq(ctx, conversationID, entrantUserID, maxSeq+1); err != nil {
|
||||
if _, err = g.msgRpcClient.SetUserConversationsMinSeq(ctx, &msg.SetUserConversationsMinSeqReq{
|
||||
UserIDs: entrantUserID,
|
||||
ConversationID: conversationID,
|
||||
Seq: maxSeq,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := g.conversationClient.CreateGroupChatConversations(ctx, groupID, entrantUserID); err != nil {
|
||||
|
||||
if err := g.conversationRpcClient.GroupChatFirstCreateConversation(ctx, groupID, entrantUserID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -625,22 +556,24 @@ func (g *NotificationSender) groupApplicationAgreeMemberEnterNotification(ctx co
|
||||
InvitedUserList: users,
|
||||
}
|
||||
opUserID := mcontext.GetOpUserID(ctx)
|
||||
if err = g.fillUserByUserID(ctx, opUserID, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||
if err = g.fillOpUserByUserID(ctx, opUserID, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||
return nil
|
||||
}
|
||||
if invitedOpUserID == opUserID {
|
||||
switch {
|
||||
case invitedOpUserID == "":
|
||||
case invitedOpUserID == opUserID:
|
||||
tips.InviterUser = tips.OpUser
|
||||
} else {
|
||||
if err = g.fillUserByUserID(ctx, invitedOpUserID, &tips.InviterUser, tips.Group.GroupID); err != nil {
|
||||
default:
|
||||
if err = g.fillOpUserByUserID(ctx, invitedOpUserID, &tips.InviterUser, tips.Group.GroupID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) MemberEnterNotification(ctx context.Context, groupID string, entrantUserID string) error {
|
||||
func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, groupID string, entrantUserID string) error {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -650,17 +583,23 @@ func (g *NotificationSender) MemberEnterNotification(ctx context.Context, groupI
|
||||
|
||||
if !g.config.RpcConfig.EnableHistoryForNewMembers {
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := g.msgClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
maxSeq, err := g.msgRpcClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.msgClient.SetUserConversationsMinSeq(ctx, conversationID, []string{entrantUserID}, maxSeq+1); err != nil {
|
||||
if _, err = g.msgRpcClient.SetUserConversationsMinSeq(ctx, &msg.SetUserConversationsMinSeqReq{
|
||||
UserIDs: []string{entrantUserID},
|
||||
ConversationID: conversationID,
|
||||
Seq: maxSeq,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := g.conversationClient.CreateGroupChatConversations(ctx, groupID, []string{entrantUserID}); err != nil {
|
||||
|
||||
if err := g.conversationRpcClient.GroupChatFirstCreateConversation(ctx, groupID, []string{entrantUserID}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var group *sdkws.GroupInfo
|
||||
group, err = g.getGroupInfo(ctx, groupID)
|
||||
if err != nil {
|
||||
@@ -681,7 +620,7 @@ func (g *NotificationSender) MemberEnterNotification(ctx context.Context, groupI
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupDismissedNotification(ctx context.Context, tips *sdkws.GroupDismissedTips, SendMessage *bool) {
|
||||
func (g *GroupNotificationSender) GroupDismissedNotification(ctx context.Context, tips *sdkws.GroupDismissedTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -691,10 +630,10 @@ func (g *NotificationSender) GroupDismissedNotification(ctx context.Context, tip
|
||||
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||
return
|
||||
}
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupDismissedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupDismissedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) {
|
||||
func (g *GroupNotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -722,7 +661,7 @@ func (g *NotificationSender) GroupMemberMutedNotification(ctx context.Context, g
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberCancelMutedNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberCancelMutedNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -747,7 +686,7 @@ func (g *NotificationSender) GroupMemberCancelMutedNotification(ctx context.Cont
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMutedNotification(ctx context.Context, groupID string) {
|
||||
func (g *GroupNotificationSender) GroupMutedNotification(ctx context.Context, groupID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -775,7 +714,7 @@ func (g *NotificationSender) GroupMutedNotification(ctx context.Context, groupID
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupCancelMutedNotification(ctx context.Context, groupID string) {
|
||||
func (g *GroupNotificationSender) GroupCancelMutedNotification(ctx context.Context, groupID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -803,7 +742,7 @@ func (g *NotificationSender) GroupCancelMutedNotification(ctx context.Context, g
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupCancelMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberInfoSetNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberInfoSetNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -828,7 +767,7 @@ func (g *NotificationSender) GroupMemberInfoSetNotification(ctx context.Context,
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberInfoSetNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberSetToAdminNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberSetToAdminNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -848,11 +787,11 @@ func (g *NotificationSender) GroupMemberSetToAdminNotification(ctx context.Conte
|
||||
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||
return
|
||||
}
|
||||
g.setSortVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID, &tips.GroupSortVersion)
|
||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToAdminNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -873,6 +812,6 @@ func (g *NotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx contex
|
||||
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||
return
|
||||
}
|
||||
g.setSortVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID, &tips.GroupSortVersion)
|
||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToOrdinaryUserNotification, tips)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
@@ -27,9 +26,6 @@ func (s *groupServer) GroupCreateCount(ctx context.Context, req *group.GroupCrea
|
||||
if req.Start > req.End {
|
||||
return nil, errs.ErrArgs.WrapMsg("start > end: %d > %d", req.Start, req.End)
|
||||
}
|
||||
if err := authverify.CheckAdmin(ctx, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
total, err := s.db.CountTotal(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+148
-47
@@ -2,7 +2,6 @@ package group
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/incrversion"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
@@ -14,23 +13,14 @@ import (
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
)
|
||||
|
||||
const versionSyncLimit = 500
|
||||
|
||||
func (s *groupServer) GetFullGroupMemberUserIDs(ctx context.Context, req *pbgroup.GetFullGroupMemberUserIDsReq) (*pbgroup.GetFullGroupMemberUserIDsResp, error) {
|
||||
userIDs, err := s.db.FindGroupMemberUserID(ctx, req.GroupID)
|
||||
vl, err := s.db.FindMaxGroupMemberVersionCache(ctx, req.GroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
|
||||
if !datautil.Contain(mcontext.GetOpUserID(ctx), userIDs...) {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("op user not in group")
|
||||
}
|
||||
}
|
||||
vl, err := s.db.FindMaxGroupMemberVersionCache(ctx, req.GroupID)
|
||||
userIDs, err := s.db.FindGroupMemberUserID(ctx, req.GroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -39,7 +29,7 @@ func (s *groupServer) GetFullGroupMemberUserIDs(ctx context.Context, req *pbgrou
|
||||
userIDs = nil
|
||||
}
|
||||
return &pbgroup.GetFullGroupMemberUserIDsResp{
|
||||
Version: uint64(vl.Version),
|
||||
Version: idHash,
|
||||
VersionID: vl.ID.Hex(),
|
||||
Equal: req.IdHash == idHash,
|
||||
UserIDs: userIDs,
|
||||
@@ -47,9 +37,6 @@ func (s *groupServer) GetFullGroupMemberUserIDs(ctx context.Context, req *pbgrou
|
||||
}
|
||||
|
||||
func (s *groupServer) GetFullJoinGroupIDs(ctx context.Context, req *pbgroup.GetFullJoinGroupIDsReq) (*pbgroup.GetFullJoinGroupIDsResp, error) {
|
||||
if err := authverify.CheckAccessV3(ctx, req.UserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vl, err := s.db.FindMaxJoinGroupVersionCache(ctx, req.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -63,7 +50,7 @@ func (s *groupServer) GetFullJoinGroupIDs(ctx context.Context, req *pbgroup.GetF
|
||||
groupIDs = nil
|
||||
}
|
||||
return &pbgroup.GetFullJoinGroupIDsResp{
|
||||
Version: uint64(vl.Version),
|
||||
Version: idHash,
|
||||
VersionID: vl.ID.Hex(),
|
||||
Equal: req.IdHash == idHash,
|
||||
GroupIDs: groupIDs,
|
||||
@@ -71,9 +58,6 @@ func (s *groupServer) GetFullJoinGroupIDs(ctx context.Context, req *pbgroup.GetF
|
||||
}
|
||||
|
||||
func (s *groupServer) GetIncrementalGroupMember(ctx context.Context, req *pbgroup.GetIncrementalGroupMemberReq) (*pbgroup.GetIncrementalGroupMemberResp, error) {
|
||||
if err := s.checkAdminOrInGroup(ctx, req.GroupID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
group, err := s.db.TakeGroup(ctx, req.GroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -148,6 +132,150 @@ func (s *groupServer) GetIncrementalGroupMember(ctx context.Context, req *pbgrou
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *groupServer) BatchGetIncrementalGroupMember(ctx context.Context, req *pbgroup.BatchGetIncrementalGroupMemberReq) (resp *pbgroup.BatchGetIncrementalGroupMemberResp, err error) {
|
||||
type VersionInfo struct {
|
||||
GroupID string
|
||||
VersionID string
|
||||
VersionNumber uint64
|
||||
}
|
||||
|
||||
var groupIDs []string
|
||||
|
||||
groupsVersionMap := make(map[string]*VersionInfo)
|
||||
groupsMap := make(map[string]*model.Group)
|
||||
hasGroupUpdateMap := make(map[string]bool)
|
||||
sortVersionMap := make(map[string]uint64)
|
||||
|
||||
var targetKeys, versionIDs []string
|
||||
var versionNumbers []uint64
|
||||
|
||||
var requestBodyLen int
|
||||
|
||||
for _, group := range req.ReqList {
|
||||
groupsVersionMap[group.GroupID] = &VersionInfo{
|
||||
GroupID: group.GroupID,
|
||||
VersionID: group.VersionID,
|
||||
VersionNumber: group.Version,
|
||||
}
|
||||
|
||||
groupIDs = append(groupIDs, group.GroupID)
|
||||
}
|
||||
|
||||
groups, err := s.db.FindGroup(ctx, groupIDs)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
|
||||
for _, group := range groups {
|
||||
if group.Status == constant.GroupStatusDismissed {
|
||||
err = servererrs.ErrDismissedAlready.Wrap()
|
||||
log.ZError(ctx, "This group is Dismissed Already", err, "group is", group.GroupID)
|
||||
|
||||
delete(groupsVersionMap, group.GroupID)
|
||||
} else {
|
||||
groupsMap[group.GroupID] = group
|
||||
}
|
||||
}
|
||||
|
||||
for groupID, vInfo := range groupsVersionMap {
|
||||
targetKeys = append(targetKeys, groupID)
|
||||
versionIDs = append(versionIDs, vInfo.VersionID)
|
||||
versionNumbers = append(versionNumbers, vInfo.VersionNumber)
|
||||
}
|
||||
|
||||
opt := incrversion.BatchOption[[]*sdkws.GroupMemberFullInfo, pbgroup.BatchGetIncrementalGroupMemberResp]{
|
||||
Ctx: ctx,
|
||||
TargetKeys: targetKeys,
|
||||
VersionIDs: versionIDs,
|
||||
VersionNumbers: versionNumbers,
|
||||
Versions: func(ctx context.Context, groupIDs []string, versions []uint64, limits []int) (map[string]*model.VersionLog, error) {
|
||||
vLogs, err := s.db.BatchFindMemberIncrVersion(ctx, groupIDs, versions, limits)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
|
||||
for groupID, vlog := range vLogs {
|
||||
vlogElems := make([]model.VersionLogElem, 0, len(vlog.Logs))
|
||||
for i, log := range vlog.Logs {
|
||||
switch log.EID {
|
||||
case model.VersionGroupChangeID:
|
||||
vlog.LogLen--
|
||||
hasGroupUpdateMap[groupID] = true
|
||||
case model.VersionSortChangeID:
|
||||
vlog.LogLen--
|
||||
sortVersionMap[groupID] = uint64(log.Version)
|
||||
default:
|
||||
vlogElems = append(vlogElems, vlog.Logs[i])
|
||||
}
|
||||
}
|
||||
vlog.Logs = vlogElems
|
||||
if vlog.LogLen > 0 {
|
||||
hasGroupUpdateMap[groupID] = true
|
||||
}
|
||||
}
|
||||
|
||||
return vLogs, nil
|
||||
},
|
||||
CacheMaxVersions: s.db.BatchFindMaxGroupMemberVersionCache,
|
||||
Find: func(ctx context.Context, groupID string, ids []string) ([]*sdkws.GroupMemberFullInfo, error) {
|
||||
memberInfo, err := s.getGroupMembersInfo(ctx, groupID, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return memberInfo, err
|
||||
},
|
||||
Resp: func(versions map[string]*model.VersionLog, deleteIdsMap map[string][]string, insertListMap, updateListMap map[string][]*sdkws.GroupMemberFullInfo, fullMap map[string]bool) *pbgroup.BatchGetIncrementalGroupMemberResp {
|
||||
resList := make(map[string]*pbgroup.GetIncrementalGroupMemberResp)
|
||||
|
||||
for groupID, versionLog := range versions {
|
||||
resList[groupID] = &pbgroup.GetIncrementalGroupMemberResp{
|
||||
VersionID: versionLog.ID.Hex(),
|
||||
Version: uint64(versionLog.Version),
|
||||
Full: fullMap[groupID],
|
||||
Delete: deleteIdsMap[groupID],
|
||||
Insert: insertListMap[groupID],
|
||||
Update: updateListMap[groupID],
|
||||
SortVersion: sortVersionMap[groupID],
|
||||
}
|
||||
|
||||
requestBodyLen += len(insertListMap[groupID]) + len(updateListMap[groupID]) + len(deleteIdsMap[groupID])
|
||||
if requestBodyLen > 200 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return &pbgroup.BatchGetIncrementalGroupMemberResp{
|
||||
RespList: resList,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
resp, err = opt.Build()
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
|
||||
for groupID, val := range resp.RespList {
|
||||
if val.Full || hasGroupUpdateMap[groupID] {
|
||||
count, err := s.db.FindGroupMemberNum(ctx, groupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
owner, err := s.db.TakeGroupOwner(ctx, groupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.RespList[groupID].Group = s.groupDB2PB(groupsMap[groupID], owner.UserID, count)
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *groupServer) GetIncrementalJoinGroup(ctx context.Context, req *pbgroup.GetIncrementalJoinGroupReq) (*pbgroup.GetIncrementalJoinGroupResp, error) {
|
||||
if err := authverify.CheckAccessV3(ctx, req.UserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
@@ -173,30 +301,3 @@ func (s *groupServer) GetIncrementalJoinGroup(ctx context.Context, req *pbgroup.
|
||||
}
|
||||
return opt.Build()
|
||||
}
|
||||
|
||||
func (s *groupServer) BatchGetIncrementalGroupMember(ctx context.Context, req *pbgroup.BatchGetIncrementalGroupMemberReq) (*pbgroup.BatchGetIncrementalGroupMemberResp, error) {
|
||||
var num int
|
||||
resp := make(map[string]*pbgroup.GetIncrementalGroupMemberResp)
|
||||
|
||||
for _, memberReq := range req.ReqList {
|
||||
if _, ok := resp[memberReq.GroupID]; ok {
|
||||
continue
|
||||
}
|
||||
memberResp, err := s.GetIncrementalGroupMember(ctx, memberReq)
|
||||
if err != nil {
|
||||
if errors.Is(err, servererrs.ErrDismissedAlready) {
|
||||
log.ZWarn(ctx, "Failed to get incremental group member", err, "groupID", memberReq.GroupID, "request", memberReq)
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp[memberReq.GroupID] = memberResp
|
||||
num += len(memberResp.Insert) + len(memberResp.Update) + len(memberResp.Delete)
|
||||
if num >= versionSyncLimit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return &pbgroup.BatchGetIncrementalGroupMemberResp{RespList: resp}, nil
|
||||
}
|
||||
|
||||
+116
-40
@@ -2,59 +2,135 @@ package msg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/wrapperspb"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"strings"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/openimsdk/tools/utils/idutil"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// DestructMsgs hard delete in Database.
|
||||
func (m *msgServer) DestructMsgs(ctx context.Context, req *msg.DestructMsgsReq) (*msg.DestructMsgsResp, error) {
|
||||
// hard delete in Database.
|
||||
func (m *msgServer) DestructMsgs(ctx context.Context, req *msg.DestructMsgsReq) (_ *msg.DestructMsgsResp, err error) {
|
||||
if err := authverify.CheckAdmin(ctx, m.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs, err := m.MsgDatabase.GetRandBeforeMsg(ctx, req.Timestamp, int(req.Limit))
|
||||
if req.Timestamp > time.Now().UnixMilli() {
|
||||
return nil, errs.ErrArgs.WrapMsg("request millisecond timestamp error")
|
||||
}
|
||||
var (
|
||||
docNum int
|
||||
msgNum int
|
||||
start = time.Now()
|
||||
getLimit = 5000
|
||||
)
|
||||
|
||||
destructMsg := func(ctx context.Context) (bool, error) {
|
||||
docIDs, err := m.MsgDatabase.GetDocIDs(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
msgs, err := m.MsgDatabase.GetBeforeMsg(ctx, req.Timestamp, docIDs, getLimit)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for _, msg := range msgs {
|
||||
index, err := m.MsgDatabase.DeleteDocMsgBefore(ctx, req.Timestamp, msg)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(index) == 0 {
|
||||
return false, errs.ErrInternalServer.WrapMsg("delete doc msg failed")
|
||||
}
|
||||
|
||||
docNum++
|
||||
msgNum += len(index)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
_, err = destructMsg(ctx)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "clear msg failed", err, "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start))
|
||||
return nil, err
|
||||
}
|
||||
for i, doc := range docs {
|
||||
if err := m.MsgDatabase.DeleteDoc(ctx, doc.DocID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "DestructMsgs delete doc", "index", i, "docID", doc.DocID)
|
||||
index := strings.LastIndex(doc.DocID, ":")
|
||||
if index < 0 {
|
||||
continue
|
||||
}
|
||||
var minSeq int64
|
||||
for _, model := range doc.Msg {
|
||||
if model.Msg == nil {
|
||||
continue
|
||||
}
|
||||
if model.Msg.Seq > minSeq {
|
||||
minSeq = model.Msg.Seq
|
||||
}
|
||||
}
|
||||
if minSeq <= 0 {
|
||||
continue
|
||||
}
|
||||
conversationID := doc.DocID[:index]
|
||||
if conversationID == "" {
|
||||
continue
|
||||
}
|
||||
minSeq++
|
||||
if err := m.MsgDatabase.SetMinSeq(ctx, conversationID, minSeq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "DestructMsgs delete doc set min seq", "index", i, "docID", doc.DocID, "conversationID", conversationID, "setMinSeq", minSeq)
|
||||
}
|
||||
return &msg.DestructMsgsResp{Count: int32(len(docs))}, nil
|
||||
|
||||
log.ZDebug(ctx, "clearing message", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start))
|
||||
|
||||
return &msg.DestructMsgsResp{}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) GetLastMessageSeqByTime(ctx context.Context, req *msg.GetLastMessageSeqByTimeReq) (*msg.GetLastMessageSeqByTimeResp, error) {
|
||||
seq, err := m.MsgDatabase.GetLastMessageSeqByTime(ctx, req.ConversationID, req.Time)
|
||||
if err != nil {
|
||||
// soft delete for user self
|
||||
func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.ClearMsgResp, err error) {
|
||||
temp := convert.ConversationsPb2DB(req.Conversations)
|
||||
|
||||
batchNum := 100
|
||||
|
||||
errg, _ := errgroup.WithContext(ctx)
|
||||
errg.SetLimit(100)
|
||||
|
||||
for i := 0; i < len(temp); i += batchNum {
|
||||
batch := temp[i:min(i+batchNum, len(temp))]
|
||||
|
||||
errg.Go(func() error {
|
||||
for _, conversation := range batch {
|
||||
handleCtx := mcontext.NewCtx(stringutil.GetSelfFuncName() + "-" + idutil.OperationIDGenerator() + "-" + conversation.ConversationID + "-" + conversation.OwnerUserID)
|
||||
log.ZDebug(handleCtx, "User MsgsDestruct",
|
||||
"conversationID", conversation.ConversationID,
|
||||
"ownerUserID", conversation.OwnerUserID,
|
||||
"msgDestructTime", conversation.MsgDestructTime,
|
||||
"lastMsgDestructTime", conversation.LatestMsgDestructTime)
|
||||
|
||||
seqs, err := m.MsgDatabase.ClearUserMsgs(handleCtx, conversation.OwnerUserID, conversation.ConversationID, conversation.MsgDestructTime, conversation.LatestMsgDestructTime)
|
||||
if err != nil {
|
||||
log.ZError(handleCtx, "user msg destruct failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(seqs) > 0 {
|
||||
minseq := datautil.Max(seqs...)
|
||||
|
||||
// update
|
||||
if err := m.Conversation.UpdateConversation(handleCtx,
|
||||
&pbconversation.UpdateConversationReq{
|
||||
UserIDs: []string{conversation.OwnerUserID},
|
||||
ConversationID: conversation.ConversationID,
|
||||
LatestMsgDestructTime: wrapperspb.Int64(time.Now().UnixMilli()),
|
||||
MinSeq: wrapperspb.Int64(minseq),
|
||||
}); err != nil {
|
||||
log.ZError(handleCtx, "updateUsersConversationField failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := m.Conversation.SetConversationMinSeq(handleCtx, []string{conversation.OwnerUserID}, conversation.ConversationID, minseq); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if you need Notify SDK client userseq is update.
|
||||
// m.msgNotificationSender.UserDeleteMsgsNotification(handleCtx, conversation.OwnerUserID, conversation.ConversationID, seqs)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msg.GetLastMessageSeqByTimeResp{Seq: seq}, nil
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -74,13 +74,19 @@ func (m *msgServer) DeleteMsgs(ctx context.Context, req *msg.DeleteMsgsReq) (*ms
|
||||
if err := m.MsgDatabase.DeleteMsgsPhysicalBySeqs(ctx, req.ConversationID, req.Seqs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conv, err := m.conversationClient.GetConversationsByConversationID(ctx, req.ConversationID)
|
||||
conversations, err := m.Conversation.GetConversationsByConversationID(ctx, []string{req.ConversationID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tips := &sdkws.DeleteMsgsTips{UserID: req.UserID, ConversationID: req.ConversationID, Seqs: req.Seqs}
|
||||
m.notificationSender.NotificationWithSessionType(ctx, req.UserID, m.conversationAndGetRecvID(conv, req.UserID),
|
||||
constant.DeleteMsgsNotification, conv.ConversationType, tips)
|
||||
m.notificationSender.NotificationWithSessionType(
|
||||
ctx,
|
||||
req.UserID,
|
||||
m.conversationAndGetRecvID(conversations[0], req.UserID),
|
||||
constant.DeleteMsgsNotification,
|
||||
conversations[0].ConversationType,
|
||||
tips,
|
||||
)
|
||||
} else {
|
||||
if err := m.MsgDatabase.DeleteUserMsgsBySeqs(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil {
|
||||
return nil, err
|
||||
@@ -106,14 +112,16 @@ func (m *msgServer) DeleteMsgPhysical(ctx context.Context, req *msg.DeleteMsgPhy
|
||||
return nil, err
|
||||
}
|
||||
remainTime := timeutil.GetCurrentTimestampBySecond() - req.Timestamp
|
||||
if _, err := m.DestructMsgs(ctx, &msg.DestructMsgsReq{Timestamp: remainTime, Limit: 9999}); err != nil {
|
||||
return nil, err
|
||||
for _, conversationID := range req.ConversationIDs {
|
||||
if err := m.MsgDatabase.DeleteConversationMsgsAndSetMinSeq(ctx, conversationID, remainTime); err != nil {
|
||||
log.ZWarn(ctx, "DeleteConversationMsgsAndSetMinSeq error", err, "conversationID", conversationID, "err", err)
|
||||
}
|
||||
}
|
||||
return &msg.DeleteMsgPhysicalResp{}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) clearConversation(ctx context.Context, conversationIDs []string, userID string, deleteSyncOpt *msg.DeleteSyncOpt) error {
|
||||
conversations, err := m.conversationClient.GetConversationsByConversationIDs(ctx, conversationIDs)
|
||||
conversations, err := m.Conversation.GetConversationsByConversationID(ctx, conversationIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -136,7 +144,7 @@ func (m *msgServer) clearConversation(ctx context.Context, conversationIDs []str
|
||||
}
|
||||
ownerUserIDs := []string{userID}
|
||||
for conversationID, seq := range setSeqs {
|
||||
if err := m.conversationClient.SetConversationMinSeq(ctx, conversationID, ownerUserIDs, seq); err != nil {
|
||||
if err := m.Conversation.SetConversationMinSeq(ctx, ownerUserIDs, conversationID, seq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,17 @@ package msg
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
type MsgNotificationSender struct {
|
||||
*notification.NotificationSender
|
||||
*rpcclient.NotificationSender
|
||||
}
|
||||
|
||||
func NewMsgNotificationSender(config *Config, opts ...notification.NotificationSenderOptions) *MsgNotificationSender {
|
||||
return &MsgNotificationSender{notification.NewNotificationSender(&config.NotificationConfig, opts...)}
|
||||
func NewMsgNotificationSender(config *Config, opts ...rpcclient.NotificationSenderOptions) *MsgNotificationSender {
|
||||
return &MsgNotificationSender{rpcclient.NewNotificationSender(&config.NotificationConfig, opts...)}
|
||||
}
|
||||
|
||||
func (m *MsgNotificationSender) UserDeleteMsgsNotification(ctx context.Context, userID, conversationID string, seqs []int64) {
|
||||
|
||||
@@ -17,9 +17,8 @@ package msg
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
@@ -64,8 +63,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
|
||||
log.ZDebug(ctx, "GetMsgBySeqs", "conversationID", req.ConversationID, "seq", req.Seq, "msg", string(data))
|
||||
var role int32
|
||||
if !authverify.IsAppManagerUid(ctx, m.config.Share.IMAdminUserID) {
|
||||
sessionType := msgs[0].SessionType
|
||||
switch sessionType {
|
||||
switch msgs[0].SessionType {
|
||||
case constant.SingleChatType:
|
||||
if err := authverify.CheckAccessV3(ctx, msgs[0].SendID, m.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
@@ -80,10 +78,8 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
|
||||
switch members[req.UserID].RoleLevel {
|
||||
case constant.GroupOwner:
|
||||
case constant.GroupAdmin:
|
||||
if sendMember, ok := members[msgs[0].SendID]; ok {
|
||||
if sendMember.RoleLevel != constant.GroupOrdinaryUsers {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("no permission")
|
||||
}
|
||||
if members[msgs[0].SendID].RoleLevel != constant.GroupOrdinaryUsers {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("no permission")
|
||||
}
|
||||
default:
|
||||
return nil, errs.ErrNoPermission.WrapMsg("no permission")
|
||||
@@ -93,7 +89,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
|
||||
role = member.RoleLevel
|
||||
}
|
||||
default:
|
||||
return nil, errs.ErrInternalServer.WrapMsg("msg sessionType not supported", "sessionType", sessionType)
|
||||
return nil, errs.ErrInternalServer.WrapMsg("msg sessionType not supported")
|
||||
}
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
+16
-16
@@ -83,7 +83,7 @@ func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgDa
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.ZPanic(nctx, "setConversationAtInfo Panic", errs.ErrPanic(r))
|
||||
log.ZPanic(nctx, "setConversationAtInfo Panic", r)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -96,14 +96,14 @@ func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgDa
|
||||
ConversationType: msg.SessionType,
|
||||
GroupID: msg.GroupID,
|
||||
}
|
||||
memberUserIDList, err := m.GroupLocalCache.GetGroupMemberIDs(ctx, msg.GroupID)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "GetGroupMemberIDs", err)
|
||||
return
|
||||
}
|
||||
|
||||
tagAll := datautil.Contain(constant.AtAllString, msg.AtUserIDList...)
|
||||
if tagAll {
|
||||
memberUserIDList, err := m.GroupLocalCache.GetGroupMemberIDs(ctx, msg.GroupID)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "GetGroupMemberIDs", err)
|
||||
return
|
||||
}
|
||||
|
||||
memberUserIDList = datautil.DeleteElems(memberUserIDList, msg.SendID)
|
||||
|
||||
@@ -113,29 +113,29 @@ func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgDa
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAll}
|
||||
} else { // @Everyone and @other people
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAllAtMe}
|
||||
atUserID = datautil.SliceIntersectFuncs(atUserID, memberUserIDList, func(a string) string { return a }, func(b string) string {
|
||||
return b
|
||||
})
|
||||
if err := m.conversationClient.SetConversations(ctx, atUserID, conversation); err != nil {
|
||||
|
||||
err = m.Conversation.SetConversations(ctx, atUserID, conversation)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, "userID", atUserID, "conversation", conversation)
|
||||
}
|
||||
|
||||
memberUserIDList = datautil.Single(atUserID, memberUserIDList)
|
||||
}
|
||||
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAll}
|
||||
if err := m.conversationClient.SetConversations(ctx, memberUserIDList, conversation); err != nil {
|
||||
|
||||
err = m.Conversation.SetConversations(ctx, memberUserIDList, conversation)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, "userID", memberUserIDList, "conversation", conversation)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
atUserID = datautil.SliceIntersectFuncs(msg.AtUserIDList, memberUserIDList, func(a string) string { return a }, func(b string) string {
|
||||
return b
|
||||
})
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtMe}
|
||||
|
||||
if err := m.conversationClient.SetConversations(ctx, atUserID, conversation); err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, atUserID, conversation)
|
||||
err := m.Conversation.SetConversations(ctx, msg.AtUserIDList, conversation)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, msg.AtUserIDList, conversation)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+51
-58
@@ -16,10 +16,6 @@ package msg
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
||||
@@ -30,6 +26,7 @@ import (
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
@@ -38,38 +35,39 @@ import (
|
||||
)
|
||||
|
||||
type MessageInterceptorFunc func(ctx context.Context, globalConfig *Config, req *msg.SendMsgReq) (*sdkws.MsgData, error)
|
||||
type (
|
||||
// MessageInterceptorChain defines a chain of message interceptor functions.
|
||||
MessageInterceptorChain []MessageInterceptorFunc
|
||||
|
||||
// MessageInterceptorChain defines a chain of message interceptor functions.
|
||||
type MessageInterceptorChain []MessageInterceptorFunc
|
||||
// MsgServer encapsulates dependencies required for message handling.
|
||||
msgServer struct {
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry // Service discovery registry for service registration.
|
||||
MsgDatabase controller.CommonMsgDatabase // Interface for message database operations.
|
||||
Conversation *rpcclient.ConversationRpcClient // RPC client for conversation service.
|
||||
UserLocalCache *rpccache.UserLocalCache // Local cache for user data.
|
||||
FriendLocalCache *rpccache.FriendLocalCache // Local cache for friend data.
|
||||
GroupLocalCache *rpccache.GroupLocalCache // Local cache for group data.
|
||||
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
|
||||
Handlers MessageInterceptorChain // Chain of handlers for processing messages.
|
||||
notificationSender *rpcclient.NotificationSender // RPC client for sending notifications.
|
||||
msgNotificationSender *MsgNotificationSender // RPC client for sending msg notifications.
|
||||
config *Config // Global configuration settings.
|
||||
webhookClient *webhook.Client
|
||||
msg.UnimplementedMsgServer
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
RpcConfig config.Msg
|
||||
RedisConfig config.Redis
|
||||
MongodbConfig config.Mongo
|
||||
KafkaConfig config.Kafka
|
||||
NotificationConfig config.Notification
|
||||
Share config.Share
|
||||
WebhooksConfig config.Webhooks
|
||||
LocalCacheConfig config.LocalCache
|
||||
Discovery config.Discovery
|
||||
}
|
||||
|
||||
// MsgServer encapsulates dependencies required for message handling.
|
||||
type msgServer struct {
|
||||
msg.UnimplementedMsgServer
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry // Service discovery registry for service registration.
|
||||
MsgDatabase controller.CommonMsgDatabase // Interface for message database operations.
|
||||
UserLocalCache *rpccache.UserLocalCache // Local cache for user data.
|
||||
FriendLocalCache *rpccache.FriendLocalCache // Local cache for friend data.
|
||||
GroupLocalCache *rpccache.GroupLocalCache // Local cache for group data.
|
||||
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
|
||||
Handlers MessageInterceptorChain // Chain of handlers for processing messages.
|
||||
notificationSender *notification.NotificationSender // RPC client for sending notifications.
|
||||
msgNotificationSender *MsgNotificationSender // RPC client for sending msg notifications.
|
||||
config *Config // Global configuration settings.
|
||||
webhookClient *webhook.Client
|
||||
conversationClient *rpcli.ConversationClient
|
||||
}
|
||||
Config struct {
|
||||
RpcConfig config.Msg
|
||||
RedisConfig config.Redis
|
||||
MongodbConfig config.Mongo
|
||||
KafkaConfig config.Kafka
|
||||
NotificationConfig config.Notification
|
||||
Share config.Share
|
||||
WebhooksConfig config.Webhooks
|
||||
LocalCacheConfig config.LocalCache
|
||||
Discovery config.Discovery
|
||||
}
|
||||
)
|
||||
|
||||
func (m *msgServer) addInterceptorHandler(interceptorFunc ...MessageInterceptorFunc) {
|
||||
m.Handlers = append(m.Handlers, interceptorFunc...)
|
||||
@@ -89,7 +87,11 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgModel := redis.NewMsgCache(rdb, msgDocModel)
|
||||
msgModel := redis.NewMsgCache(rdb)
|
||||
conversationClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
friendRpcClient := rpcclient.NewFriendRpcClient(client, config.Share.RpcRegisterName.Friend)
|
||||
seqConversation, err := mgo.NewSeqConversationMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -104,37 +106,20 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conversationClient := rpcli.NewConversationClient(conversationConn)
|
||||
s := &msgServer{
|
||||
Conversation: &conversationClient,
|
||||
MsgDatabase: msgDatabase,
|
||||
RegisterCenter: client,
|
||||
UserLocalCache: rpccache.NewUserLocalCache(rpcli.NewUserClient(userConn), &config.LocalCacheConfig, rdb),
|
||||
GroupLocalCache: rpccache.NewGroupLocalCache(rpcli.NewGroupClient(groupConn), &config.LocalCacheConfig, rdb),
|
||||
UserLocalCache: rpccache.NewUserLocalCache(userRpcClient, &config.LocalCacheConfig, rdb),
|
||||
GroupLocalCache: rpccache.NewGroupLocalCache(groupRpcClient, &config.LocalCacheConfig, rdb),
|
||||
ConversationLocalCache: rpccache.NewConversationLocalCache(conversationClient, &config.LocalCacheConfig, rdb),
|
||||
FriendLocalCache: rpccache.NewFriendLocalCache(rpcli.NewRelationClient(friendConn), &config.LocalCacheConfig, rdb),
|
||||
FriendLocalCache: rpccache.NewFriendLocalCache(friendRpcClient, &config.LocalCacheConfig, rdb),
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
conversationClient: conversationClient,
|
||||
}
|
||||
|
||||
s.notificationSender = notification.NewNotificationSender(&config.NotificationConfig, notification.WithLocalSendMsg(s.SendMsg))
|
||||
s.msgNotificationSender = NewMsgNotificationSender(config, notification.WithLocalSendMsg(s.SendMsg))
|
||||
s.notificationSender = rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithLocalSendMsg(s.SendMsg))
|
||||
s.msgNotificationSender = NewMsgNotificationSender(config, rpcclient.WithLocalSendMsg(s.SendMsg))
|
||||
|
||||
msg.RegisterMsgServer(server, s)
|
||||
|
||||
@@ -154,3 +139,11 @@ func (m *msgServer) conversationAndGetRecvID(conversation *conversation.Conversa
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *msgServer) AppendStreamMsg(ctx context.Context, req *msg.AppendStreamMsgReq) (*msg.AppendStreamMsgResp, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) GetStreamMsg(ctx context.Context, req *msg.GetStreamMsgReq) (*msg.GetStreamMsgResp, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -245,11 +245,3 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
|
||||
func (m *msgServer) GetServerTime(ctx context.Context, _ *msg.GetServerTimeReq) (*msg.GetServerTimeResp, error) {
|
||||
return &msg.GetServerTimeResp{ServerTime: timeutil.GetCurrentTimestampByMill()}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) GetLastMessage(ctx context.Context, req *msg.GetLastMessageReq) (*msg.GetLastMessageResp, error) {
|
||||
msgs, err := m.MsgDatabase.GetLastMessage(ctx, req.ConversationIDs, req.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msg.GetLastMessageResp{Msgs: msgs}, nil
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (s *friendServer) GetPaginationBlacks(ctx context.Context, req *relation.Ge
|
||||
return nil, err
|
||||
}
|
||||
resp = &relation.GetPaginationBlacksResp{}
|
||||
resp.Blacks, err = convert.BlackDB2Pb(ctx, blacks, s.userClient.GetUsersInfoMap)
|
||||
resp.Blacks, err = convert.BlackDB2Pb(ctx, blacks, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -81,7 +81,9 @@ func (s *friendServer) AddBlack(ctx context.Context, req *relation.AddBlackReq)
|
||||
if err := s.webhookBeforeAddBlack(ctx, &s.config.WebhooksConfig.BeforeAddBlack, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.userClient.CheckUser(ctx, []string{req.OwnerUserID, req.BlackUserID}); err != nil {
|
||||
|
||||
_, err := s.userRpcClient.GetUsersInfo(ctx, []string{req.OwnerUserID, req.BlackUserID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
black := model.Black{
|
||||
@@ -112,7 +114,7 @@ func (s *friendServer) GetSpecifiedBlacks(ctx context.Context, req *relation.Get
|
||||
return nil, errs.ErrArgs.WrapMsg("userIDList repeated")
|
||||
}
|
||||
|
||||
userMap, err := s.userClient.GetUsersInfoMap(ctx, req.UserIDList)
|
||||
userMap, err := s.userRpcClient.GetPublicUserInfoMap(ctx, req.UserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -130,26 +132,13 @@ func (s *friendServer) GetSpecifiedBlacks(ctx context.Context, req *relation.Get
|
||||
Blacks: make([]*sdkws.BlackInfo, 0, len(req.UserIDList)),
|
||||
}
|
||||
|
||||
toPublcUser := func(userID string) *sdkws.PublicUserInfo {
|
||||
v, ok := userMap[userID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return &sdkws.PublicUserInfo{
|
||||
UserID: v.UserID,
|
||||
Nickname: v.Nickname,
|
||||
FaceURL: v.FaceURL,
|
||||
Ex: v.Ex,
|
||||
}
|
||||
}
|
||||
|
||||
for _, userID := range req.UserIDList {
|
||||
if black := blackMap[userID]; black != nil {
|
||||
resp.Blacks = append(resp.Blacks,
|
||||
&sdkws.BlackInfo{
|
||||
OwnerUserID: black.OwnerUserID,
|
||||
CreateTime: black.CreateTime.UnixMilli(),
|
||||
BlackUserInfo: toPublcUser(userID),
|
||||
BlackUserInfo: userMap[userID],
|
||||
AddSource: black.AddSource,
|
||||
OperatorUserID: black.OperatorUserID,
|
||||
Ex: black.Ex,
|
||||
|
||||
@@ -17,9 +17,6 @@ package relation
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/tools/mq/memamq"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
@@ -34,6 +31,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -46,14 +44,15 @@ import (
|
||||
|
||||
type friendServer struct {
|
||||
relation.UnimplementedFriendServer
|
||||
db controller.FriendDatabase
|
||||
blackDatabase controller.BlackDatabase
|
||||
notificationSender *FriendNotificationSender
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry
|
||||
config *Config
|
||||
webhookClient *webhook.Client
|
||||
queue *memamq.MemoryQueue
|
||||
userClient *rpcli.UserClient
|
||||
db controller.FriendDatabase
|
||||
blackDatabase controller.BlackDatabase
|
||||
userRpcClient *rpcclient.UserRpcClient
|
||||
notificationSender *FriendNotificationSender
|
||||
conversationRpcClient rpcclient.ConversationRpcClient
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry
|
||||
config *Config
|
||||
webhookClient *webhook.Client
|
||||
queue *memamq.MemoryQueue
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -93,44 +92,37 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
return err
|
||||
}
|
||||
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userClient := rpcli.NewUserClient(userConn)
|
||||
// Initialize RPC clients
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
|
||||
database := controller.NewFriendDatabase(
|
||||
friendMongoDB,
|
||||
friendRequestMongoDB,
|
||||
redis.NewFriendCacheRedis(rdb, &config.LocalCacheConfig, friendMongoDB, redis.GetRocksCacheOptions()),
|
||||
mgocli.GetTx(),
|
||||
)
|
||||
// Initialize notification sender
|
||||
notificationSender := NewFriendNotificationSender(
|
||||
&config.NotificationConfig,
|
||||
rpcli.NewMsgClient(msgConn),
|
||||
WithRpcFunc(userClient.GetUsersInfo),
|
||||
WithFriendDB(database),
|
||||
&msgRpcClient,
|
||||
WithRpcFunc(userRpcClient.GetUsersInfo),
|
||||
)
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
|
||||
// Register Friend server with refactored MongoDB and Redis integrations
|
||||
relation.RegisterFriendServer(server, &friendServer{
|
||||
db: database,
|
||||
db: controller.NewFriendDatabase(
|
||||
friendMongoDB,
|
||||
friendRequestMongoDB,
|
||||
redis.NewFriendCacheRedis(rdb, &config.LocalCacheConfig, friendMongoDB, redis.GetRocksCacheOptions()),
|
||||
mgocli.GetTx(),
|
||||
),
|
||||
blackDatabase: controller.NewBlackDatabase(
|
||||
blackMongoDB,
|
||||
redis.NewBlackCacheRedis(rdb, &config.LocalCacheConfig, blackMongoDB, redis.GetRocksCacheOptions()),
|
||||
),
|
||||
notificationSender: notificationSender,
|
||||
RegisterCenter: client,
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
queue: memamq.NewMemoryQueue(16, 1024*1024),
|
||||
userClient: userClient,
|
||||
userRpcClient: &userRpcClient,
|
||||
notificationSender: notificationSender,
|
||||
RegisterCenter: client,
|
||||
conversationRpcClient: rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation),
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
queue: memamq.NewMemoryQueue(16, 1024*1024),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -147,7 +139,7 @@ func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *relation.Apply
|
||||
if err = s.webhookBeforeAddFriend(ctx, &s.config.WebhooksConfig.BeforeAddFriend, req); err != nil && err != servererrs.ErrCallbackContinue {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.userClient.CheckUser(ctx, []string{req.ToUserID, req.FromUserID}); err != nil {
|
||||
if _, err := s.userRpcClient.GetUsersInfoMap(ctx, []string{req.ToUserID, req.FromUserID}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -171,8 +163,7 @@ func (s *friendServer) ImportFriends(ctx context.Context, req *relation.ImportFr
|
||||
if err := authverify.CheckAdmin(ctx, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.userClient.CheckUser(ctx, append([]string{req.OwnerUserID}, req.FriendUserIDs...)); err != nil {
|
||||
if _, err := s.userRpcClient.GetUsersInfo(ctx, append([]string{req.OwnerUserID}, req.FriendUserIDs...)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if datautil.Contain(req.OwnerUserID, req.FriendUserIDs...) {
|
||||
@@ -194,7 +185,7 @@ func (s *friendServer) ImportFriends(ctx context.Context, req *relation.ImportFr
|
||||
FromUserID: req.OwnerUserID,
|
||||
ToUserID: userID,
|
||||
HandleResult: constant.FriendResponseAgree,
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
|
||||
s.webhookAfterImportFriends(ctx, &s.config.WebhooksConfig.AfterImportFriends, req)
|
||||
@@ -223,7 +214,7 @@ func (s *friendServer) RespondFriendApply(ctx context.Context, req *relation.Res
|
||||
return nil, err
|
||||
}
|
||||
s.webhookAfterAddFriendAgree(ctx, &s.config.WebhooksConfig.AfterAddFriendAgree, req)
|
||||
s.notificationSender.FriendApplicationAgreedNotification(ctx, req, true)
|
||||
s.notificationSender.FriendApplicationAgreedNotification(ctx, req)
|
||||
return resp, nil
|
||||
}
|
||||
if req.HandleResult == constant.FriendResponseRefuse {
|
||||
@@ -284,9 +275,6 @@ func (s *friendServer) SetFriendRemark(ctx context.Context, req *relation.SetFri
|
||||
}
|
||||
|
||||
func (s *friendServer) GetFriendInfo(ctx context.Context, req *relation.GetFriendInfoReq) (*relation.GetFriendInfoResp, error) {
|
||||
if err := authverify.CheckAccessV3(ctx, req.OwnerUserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
friends, err := s.db.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -299,9 +287,6 @@ func (s *friendServer) GetDesignatedFriends(ctx context.Context, req *relation.G
|
||||
if datautil.Duplicate(req.FriendUserIDs) {
|
||||
return nil, errs.ErrArgs.WrapMsg("friend userID repeated")
|
||||
}
|
||||
if err := authverify.CheckAccessV3(ctx, req.OwnerUserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
friends, err := s.getFriend(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -319,7 +304,7 @@ func (s *friendServer) getFriend(ctx context.Context, ownerUserID string, friend
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return convert.FriendsDB2Pb(ctx, friends, s.userClient.GetUsersInfoMap)
|
||||
return convert.FriendsDB2Pb(ctx, friends, s.userRpcClient.GetUsersInfoMap)
|
||||
}
|
||||
|
||||
// Get the list of friend requests sent out proactively.
|
||||
@@ -331,7 +316,7 @@ func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
resp = &relation.GetDesignatedFriendsApplyResp{}
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.getCommonUserMap)
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -344,16 +329,13 @@ func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *rel
|
||||
return nil, err
|
||||
}
|
||||
|
||||
handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
|
||||
return int(e)
|
||||
})
|
||||
total, friendRequests, err := s.db.PageFriendRequestToMe(ctx, req.UserID, handleResults, req.Pagination)
|
||||
total, friendRequests, err := s.db.PageFriendRequestToMe(ctx, req.UserID, req.Pagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp = &relation.GetPaginationFriendsApplyToResp{}
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.getCommonUserMap)
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -370,15 +352,12 @@ func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
|
||||
return int(e)
|
||||
})
|
||||
total, friendRequests, err := s.db.PageFriendRequestFromMe(ctx, req.UserID, handleResults, req.Pagination)
|
||||
total, friendRequests, err := s.db.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.getCommonUserMap)
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -409,7 +388,7 @@ func (s *friendServer) GetPaginationFriends(ctx context.Context, req *relation.G
|
||||
}
|
||||
|
||||
resp = &relation.GetPaginationFriendsResp{}
|
||||
resp.FriendsInfo, err = convert.FriendsDB2Pb(ctx, friends, s.userClient.GetUsersInfoMap)
|
||||
resp.FriendsInfo, err = convert.FriendsDB2Pb(ctx, friends, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -442,11 +421,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *relatio
|
||||
return nil, errs.ErrArgs.WrapMsg("userIDList repeated")
|
||||
}
|
||||
|
||||
if err := authverify.CheckAccessV3(ctx, req.OwnerUserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMap, err := s.userClient.GetUsersInfoMap(ctx, req.UserIDList)
|
||||
userMap, err := s.userRpcClient.GetUsersInfoMap(ctx, req.UserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -525,10 +500,6 @@ func (s *friendServer) UpdateFriends(
|
||||
return nil, errs.ErrArgs.WrapMsg("friendIDList repeated")
|
||||
}
|
||||
|
||||
if err := authverify.CheckAccessV3(ctx, req.OwnerUserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err := s.db.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -555,27 +526,17 @@ func (s *friendServer) UpdateFriends(
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *friendServer) GetSelfUnhandledApplyCount(ctx context.Context, req *relation.GetSelfUnhandledApplyCountReq) (*relation.GetSelfUnhandledApplyCountResp, error) {
|
||||
if err := authverify.CheckAccessV3(ctx, req.UserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count, err := s.db.GetUnhandledCount(ctx, req.UserID, req.Time)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &relation.GetSelfUnhandledApplyCountResp{
|
||||
Count: count,
|
||||
}, nil
|
||||
func (s *friendServer) GetIncrementalFriendsApplyTo(ctx context.Context, req *relation.GetIncrementalFriendsApplyToReq) (*relation.GetIncrementalFriendsApplyToResp, error) {
|
||||
// TODO implement me
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *friendServer) getCommonUserMap(ctx context.Context, userIDs []string) (map[string]common_user.CommonUser, error) {
|
||||
users, err := s.userClient.GetUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.SliceToMapAny(users, func(e *sdkws.UserInfo) (string, common_user.CommonUser) {
|
||||
return e.UserID, e
|
||||
}), nil
|
||||
func (s *friendServer) GetIncrementalFriendsApplyFrom(ctx context.Context, req *relation.GetIncrementalFriendsApplyFromReq) (*relation.GetIncrementalFriendsApplyFromResp, error) {
|
||||
// TODO implement me
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *friendServer) GetIncrementalBlacks(ctx context.Context, req *relation.GetIncrementalBlacksReq) (*relation.GetIncrementalBlacksResp, error) {
|
||||
// TODO implement me
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -16,13 +16,6 @@ package relation
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
||||
|
||||
@@ -31,8 +24,8 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -40,9 +33,9 @@ import (
|
||||
)
|
||||
|
||||
type FriendNotificationSender struct {
|
||||
*notification.NotificationSender
|
||||
*rpcclient.NotificationSender
|
||||
// Target not found err
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error)
|
||||
// db controller
|
||||
db controller.FriendDatabase
|
||||
}
|
||||
@@ -55,9 +48,11 @@ func WithFriendDB(db controller.FriendDatabase) friendNotificationSenderOptions
|
||||
}
|
||||
}
|
||||
|
||||
func WithDBFunc(fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error)) friendNotificationSenderOptions {
|
||||
func WithDBFunc(
|
||||
fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error),
|
||||
) friendNotificationSenderOptions {
|
||||
return func(s *FriendNotificationSender) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
|
||||
users, err := fn(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -71,9 +66,11 @@ func WithDBFunc(fn func(ctx context.Context, userIDs []string) (users []*relatio
|
||||
}
|
||||
}
|
||||
|
||||
func WithRpcFunc(fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error)) friendNotificationSenderOptions {
|
||||
func WithRpcFunc(
|
||||
fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error),
|
||||
) friendNotificationSenderOptions {
|
||||
return func(s *FriendNotificationSender) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
|
||||
users, err := fn(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -87,11 +84,13 @@ func WithRpcFunc(fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserIn
|
||||
}
|
||||
}
|
||||
|
||||
func NewFriendNotificationSender(conf *config.Notification, msgClient *rpcli.MsgClient, opts ...friendNotificationSenderOptions) *FriendNotificationSender {
|
||||
func NewFriendNotificationSender(
|
||||
conf *config.Notification,
|
||||
msgRpcClient *rpcclient.MessageRpcClient,
|
||||
opts ...friendNotificationSenderOptions,
|
||||
) *FriendNotificationSender {
|
||||
f := &FriendNotificationSender{
|
||||
NotificationSender: notification.NewNotificationSender(conf, notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msgClient.SendMsg(ctx, req)
|
||||
})),
|
||||
NotificationSender: rpcclient.NewNotificationSender(conf, rpcclient.WithRpcClient(msgRpcClient)),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(f)
|
||||
@@ -99,7 +98,10 @@ func NewFriendNotificationSender(conf *config.Notification, msgClient *rpcli.Msg
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *FriendNotificationSender) getUsersInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error) {
|
||||
func (f *FriendNotificationSender) getUsersInfoMap(
|
||||
ctx context.Context,
|
||||
userIDs []string,
|
||||
) (map[string]*sdkws.UserInfo, error) {
|
||||
users, err := f.getUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -112,7 +114,10 @@ func (f *FriendNotificationSender) getUsersInfoMap(ctx context.Context, userIDs
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func (f *FriendNotificationSender) getFromToUserNickname(ctx context.Context, fromUserID, toUserID string) (string, string, error) {
|
||||
func (f *FriendNotificationSender) getFromToUserNickname(
|
||||
ctx context.Context,
|
||||
fromUserID, toUserID string,
|
||||
) (string, string, error) {
|
||||
users, err := f.getUsersInfoMap(ctx, []string{fromUserID, toUserID})
|
||||
if err != nil {
|
||||
return "", "", nil
|
||||
@@ -125,113 +130,60 @@ func (f *FriendNotificationSender) UserInfoUpdatedNotification(ctx context.Conte
|
||||
f.Notification(ctx, mcontext.GetOpUserID(ctx), changedUserID, constant.UserInfoUpdatedNotification, &tips)
|
||||
}
|
||||
|
||||
func (f *FriendNotificationSender) getCommonUserMap(ctx context.Context, userIDs []string) (map[string]common_user.CommonUser, error) {
|
||||
users, err := f.getUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.SliceToMap(users, func(e common_user.CommonUser) string {
|
||||
return e.GetUserID()
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (f *FriendNotificationSender) getFriendRequests(ctx context.Context, fromUserID, toUserID string) (*sdkws.FriendRequest, error) {
|
||||
if f.db == nil {
|
||||
return nil, errs.ErrInternalServer.WithDetail("db is nil")
|
||||
}
|
||||
friendRequests, err := f.db.FindBothFriendRequests(ctx, fromUserID, toUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
requests, err := convert.FriendRequestDB2Pb(ctx, friendRequests, f.getCommonUserMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, request := range requests {
|
||||
if request.FromUserID == fromUserID && request.ToUserID == toUserID {
|
||||
return request, nil
|
||||
}
|
||||
}
|
||||
return nil, errs.ErrRecordNotFound.WrapMsg("friend request not found", "fromUserID", fromUserID, "toUserID", toUserID)
|
||||
}
|
||||
|
||||
func (f *FriendNotificationSender) FriendApplicationAddNotification(ctx context.Context, req *relation.ApplyToAddFriendReq) {
|
||||
request, err := f.getFriendRequests(ctx, req.FromUserID, req.ToUserID)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "FriendApplicationAddNotification get friend request", err, "fromUserID", req.FromUserID, "toUserID", req.ToUserID)
|
||||
return
|
||||
}
|
||||
tips := sdkws.FriendApplicationTips{
|
||||
FromToUserID: &sdkws.FromToUserID{
|
||||
FromUserID: req.FromUserID,
|
||||
ToUserID: req.ToUserID,
|
||||
},
|
||||
Request: request,
|
||||
}
|
||||
tips := sdkws.FriendApplicationTips{FromToUserID: &sdkws.FromToUserID{
|
||||
FromUserID: req.FromUserID,
|
||||
ToUserID: req.ToUserID,
|
||||
}}
|
||||
f.Notification(ctx, req.FromUserID, req.ToUserID, constant.FriendApplicationNotification, &tips)
|
||||
}
|
||||
|
||||
func (f *FriendNotificationSender) FriendApplicationAgreedNotification(ctx context.Context, req *relation.RespondFriendApplyReq, checkReq bool) {
|
||||
var (
|
||||
request *sdkws.FriendRequest
|
||||
err error
|
||||
)
|
||||
if checkReq {
|
||||
request, err = f.getFriendRequests(ctx, req.FromUserID, req.ToUserID)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "FriendApplicationAgreedNotification get friend request", err, "fromUserID", req.FromUserID, "toUserID", req.ToUserID)
|
||||
return
|
||||
}
|
||||
}
|
||||
tips := sdkws.FriendApplicationApprovedTips{
|
||||
FromToUserID: &sdkws.FromToUserID{
|
||||
FromUserID: req.FromUserID,
|
||||
ToUserID: req.ToUserID,
|
||||
},
|
||||
HandleMsg: req.HandleMsg,
|
||||
Request: request,
|
||||
}
|
||||
func (f *FriendNotificationSender) FriendApplicationAgreedNotification(
|
||||
ctx context.Context,
|
||||
req *relation.RespondFriendApplyReq,
|
||||
) {
|
||||
tips := sdkws.FriendApplicationApprovedTips{FromToUserID: &sdkws.FromToUserID{
|
||||
FromUserID: req.FromUserID,
|
||||
ToUserID: req.ToUserID,
|
||||
}, HandleMsg: req.HandleMsg}
|
||||
f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationApprovedNotification, &tips)
|
||||
}
|
||||
|
||||
func (f *FriendNotificationSender) FriendApplicationRefusedNotification(ctx context.Context, req *relation.RespondFriendApplyReq) {
|
||||
request, err := f.getFriendRequests(ctx, req.FromUserID, req.ToUserID)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "FriendApplicationRefusedNotification get friend request", err, "fromUserID", req.FromUserID, "toUserID", req.ToUserID)
|
||||
return
|
||||
}
|
||||
tips := sdkws.FriendApplicationRejectedTips{
|
||||
FromToUserID: &sdkws.FromToUserID{
|
||||
FromUserID: req.FromUserID,
|
||||
ToUserID: req.ToUserID,
|
||||
},
|
||||
HandleMsg: req.HandleMsg,
|
||||
Request: request,
|
||||
}
|
||||
func (f *FriendNotificationSender) FriendApplicationRefusedNotification(
|
||||
ctx context.Context,
|
||||
req *relation.RespondFriendApplyReq,
|
||||
) {
|
||||
tips := sdkws.FriendApplicationApprovedTips{FromToUserID: &sdkws.FromToUserID{
|
||||
FromUserID: req.FromUserID,
|
||||
ToUserID: req.ToUserID,
|
||||
}, HandleMsg: req.HandleMsg}
|
||||
f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationRejectedNotification, &tips)
|
||||
}
|
||||
|
||||
//func (f *FriendNotificationSender) FriendAddedNotification(ctx context.Context, operationID, opUserID, fromUserID, toUserID string) error {
|
||||
// tips := sdkws.FriendAddedTips{Friend: &sdkws.FriendInfo{}, OpUser: &sdkws.PublicUserInfo{}}
|
||||
// user, err := f.getUsersInfo(ctx, []string{opUserID})
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// tips.OpUser.UserID = user[0].GetUserID()
|
||||
// tips.OpUser.Ex = user[0].GetEx()
|
||||
// tips.OpUser.Nickname = user[0].GetNickname()
|
||||
// tips.OpUser.FaceURL = user[0].GetFaceURL()
|
||||
// friends, err := f.db.FindFriendsWithError(ctx, fromUserID, []string{toUserID})
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// tips.Friend, err = convert.FriendDB2Pb(ctx, friends[0], f.getUsersInfoMap)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// f.Notification(ctx, fromUserID, toUserID, constant.FriendAddedNotification, &tips)
|
||||
// return nil
|
||||
//}
|
||||
func (f *FriendNotificationSender) FriendAddedNotification(
|
||||
ctx context.Context,
|
||||
operationID, opUserID, fromUserID, toUserID string,
|
||||
) error {
|
||||
tips := sdkws.FriendAddedTips{Friend: &sdkws.FriendInfo{}, OpUser: &sdkws.PublicUserInfo{}}
|
||||
user, err := f.getUsersInfo(ctx, []string{opUserID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tips.OpUser.UserID = user[0].GetUserID()
|
||||
tips.OpUser.Ex = user[0].GetEx()
|
||||
tips.OpUser.Nickname = user[0].GetNickname()
|
||||
tips.OpUser.FaceURL = user[0].GetFaceURL()
|
||||
friends, err := f.db.FindFriendsWithError(ctx, fromUserID, []string{toUserID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tips.Friend, err = convert.FriendDB2Pb(ctx, friends[0], f.getUsersInfoMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Notification(ctx, fromUserID, toUserID, constant.FriendAddedNotification, &tips)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FriendNotificationSender) FriendDeletedNotification(ctx context.Context, req *relation.DeleteFriendReq) {
|
||||
tips := sdkws.FriendDeletedTips{FromToUserID: &sdkws.FromToUserID{
|
||||
|
||||
@@ -2,11 +2,10 @@ package relation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/util/hashutil"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"slices"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/incrversion"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
@@ -40,9 +39,6 @@ func (s *friendServer) NotificationUserInfoUpdate(ctx context.Context, req *rela
|
||||
}
|
||||
|
||||
func (s *friendServer) GetFullFriendUserIDs(ctx context.Context, req *relation.GetFullFriendUserIDsReq) (*relation.GetFullFriendUserIDsResp, error) {
|
||||
if err := authverify.CheckAccessV3(ctx, req.UserID, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vl, err := s.db.FindMaxFriendVersionCache(ctx, req.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -56,7 +52,7 @@ func (s *friendServer) GetFullFriendUserIDs(ctx context.Context, req *relation.G
|
||||
userIDs = nil
|
||||
}
|
||||
return &relation.GetFullFriendUserIDsResp{
|
||||
Version: uint64(vl.Version),
|
||||
Version: idHash,
|
||||
VersionID: vl.ID.Hex(),
|
||||
Equal: req.IdHash == idHash,
|
||||
UserIDs: userIDs,
|
||||
|
||||
@@ -19,9 +19,10 @@ import (
|
||||
"crypto/rand"
|
||||
"time"
|
||||
|
||||
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
@@ -148,7 +149,7 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
|
||||
for _, log := range logs {
|
||||
userIDs = append(userIDs, log.UserID)
|
||||
}
|
||||
userMap, err := t.userClient.GetUsersInfoMap(ctx, userIDs)
|
||||
userMap, err := t.userRpcClient.GetUsersInfoMap(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+78
-27
@@ -23,11 +23,13 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
@@ -38,10 +40,7 @@ import (
|
||||
)
|
||||
|
||||
func (t *thirdServer) PartLimit(ctx context.Context, req *third.PartLimitReq) (*third.PartLimitResp, error) {
|
||||
limit, err := t.s3dataBase.PartLimit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
limit := t.s3dataBase.PartLimit()
|
||||
return &third.PartLimitResp{
|
||||
MinPartSize: limit.MinPartSize,
|
||||
MaxPartSize: limit.MaxPartSize,
|
||||
@@ -289,35 +288,87 @@ func (t *thirdServer) apiAddress(prefix, name string) string {
|
||||
}
|
||||
|
||||
func (t *thirdServer) DeleteOutdatedData(ctx context.Context, req *third.DeleteOutdatedDataReq) (*third.DeleteOutdatedDataResp, error) {
|
||||
if err := authverify.CheckAdmin(ctx, t.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
engine := t.config.RpcConfig.Object.Enable
|
||||
var conf config.Third
|
||||
expireTime := time.UnixMilli(req.ExpireTime)
|
||||
// Find all expired data in S3 database
|
||||
models, err := t.s3dataBase.FindExpirationObject(ctx, engine, expireTime, req.ObjectGroup, int64(req.Limit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
findPagination := &sdkws.RequestPagination{
|
||||
PageNumber: 1,
|
||||
ShowNumber: 500,
|
||||
}
|
||||
for i, obj := range models {
|
||||
if err := t.s3dataBase.DeleteSpecifiedData(ctx, engine, []string{obj.Name}); err != nil {
|
||||
|
||||
// Find all expired data in S3 database
|
||||
total, models, err := t.s3dataBase.FindNeedDeleteObjectByDB(ctx, expireTime, req.ObjectGroup, findPagination)
|
||||
if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
|
||||
if total == 0 {
|
||||
log.ZDebug(ctx, "Not have OutdatedData", "delete Total", total)
|
||||
return &third.DeleteOutdatedDataResp{Count: int32(total)}, nil
|
||||
}
|
||||
|
||||
needDelObjectKeys := make([]string, len(models))
|
||||
for _, model := range models {
|
||||
needDelObjectKeys = append(needDelObjectKeys, model.Key)
|
||||
}
|
||||
|
||||
// Remove duplicate keys, have the same key use in different models
|
||||
needDelObjectKeys = datautil.Distinct(needDelObjectKeys)
|
||||
|
||||
for _, key := range needDelObjectKeys {
|
||||
// Find all models by key
|
||||
keyModels, err := t.s3dataBase.FindModelsByKey(ctx, key)
|
||||
if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
if err := t.s3dataBase.DelS3Key(ctx, engine, obj.Name); err != nil {
|
||||
return nil, err
|
||||
|
||||
// check keyModels, if all keyModels.
|
||||
needDelKey := true // Default can delete
|
||||
for _, keymodel := range keyModels {
|
||||
// If group is empty or CreateTime is after expireTime, can't delete this key
|
||||
if keymodel.Group == "" || keymodel.CreateTime.After(expireTime) {
|
||||
needDelKey = false
|
||||
break
|
||||
}
|
||||
}
|
||||
count, err := t.s3dataBase.GetKeyCount(ctx, engine, obj.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "delete s3 object record", "index", i, "s3", obj, "count", count)
|
||||
if count == 0 {
|
||||
if err := t.s3.DeleteObject(ctx, obj.Key); err != nil {
|
||||
return nil, err
|
||||
|
||||
// If this object is not referenced by not expire data, delete it
|
||||
if needDelKey && t.minio != nil {
|
||||
// If have a thumbnail, delete it
|
||||
thumbnailKey, _ := t.getMinioImageThumbnailKey(ctx, key)
|
||||
if thumbnailKey != "" {
|
||||
err := t.s3dataBase.DeleteObject(ctx, thumbnailKey)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "Delete thumbnail object is error:", errs.Wrap(err), "thumbnailKey", thumbnailKey)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete object
|
||||
err = t.s3dataBase.DeleteObject(ctx, key)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "Delete object is error", errs.Wrap(err), "object key", key)
|
||||
}
|
||||
|
||||
// Delete cache key
|
||||
err = t.s3dataBase.DelS3Key(ctx, conf.Object.Enable, key)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "Delete cache key is error:", errs.Wrap(err), "cache S3 key:", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &third.DeleteOutdatedDataResp{Count: int32(len(models))}, nil
|
||||
|
||||
// handle delete data in S3 database
|
||||
for _, model := range models {
|
||||
// Delete all expired data row in S3 database
|
||||
err := t.s3dataBase.DeleteSpecifiedData(ctx, model.Engine, model.Name)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
log.ZDebug(ctx, "DeleteOutdatedData", "delete Total", total)
|
||||
|
||||
return &third.DeleteOutdatedDataResp{Count: int32(total)}, nil
|
||||
}
|
||||
|
||||
type FormDataMate struct {
|
||||
|
||||
+17
-23
@@ -17,19 +17,14 @@ package third
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/tools/s3/aws"
|
||||
"github.com/openimsdk/tools/s3/disable"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
@@ -39,16 +34,17 @@ import (
|
||||
"github.com/openimsdk/tools/s3/kodo"
|
||||
"github.com/openimsdk/tools/s3/minio"
|
||||
"github.com/openimsdk/tools/s3/oss"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type thirdServer struct {
|
||||
third.UnimplementedThirdServer
|
||||
thirdDatabase controller.ThirdDatabase
|
||||
s3dataBase controller.S3Database
|
||||
userRpcClient rpcclient.UserRpcClient
|
||||
defaultExpire time.Duration
|
||||
config *Config
|
||||
s3 s3.Interface
|
||||
userClient *rpcli.UserClient
|
||||
minio *minio.Minio
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -83,43 +79,41 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
// Select the oss method according to the profile policy
|
||||
enable := config.RpcConfig.Object.Enable
|
||||
var (
|
||||
o s3.Interface
|
||||
o s3.Interface
|
||||
minioCli *minio.Minio
|
||||
)
|
||||
switch enable {
|
||||
case "minio":
|
||||
o, err = minio.NewMinio(ctx, redis.NewMinioCache(rdb), *config.MinioConfig.Build())
|
||||
minioCli, err = minio.NewMinio(ctx, redis.NewMinioCache(rdb), *config.MinioConfig.Build())
|
||||
o = minioCli
|
||||
case "cos":
|
||||
o, err = cos.NewCos(*config.RpcConfig.Object.Cos.Build())
|
||||
case "oss":
|
||||
o, err = oss.NewOSS(*config.RpcConfig.Object.Oss.Build())
|
||||
case "kodo":
|
||||
o, err = kodo.NewKodo(*config.RpcConfig.Object.Kodo.Build())
|
||||
case "aws":
|
||||
o, err = aws.NewAws(*config.RpcConfig.Object.Aws.Build())
|
||||
case "":
|
||||
o = disable.NewDisable()
|
||||
default:
|
||||
err = fmt.Errorf("invalid object enable: %s", enable)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
third.RegisterThirdServer(server, &thirdServer{
|
||||
thirdDatabase: controller.NewThirdDatabase(redis.NewThirdCache(rdb), logdb),
|
||||
userRpcClient: rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID),
|
||||
s3dataBase: controller.NewS3Database(rdb, o, s3db),
|
||||
defaultExpire: time.Hour * 24 * 7,
|
||||
config: config,
|
||||
s3: o,
|
||||
userClient: rpcli.NewUserClient(userConn),
|
||||
minio: minioCli,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *thirdServer) getMinioImageThumbnailKey(ctx context.Context, name string) (string, error) {
|
||||
return t.minio.GetImageThumbnailKey(ctx, name)
|
||||
}
|
||||
|
||||
func (t *thirdServer) FcmUpdateToken(ctx context.Context, req *third.FcmUpdateTokenReq) (resp *third.FcmUpdateTokenResp, err error) {
|
||||
err = t.thirdDatabase.FcmUpdateToken(ctx, req.Account, int(req.PlatformID), req.FcmToken, req.ExpireTime)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,22 +16,18 @@ package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
|
||||
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
type UserNotificationSender struct {
|
||||
*notification.NotificationSender
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||
*rpcclient.NotificationSender
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error)
|
||||
// db controller
|
||||
db controller.UserDatabase
|
||||
}
|
||||
@@ -48,7 +44,7 @@ func WithUserFunc(
|
||||
fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error),
|
||||
) userNotificationSenderOptions {
|
||||
return func(u *UserNotificationSender) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
|
||||
users, err := fn(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -62,11 +58,9 @@ func WithUserFunc(
|
||||
}
|
||||
}
|
||||
|
||||
func NewUserNotificationSender(config *Config, msgClient *rpcli.MsgClient, opts ...userNotificationSenderOptions) *UserNotificationSender {
|
||||
func NewUserNotificationSender(config *Config, msgRpcClient *rpcclient.MessageRpcClient, opts ...userNotificationSenderOptions) *UserNotificationSender {
|
||||
f := &UserNotificationSender{
|
||||
NotificationSender: notification.NewNotificationSender(&config.NotificationConfig, notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msgClient.SendMsg(ctx, req)
|
||||
})),
|
||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithRpcClient(msgRpcClient)),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(f)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user