mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-05-09 11:35:59 +08:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 391eafb402 | |||
| 482284a0fb | |||
| a893141ae6 | |||
| 9eccfee997 | |||
| f950dbc5e7 | |||
| 55113e5277 | |||
| 7fdc438500 | |||
| 2804d90020 | |||
| 4ca3f2dc0c | |||
| b92c5ab821 | |||
| 9c4b6e50ef | |||
| 54e189d80f | |||
| 1b6d70e4a7 | |||
| 4c9cf55867 | |||
| 9be25ab041 | |||
| 8a5f8a10ba | |||
| 1f3b41e379 | |||
| 1684c82458 | |||
| bc326704f1 | |||
| e254bbf1fc | |||
| 54309b83a2 | |||
| d55cb0fa8b | |||
| 2e58a5cc82 | |||
| cc957886b1 | |||
| 78c82e08b8 | |||
| 09cb8336ad | |||
| 9a436087cf | |||
| 6c7c268b1f | |||
| 04b7e6b75e | |||
| 916d074cf9 | |||
| 61b968fbf2 | |||
| efed369c0c | |||
| aaf898567f | |||
| 62583b32a7 | |||
| 4890487429 | |||
| 744f481b9c | |||
| f242066f30 | |||
| 57710bb9e3 | |||
| 0006bce0a2 | |||
| 0bb6f610ef | |||
| 82d133588e | |||
| d70dc7b16b | |||
| 9f796e78c1 | |||
| efcd76318e | |||
| d7af353e42 | |||
| ab1691865f |
@@ -1,4 +1,4 @@
|
|||||||
name: Build and release services Docker Images
|
name: Build and release services Images
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -19,26 +19,26 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.8.0
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v3.3.0
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
- name: Log in to GitHub Container Registry
|
- name: Log in to GitHub Container Registry
|
||||||
uses: docker/login-action@v3.3.0
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Log in to Aliyun Container Registry
|
- name: Log in to Aliyun Container Registry
|
||||||
uses: docker/login-action@v3.3.0
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: registry.cn-hangzhou.aliyuncs.com
|
registry: registry.cn-hangzhou.aliyuncs.com
|
||||||
username: ${{ secrets.ALIREGISTRY_USERNAME }}
|
username: ${{ secrets.ALIREGISTRY_USERNAME }}
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Extract metadata for Docker (tags, labels)
|
- name: Extract metadata for Docker (tags, labels)
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5.6.0
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=tag
|
type=ref,event=tag
|
||||||
@@ -54,14 +54,15 @@ jobs:
|
|||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern=v{{version}}
|
type=semver,pattern=v{{version}}
|
||||||
|
# type=semver,pattern={{major}}.{{minor}}
|
||||||
type=semver,pattern=release-{{raw}}
|
type=semver,pattern=release-{{raw}}
|
||||||
type=sha
|
type=sha
|
||||||
type=raw,value=${{ github.event.inputs.tag }}
|
type=raw,value=${{ github.event.inputs.tag }}
|
||||||
|
|
||||||
- name: Build and push Docker images
|
- name: Build and push Docker images
|
||||||
run: |
|
run: |
|
||||||
IMG_DIR="build/images"
|
ROOT_DIR="build/images"
|
||||||
for dir in "$IMG_DIR"/*/; do
|
for dir in "$ROOT_DIR"/*/; do
|
||||||
# Find Dockerfile or *.dockerfile in a case-insensitive manner
|
# Find Dockerfile or *.dockerfile in a case-insensitive manner
|
||||||
dockerfile=$(find "$dir" -maxdepth 1 -type f \( -iname 'dockerfile' -o -iname '*.dockerfile' \) | head -n 1)
|
dockerfile=$(find "$dir" -maxdepth 1 -type f \( -iname 'dockerfile' -o -iname '*.dockerfile' \) | head -n 1)
|
||||||
|
|
||||||
@@ -83,9 +84,8 @@ jobs:
|
|||||||
docker buildx build --platform linux/amd64,linux/arm64 \
|
docker buildx build --platform linux/amd64,linux/arm64 \
|
||||||
--file "$dockerfile" \
|
--file "$dockerfile" \
|
||||||
"${tag_args[@]}" \
|
"${tag_args[@]}" \
|
||||||
--push \
|
--push "$dir"
|
||||||
"."
|
|
||||||
else
|
else
|
||||||
echo "No valid Dockerfile found in $dir"
|
echo "No valid Dockerfile found in $dir"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- "**/*.md"
|
- '**/*.md'
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
go_version: ["1.22.x"]
|
go_version: ["1.21.x", "1.22.x"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Server repository
|
- name: Checkout Server repository
|
||||||
@@ -37,20 +37,27 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up infra services
|
- name: Set up infra services
|
||||||
uses: hoverkraft-tech/compose-action@v2.0.1
|
uses: hoverkraft-tech/compose-action@v2.0.1
|
||||||
|
# Uncomment and set the correct path to your docker-compose file
|
||||||
with:
|
with:
|
||||||
compose-file: "./docker-compose.yml"
|
compose-file: "./docker-compose.yml"
|
||||||
|
|
||||||
# - name: Get Internal IP Address
|
# run: |
|
||||||
# id: get-ip
|
# sudo docker compose up -d
|
||||||
# run: |
|
# sudo sleep 30 # Increased sleep time for better stability
|
||||||
# IP=$(hostname -I | awk '{print $1}')
|
# timeout-minutes: 60 # Increased timeout for Docker setup
|
||||||
# echo "The IP Address is: $IP"
|
|
||||||
# echo "::set-output name=ip::$IP"
|
|
||||||
|
|
||||||
# - name: Update .env
|
|
||||||
# run: |
|
# - name: Get Internal IP Address
|
||||||
# sed -i 's|externalAddress:.*|externalAddress: "http://${{ steps.get-ip.outputs.ip }}:10005"|' config/minio.yml
|
# id: get-ip
|
||||||
# cat config/minio.yml
|
# run: |
|
||||||
|
# IP=$(hostname -I | awk '{print $1}')
|
||||||
|
# echo "The IP Address is: $IP"
|
||||||
|
# echo "::set-output name=ip::$IP"
|
||||||
|
|
||||||
|
# - name: Update .env
|
||||||
|
# run: |
|
||||||
|
# sed -i 's|externalAddress:.*|externalAddress: "http://${{ steps.get-ip.outputs.ip }}:10005"|' config/minio.yml
|
||||||
|
# cat config/minio.yml
|
||||||
|
|
||||||
- name: Build and test Server Services
|
- name: Build and test Server Services
|
||||||
run: |
|
run: |
|
||||||
@@ -78,90 +85,6 @@ jobs:
|
|||||||
mage start
|
mage start
|
||||||
mage check
|
mage check
|
||||||
|
|
||||||
- name: Test Server and Chat
|
|
||||||
run: |
|
|
||||||
check_error() {
|
|
||||||
echo "Response: $1"
|
|
||||||
errCode=$(echo $1 | jq -r '.errCode')
|
|
||||||
if [ "$errCode" != "0" ]; then
|
|
||||||
errMsg=$(echo $1 | jq -r '.errMsg')
|
|
||||||
echo "Error: $errMsg"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test register
|
|
||||||
response1=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
|
|
||||||
"verifyCode": "666666",
|
|
||||||
"platform": 3,
|
|
||||||
"autoLogin": true,
|
|
||||||
"user":{
|
|
||||||
"nickname": "test12312",
|
|
||||||
"areaCode":"+86",
|
|
||||||
"phoneNumber": "12345678190",
|
|
||||||
"password":"test123456"
|
|
||||||
}
|
|
||||||
}' http://127.0.0.1:10008/account/register)
|
|
||||||
check_error "$response1"
|
|
||||||
userID1=$(echo $response1 | jq -r '.data.userID')
|
|
||||||
echo "userID1: $userID1"
|
|
||||||
|
|
||||||
response2=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
|
|
||||||
"verifyCode": "666666",
|
|
||||||
"platform": 3,
|
|
||||||
"autoLogin": true,
|
|
||||||
"user":{
|
|
||||||
"nickname": "test22312",
|
|
||||||
"areaCode":"+86",
|
|
||||||
"phoneNumber": "12345678290",
|
|
||||||
"password":"test123456"
|
|
||||||
}
|
|
||||||
}' http://127.0.0.1:10008/account/register)
|
|
||||||
check_error "$response2"
|
|
||||||
userID2=$(echo $response2 | jq -r '.data.userID')
|
|
||||||
echo "userID2: $userID2"
|
|
||||||
|
|
||||||
# Test login
|
|
||||||
login_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
|
|
||||||
"platform": 3,
|
|
||||||
"areaCode":"+86",
|
|
||||||
"phoneNumber": "12345678190",
|
|
||||||
"password":"test123456"
|
|
||||||
}' http://localhost:10008/account/login)
|
|
||||||
check_error "$login_response"
|
|
||||||
|
|
||||||
# Test get admin token
|
|
||||||
get_admin_token_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
|
|
||||||
"secret": "openIM123",
|
|
||||||
"platformID": 2,
|
|
||||||
"userID": "imAdmin"
|
|
||||||
}' http://127.0.0.1:10002/auth/get_admin_token)
|
|
||||||
check_error "$get_admin_token_response"
|
|
||||||
adminToken=$(echo $get_admin_token_response | jq -r '.data.token')
|
|
||||||
echo "adminToken: $adminToken"
|
|
||||||
|
|
||||||
# Test send message
|
|
||||||
send_msg_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -H "token: $adminToken" -d '{
|
|
||||||
"sendID": "'$userID1'",
|
|
||||||
"recvID": "'$userID2'",
|
|
||||||
"senderPlatformID": 3,
|
|
||||||
"content": {
|
|
||||||
"content": "hello!!"
|
|
||||||
},
|
|
||||||
"contentType": 101,
|
|
||||||
"sessionType": 1
|
|
||||||
}' http://127.0.0.1:10002/msg/send_msg)
|
|
||||||
check_error "$send_msg_response"
|
|
||||||
|
|
||||||
# Test get users
|
|
||||||
get_users_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -H "token: $adminToken" -d '{
|
|
||||||
"pagination": {
|
|
||||||
"pageNumber": 1,
|
|
||||||
"showNumber": 100
|
|
||||||
}
|
|
||||||
}' http://127.0.0.1:10002/user/get_users)
|
|
||||||
check_error "$get_users_response"
|
|
||||||
|
|
||||||
go-test:
|
go-test:
|
||||||
name: Benchmark Test with go ${{ matrix.go_version }} on ${{ matrix.os }}
|
name: Benchmark Test with go ${{ matrix.go_version }} on ${{ matrix.os }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
@@ -170,11 +93,11 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SDK_DIR: openim-sdk-core
|
SDK_DIR: openim-sdk-core
|
||||||
CONFIG_PATH: config/notification.yml
|
CONFIG_PATH: config/notification.yml
|
||||||
|
# pull-requests: write
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ ubuntu-latest ]
|
||||||
go_version: ["1.22.x"]
|
go_version: [ "1.22.x" ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Server repository
|
- name: Checkout Server repository
|
||||||
@@ -183,8 +106,7 @@ jobs:
|
|||||||
- name: Checkout SDK repository
|
- name: Checkout SDK repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: "openimsdk/openim-sdk-core"
|
repository: 'openimsdk/openim-sdk-core'
|
||||||
ref: "release-v3.8"
|
|
||||||
path: ${{ env.SDK_DIR }}
|
path: ${{ env.SDK_DIR }}
|
||||||
|
|
||||||
- name: Set up Go ${{ matrix.go_version }}
|
- name: Set up Go ${{ matrix.go_version }}
|
||||||
@@ -197,10 +119,15 @@ jobs:
|
|||||||
go install github.com/magefile/mage@latest
|
go install github.com/magefile/mage@latest
|
||||||
go mod download
|
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
|
- name: Modify Server Configuration
|
||||||
run: |
|
run: |
|
||||||
yq e '.groupCreated.isSendMsg = true' -i ${{ env.CONFIG_PATH }}
|
yq e '.groupCreated.unreadCount = true' -i ${{ env.CONFIG_PATH }}
|
||||||
yq e '.friendApplicationApproved.isSendMsg = true' -i ${{ env.CONFIG_PATH }}
|
yq e '.friendApplicationApproved.unreadCount = true' -i ${{ env.CONFIG_PATH }}
|
||||||
|
|
||||||
- name: Start Server Services
|
- name: Start Server Services
|
||||||
run: |
|
run: |
|
||||||
@@ -256,3 +183,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
CONTAINER_NAME="${{ github.event.repository.name }}-container"
|
CONTAINER_NAME="${{ github.event.repository.name }}-container"
|
||||||
docker logs $CONTAINER_NAME
|
docker logs $CONTAINER_NAME
|
||||||
|
|
||||||
|
# - name: Cleanup Docker Container
|
||||||
|
# run: |
|
||||||
|
# CONTAINER_NAME="${{ github.event.repository.name }}-container"
|
||||||
|
# IMAGE_NAME="${{ github.event.repository.name }}-test"
|
||||||
|
# docker stop $CONTAINER_NAME
|
||||||
|
# docker rm $CONTAINER_NAME
|
||||||
|
# docker rmi $IMAGE_NAME
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Create Individual PRs from Milestone
|
name: Create Pre-Release PR from Milestone
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -9,24 +9,24 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
milestone_name:
|
milestone_name:
|
||||||
description: "Milestone name to collect closed PRs from"
|
description: 'Milestone name to collect closed PRs from'
|
||||||
required: true
|
required: true
|
||||||
default: "v3.8.4"
|
default: 'v3.8.2'
|
||||||
target_branch:
|
target_branch:
|
||||||
description: "Target branch to merge the consolidated PR"
|
description: 'Target branch to merge the consolidated PR'
|
||||||
required: true
|
required: true
|
||||||
default: "pre-release-v3.8.4"
|
default: 'pre-release-v3.8.2'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
MILESTONE_NAME: ${{ github.event.inputs.milestone_name || 'v3.8.4' }}
|
MILESTONE_NAME: ${{ github.event.inputs.milestone_name || 'v3.8.2' }}
|
||||||
TARGET_BRANCH: ${{ github.event.inputs.target_branch || 'pre-release-v3.8.4' }}
|
TARGET_BRANCH: ${{ github.event.inputs.target_branch || 'pre-release-v3.8.2' }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
LABEL_NAME: cherry-picked
|
LABEL_NAME: cherry-picked
|
||||||
TEMP_DIR: /tmp
|
TEMP_DIR: /tmp # Using /tmp as the temporary directory
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
merge_milestone_prs:
|
cherry_pick_milestone_prs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Setup temp directory
|
- name: Setup temp directory
|
||||||
@@ -47,6 +47,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup Git User for OpenIM-Robot
|
- name: Setup Git User for OpenIM-Robot
|
||||||
run: |
|
run: |
|
||||||
|
# Set up Git credentials for the bot
|
||||||
git config --global user.email "OpenIM-Robot@users.noreply.github.com"
|
git config --global user.email "OpenIM-Robot@users.noreply.github.com"
|
||||||
git config --global user.name "OpenIM-Robot"
|
git config --global user.name "OpenIM-Robot"
|
||||||
|
|
||||||
@@ -82,65 +83,136 @@ jobs:
|
|||||||
if ! echo "$labels" | grep -q "${LABEL_NAME}"; then
|
if ! echo "$labels" | grep -q "${LABEL_NAME}"; then
|
||||||
echo "PR #$pr_number does not have the 'cherry-picked' label. Adding to the list."
|
echo "PR #$pr_number does not have the 'cherry-picked' label. Adding to the list."
|
||||||
echo "$pr_number" >> ${{ env.TEMP_DIR }}/pr_numbers.txt
|
echo "$pr_number" >> ${{ env.TEMP_DIR }}/pr_numbers.txt
|
||||||
|
else
|
||||||
|
echo "PR #$pr_number already has the 'cherry-picked' label. Skipping."
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Sort the filtered PR numbers
|
||||||
sort -n ${{ env.TEMP_DIR }}/pr_numbers.txt -o ${{ env.TEMP_DIR }}/pr_numbers.txt
|
sort -n ${{ env.TEMP_DIR }}/pr_numbers.txt -o ${{ env.TEMP_DIR }}/pr_numbers.txt
|
||||||
|
|
||||||
- name: Create Individual PRs
|
echo "Filtered and sorted PR numbers:"
|
||||||
|
cat ${{ env.TEMP_DIR }}/pr_numbers.txt || echo "No closed PR numbers found for milestone."
|
||||||
|
|
||||||
|
- name: Fetch Merge Commits for PRs and Generate Title and Body
|
||||||
run: |
|
run: |
|
||||||
|
# Ensure the files are initialized
|
||||||
|
> ${{ env.TEMP_DIR }}/commit_hashes.txt
|
||||||
|
> ${{ env.TEMP_DIR }}/pr_title.txt
|
||||||
|
> ${{ env.TEMP_DIR }}/pr_body.txt
|
||||||
|
|
||||||
|
# Write description to the PR body
|
||||||
|
echo "### Description:" >> ${{ env.TEMP_DIR }}/pr_body.txt
|
||||||
|
echo "Merging PRs from milestone \`$MILESTONE_NAME\` into target branch \`$TARGET_BRANCH\`." >> ${{ env.TEMP_DIR }}/pr_body.txt
|
||||||
|
echo "" >> ${{ env.TEMP_DIR }}/pr_body.txt
|
||||||
|
echo "### Need Merge PRs:" >> ${{ env.TEMP_DIR }}/pr_body.txt
|
||||||
|
|
||||||
|
pr_numbers_in_title=""
|
||||||
|
|
||||||
|
# Process sorted PR numbers and generate commit hashes
|
||||||
for pr_number in $(cat ${{ env.TEMP_DIR }}/pr_numbers.txt); do
|
for pr_number in $(cat ${{ env.TEMP_DIR }}/pr_numbers.txt); do
|
||||||
|
echo "Processing PR #$pr_number"
|
||||||
pr_details=$(curl -s -H "Authorization: token $BOT_TOKEN" \
|
pr_details=$(curl -s -H "Authorization: token $BOT_TOKEN" \
|
||||||
-H "Accept: application/vnd.github+json" \
|
-H "Accept: application/vnd.github+json" \
|
||||||
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
|
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
|
||||||
pr_title=$(echo "$pr_details" | jq -r '.title')
|
pr_title=$(echo "$pr_details" | jq -r '.title')
|
||||||
pr_body=$(echo "$pr_details" | jq -r '.body')
|
|
||||||
pr_creator=$(echo "$pr_details" | jq -r '.user.login')
|
|
||||||
merge_commit=$(echo "$pr_details" | jq -r '.merge_commit_sha')
|
merge_commit=$(echo "$pr_details" | jq -r '.merge_commit_sha')
|
||||||
short_commit_hash=$(echo "$merge_commit" | cut -c 1-7)
|
short_commit_hash=$(echo "$merge_commit" | cut -c 1-7)
|
||||||
|
|
||||||
if [ "$merge_commit" != "null" ]; then
|
# Append PR details to the body
|
||||||
git fetch origin
|
echo "- $pr_title: (#$pr_number) ($short_commit_hash)" >> ${{ env.TEMP_DIR }}/pr_body.txt
|
||||||
|
|
||||||
echo "Checking out target branch: $TARGET_BRANCH"
|
|
||||||
git checkout $TARGET_BRANCH
|
|
||||||
|
|
||||||
echo "Pulling latest changes from target branch: $TARGET_BRANCH"
|
if [ "$merge_commit" != "null" ];then
|
||||||
git pull origin $TARGET_BRANCH
|
echo "$merge_commit" >> ${{ env.TEMP_DIR }}/commit_hashes.txt
|
||||||
|
echo "#$pr_number" >> ${{ env.TEMP_DIR }}/pr_title.txt
|
||||||
cherry_pick_branch="cherry-pick-${short_commit_hash}"
|
pr_numbers_in_title="$pr_numbers_in_title #$pr_number"
|
||||||
git checkout -b $cherry_pick_branch
|
|
||||||
|
|
||||||
echo "Cherry-picking commit: $merge_commit"
|
|
||||||
if ! git cherry-pick "$merge_commit" --strategy=recursive -X theirs; then
|
|
||||||
echo "Cherry-pick encountered conflicts, attempting to continue..."
|
|
||||||
git cherry-pick --continue || { echo "Cherry-pick failed"; exit 1; }
|
|
||||||
fi
|
|
||||||
|
|
||||||
git remote set-url origin "https://${BOT_TOKEN}@github.com/${{ github.repository }}.git"
|
|
||||||
|
|
||||||
echo "Pushing branch: $cherry_pick_branch"
|
|
||||||
git push origin $cherry_pick_branch --force || { echo "Push failed"; exit 1; }
|
|
||||||
|
|
||||||
new_pr_title="$pr_title [Created by @$pr_creator from #$pr_number]"
|
|
||||||
new_pr_body="$pr_body
|
|
||||||
> This PR is created from original PR #$pr_number."
|
|
||||||
|
|
||||||
response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
|
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
https://api.github.com/repos/${{ github.repository }}/pulls \
|
|
||||||
-d "$(jq -n --arg title "$new_pr_title" \
|
|
||||||
--arg head "$cherry_pick_branch" \
|
|
||||||
--arg base "$TARGET_BRANCH" \
|
|
||||||
--arg body "$new_pr_body" \
|
|
||||||
'{title: $title, head: $head, base: $base, body: $body}')")
|
|
||||||
|
|
||||||
new_pr_number=$(echo "$response" | jq -r '.number')
|
|
||||||
echo "Created PR #$new_pr_number"
|
|
||||||
|
|
||||||
curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
|
||||||
-H "Accept: application/vnd.github+json" \
|
|
||||||
-d '{"labels": ["milestone-merge"]}' \
|
|
||||||
"https://api.github.com/repos/${{ github.repository }}/issues/$new_pr_number/labels"
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
commit_hashes=$(cat ${{ env.TEMP_DIR }}/commit_hashes.txt | tr '\n' ' ')
|
||||||
|
first_commit_hash=$(head -n 1 ${{ env.TEMP_DIR }}/commit_hashes.txt)
|
||||||
|
cherry_pick_branch="cherry-pick-${first_commit_hash:0:7}"
|
||||||
|
echo "COMMIT_HASHES=$commit_hashes" >> $GITHUB_ENV
|
||||||
|
echo "CHERRY_PICK_BRANCH=$cherry_pick_branch" >> $GITHUB_ENV
|
||||||
|
echo "pr_numbers_in_title=$pr_numbers_in_title" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Pull and Cherry-pick Commits, Then Push
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
|
run: |
|
||||||
|
# Fetch and pull the latest changes from the target branch
|
||||||
|
git fetch origin
|
||||||
|
git checkout $TARGET_BRANCH
|
||||||
|
git pull origin $TARGET_BRANCH
|
||||||
|
|
||||||
|
# Create a new branch for cherry-picking
|
||||||
|
git checkout -b $CHERRY_PICK_BRANCH
|
||||||
|
|
||||||
|
# Cherry-pick the commits and handle conflicts
|
||||||
|
for commit_hash in $COMMIT_HASHES; do
|
||||||
|
echo "Attempting to cherry-pick commit $commit_hash"
|
||||||
|
if ! git cherry-pick "$commit_hash" --strategy=recursive -X theirs; then
|
||||||
|
echo "Conflict detected for $commit_hash. Resolving with incoming changes."
|
||||||
|
conflict_files=$(git diff --name-only --diff-filter=U)
|
||||||
|
echo "Conflicting files:"
|
||||||
|
echo "$conflict_files"
|
||||||
|
|
||||||
|
for file in $conflict_files; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
echo "Resolving conflict for $file"
|
||||||
|
git add "$file"
|
||||||
|
else
|
||||||
|
echo "File $file has been deleted. Skipping."
|
||||||
|
git rm "$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Conflicts resolved. Continuing cherry-pick."
|
||||||
|
git cherry-pick --continue
|
||||||
|
else
|
||||||
|
echo "Cherry-pick successful for commit $commit_hash."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Push the cherry-pick branch to the repository
|
||||||
|
git remote set-url origin "https://${BOT_TOKEN}@github.com/${{ github.repository }}.git"
|
||||||
|
git push origin $CHERRY_PICK_BRANCH --force
|
||||||
|
|
||||||
|
- name: Create Pull Request
|
||||||
|
run: |
|
||||||
|
# Prepare and create the PR
|
||||||
|
pr_title="deps: Merge ${{ env.pr_numbers_in_title }} PRs into $TARGET_BRANCH"
|
||||||
|
pr_body=$(cat ${{ env.TEMP_DIR }}/pr_body.txt)
|
||||||
|
|
||||||
|
echo "Prepared PR title:"
|
||||||
|
echo "$pr_title"
|
||||||
|
echo "Prepared PR body:"
|
||||||
|
echo "$pr_body"
|
||||||
|
|
||||||
|
# Create the PR using the GitHub API
|
||||||
|
response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
https://api.github.com/repos/${{ github.repository }}/pulls \
|
||||||
|
-d "$(jq -n --arg title "$pr_title" \
|
||||||
|
--arg head "$CHERRY_PICK_BRANCH" \
|
||||||
|
--arg base "$TARGET_BRANCH" \
|
||||||
|
--arg body "$pr_body" \
|
||||||
|
'{title: $title, head: $head, base: $base, body: $body}')")
|
||||||
|
|
||||||
|
pr_number=$(echo "$response" | jq -r '.number')
|
||||||
|
echo "$pr_number" > ${{ env.TEMP_DIR }}/created_pr_number.txt
|
||||||
|
echo "Created PR #$pr_number"
|
||||||
|
|
||||||
|
- name: Add Label to Created Pull Request
|
||||||
|
run: |
|
||||||
|
# Add 'milestone-merge' label to the created PR
|
||||||
|
pr_number=$(cat ${{ env.TEMP_DIR }}/created_pr_number.txt)
|
||||||
|
echo "Adding label to PR #$pr_number"
|
||||||
|
|
||||||
|
curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-d '{"labels": ["milestone-merge"]}' \
|
||||||
|
"https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels"
|
||||||
|
|
||||||
|
echo "Added 'milestone-merge' label to PR #$pr_number."
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: main-repo
|
path: main-repo
|
||||||
|
|
||||||
# - name: Set up QEMU
|
- name: Set up QEMU
|
||||||
# uses: docker/setup-qemu-action@v3.3.0
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.8.0
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Build Docker image
|
- name: Build Docker image
|
||||||
id: build
|
id: build
|
||||||
@@ -38,8 +38,11 @@ jobs:
|
|||||||
context: ./main-repo
|
context: ./main-repo
|
||||||
load: true
|
load: true
|
||||||
tags: "openim/openim-server:local"
|
tags: "openim/openim-server:local"
|
||||||
cache-from: type=gha,scope=build
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max,scope=build
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Save Docker image to file
|
||||||
|
run: docker save -o image.tar openim/openim-server:local
|
||||||
|
|
||||||
- name: Checkout compose repository
|
- name: Checkout compose repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -63,12 +66,43 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd ${{ github.workspace }}/compose-repo
|
cd ${{ github.workspace }}/compose-repo
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
sleep 60
|
||||||
|
|
||||||
docker compose ps
|
# - name: Check openim-server health
|
||||||
|
# run: |
|
||||||
|
# timeout=300
|
||||||
|
# interval=30
|
||||||
|
# elapsed=0
|
||||||
|
# while [[ $elapsed -le $timeout ]]; do
|
||||||
|
# if ! docker exec openim-server mage check; then
|
||||||
|
# echo "openim-server is not ready, waiting..."
|
||||||
|
# sleep $interval
|
||||||
|
# elapsed=$(($elapsed + $interval))
|
||||||
|
# else
|
||||||
|
# echo "Health check successful"
|
||||||
|
# exit 0
|
||||||
|
# fi
|
||||||
|
# done
|
||||||
|
# echo "Health check failed after 5 minutes"
|
||||||
|
# exit 1
|
||||||
|
|
||||||
|
# - name: Check openim-chat health
|
||||||
|
# if: success()
|
||||||
|
# run: |
|
||||||
|
# if ! docker exec openim-chat mage check; then
|
||||||
|
# echo "openim-chat check failed"
|
||||||
|
# exit 1
|
||||||
|
# else
|
||||||
|
# echo "Health check successful"
|
||||||
|
# exit 0
|
||||||
|
# fi
|
||||||
|
|
||||||
|
- name: Load Docker image from file
|
||||||
|
run: docker load -i image.tar
|
||||||
|
|
||||||
- name: Extract metadata for Docker (tags, labels)
|
- name: Extract metadata for Docker (tags, labels)
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5.6.0
|
uses: docker/metadata-action@v5.5.1
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
openim/openim-server
|
openim/openim-server
|
||||||
@@ -78,27 +112,29 @@ jobs:
|
|||||||
type=ref,event=tag
|
type=ref,event=tag
|
||||||
type=schedule
|
type=schedule
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
# type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern=v{{version}}
|
type=semver,pattern=v{{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
type=semver,pattern=release-{{raw}}
|
type=semver,pattern=release-{{raw}}
|
||||||
type=sha
|
type=sha
|
||||||
type=raw,value=${{ github.event.inputs.tag }}
|
type=raw,value=${{ github.event.inputs.tag }}
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v3.3.0
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
- name: Log in to GitHub Container Registry
|
- name: Log in to GitHub Container Registry
|
||||||
uses: docker/login-action@v3.3.0
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Log in to Aliyun Container Registry
|
- name: Log in to Aliyun Container Registry
|
||||||
uses: docker/login-action@v3.3.0
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: registry.cn-hangzhou.aliyuncs.com
|
registry: registry.cn-hangzhou.aliyuncs.com
|
||||||
username: ${{ secrets.ALIREGISTRY_USERNAME }}
|
username: ${{ secrets.ALIREGISTRY_USERNAME }}
|
||||||
@@ -112,28 +148,3 @@ jobs:
|
|||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha,scope=build
|
|
||||||
cache-to: type=gha,mode=max,scope=build
|
|
||||||
|
|
||||||
- name: Verify multi-platform support
|
|
||||||
run: |
|
|
||||||
images=("openim/openim-server" "ghcr.io/openimsdk/openim-server" "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server")
|
|
||||||
for image in "${images[@]}"; do
|
|
||||||
for tag in $(echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n'); do
|
|
||||||
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
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|||||||
@@ -8,19 +8,40 @@ jobs:
|
|||||||
update-version:
|
update-version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TAG_VERSION: ${{ github.event.release.tag_name }}
|
TAG_VERSION: ${{ github.event.release.tag_name }}
|
||||||
steps:
|
steps:
|
||||||
# Step 1: Checkout the original repository's code
|
# Step 1: Checkout the original repository's code
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
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
|
# Step 2: Set up Git with official account
|
||||||
- name: Set up Git
|
- name: Set up Git
|
||||||
run: |
|
run: |
|
||||||
git config user.name "github-actions[bot]"
|
git config --global user.name "github-actions[bot]"
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
# Step 3: Check and delete existing tag
|
# Step 3: Check and delete existing tag
|
||||||
- name: Check and delete existing tag
|
- name: Check and delete existing tag
|
||||||
@@ -33,7 +54,8 @@ jobs:
|
|||||||
# Step 4: Update version file
|
# Step 4: Update version file
|
||||||
- name: Update version file
|
- name: Update version file
|
||||||
run: |
|
run: |
|
||||||
echo "${{ env.TAG_VERSION }}" > version/version
|
mkdir -p version
|
||||||
|
echo -n "${{ env.TAG_VERSION }}" > version/version
|
||||||
|
|
||||||
# Step 5: Commit and push changes
|
# Step 5: Commit and push changes
|
||||||
- name: Commit and push changes
|
- name: Commit and push changes
|
||||||
@@ -42,43 +64,56 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git add version/version
|
git add version/version
|
||||||
git commit -m "Update version to ${{ env.TAG_VERSION }}"
|
git commit -m "Update version to ${{ env.TAG_VERSION }}"
|
||||||
git push origin HEAD:${{ github.ref }}
|
|
||||||
|
|
||||||
# Step 6: Create and push tag
|
# Step 6: Update tag
|
||||||
- name: Create and push tag
|
- name: Update tag
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
run: |
|
||||||
git tag ${{ env.TAG_VERSION }}
|
git tag -fa ${{ env.TAG_VERSION }} -m "Update version to ${{ env.TAG_VERSION }}"
|
||||||
git push origin ${{ env.TAG_VERSION }}
|
git push origin ${{ env.TAG_VERSION }} --force
|
||||||
|
|
||||||
# Step 7: Find and Publish Draft Release
|
# Step 7: Find and Publish Draft Release
|
||||||
- name: Find and Publish Draft Release
|
- name: Find and Publish Draft Release
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
// Get the list of releases
|
const { owner, repo } = context.repo;
|
||||||
const releases = await github.rest.repos.listReleases({
|
const tagName = process.env.TAG_VERSION;
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo
|
|
||||||
});
|
|
||||||
|
|
||||||
// Find the draft release where the title and tag_name are the same
|
try {
|
||||||
const draftRelease = releases.data.find(release =>
|
let release;
|
||||||
release.draft && release.name === release.tag_name
|
try {
|
||||||
);
|
const response = await github.rest.repos.getReleaseByTag({
|
||||||
|
owner,
|
||||||
if (draftRelease) {
|
repo,
|
||||||
// Publish the draft release using the release_id
|
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}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await github.rest.repos.updateRelease({
|
await github.rest.repos.updateRelease({
|
||||||
owner: context.repo.owner,
|
owner,
|
||||||
repo: context.repo.repo,
|
repo,
|
||||||
release_id: draftRelease.id, // Use release_id
|
release_id: release.id,
|
||||||
draft: false
|
draft: false,
|
||||||
|
prerelease: release.prerelease
|
||||||
});
|
});
|
||||||
|
|
||||||
core.info(`Draft Release ${draftRelease.tag_name} published successfully.`);
|
const status = release.draft ? "was draft" : "was already published";
|
||||||
} else {
|
core.info(`Release ${tagName} ensured to be published (${status}).`);
|
||||||
core.info("No matching draft release found.");
|
|
||||||
}
|
} catch (error) {
|
||||||
|
core.warning(`Could not find or update release for tag ${tagName}: ${error.message}`);
|
||||||
|
}
|
||||||
|
|||||||
+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.mod $SERVER_DIR/
|
||||||
COPY --from=builder $SERVER_DIR/go.sum $SERVER_DIR/
|
COPY --from=builder $SERVER_DIR/go.sum $SERVER_DIR/
|
||||||
|
|
||||||
RUN go get github.com/openimsdk/gomake@v0.0.14-alpha.5
|
RUN go get github.com/openimsdk/gomake@v0.0.15-alpha.5
|
||||||
|
|
||||||
# Set the command to run when the container starts
|
# Set the command to run when the container starts
|
||||||
ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"]
|
ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"]
|
||||||
|
|||||||
+1
-10
@@ -5,13 +5,4 @@ etcd:
|
|||||||
username: ''
|
username: ''
|
||||||
password: ''
|
password: ''
|
||||||
|
|
||||||
rpcService:
|
|
||||||
user: user-rpc-service
|
|
||||||
friend: friend-rpc-service
|
|
||||||
msg: msg-rpc-service
|
|
||||||
push: push-rpc-service
|
|
||||||
messageGateway: messagegateway-rpc-service
|
|
||||||
group: group-rpc-service
|
|
||||||
auth: auth-rpc-service
|
|
||||||
conversation: conversation-rpc-service
|
|
||||||
third: third-rpc-service
|
|
||||||
|
|||||||
+19
-17
@@ -1,10 +1,12 @@
|
|||||||
groupCreated:
|
groupCreated:
|
||||||
isSendMsg: true
|
isSendMsg: true
|
||||||
# Deprecated. Fixed as 1.
|
# Reliability level of the message sending.
|
||||||
|
# Set to 1 to send only when online, 2 for guaranteed delivery.
|
||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
# Deprecated. Fixed as false.
|
# This setting is effective only when 'isSendMsg' is true.
|
||||||
|
# It controls whether to count unread messages.
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
# Configuration for offline push notifications.
|
# Configuration for offline push notifications.
|
||||||
offlinePush:
|
offlinePush:
|
||||||
# Enables or disables offline push notifications.
|
# Enables or disables offline push notifications.
|
||||||
enable: false
|
enable: false
|
||||||
@@ -31,7 +33,7 @@ joinGroupApplication:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: false
|
enable: true
|
||||||
title: joinGroupApplication title
|
title: joinGroupApplication title
|
||||||
desc: joinGroupApplication desc
|
desc: joinGroupApplication desc
|
||||||
ext: joinGroupApplication ext
|
ext: joinGroupApplication ext
|
||||||
@@ -51,7 +53,7 @@ groupApplicationAccepted:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: false
|
enable: true
|
||||||
title: groupApplicationAccepted title
|
title: groupApplicationAccepted title
|
||||||
desc: groupApplicationAccepted desc
|
desc: groupApplicationAccepted desc
|
||||||
ext: groupApplicationAccepted ext
|
ext: groupApplicationAccepted ext
|
||||||
@@ -61,7 +63,7 @@ groupApplicationRejected:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: false
|
enable: true
|
||||||
title: groupApplicationRejected title
|
title: groupApplicationRejected title
|
||||||
desc: groupApplicationRejected desc
|
desc: groupApplicationRejected desc
|
||||||
ext: groupApplicationRejected ext
|
ext: groupApplicationRejected ext
|
||||||
@@ -198,7 +200,7 @@ friendApplicationAdded:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: false
|
enable: true
|
||||||
title: Somebody applies to add you as a friend
|
title: Somebody applies to add you as a friend
|
||||||
desc: 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
|
ext: Somebody applies to add you as a friend
|
||||||
@@ -228,7 +230,7 @@ friendAdded:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: We have become friends
|
title: We have become friends
|
||||||
desc: We have become friends
|
desc: We have become friends
|
||||||
ext: We have become friends
|
ext: We have become friends
|
||||||
@@ -238,7 +240,7 @@ friendDeleted:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: deleted a friend
|
title: deleted a friend
|
||||||
desc: deleted a friend
|
desc: deleted a friend
|
||||||
ext: deleted a friend
|
ext: deleted a friend
|
||||||
@@ -248,7 +250,7 @@ friendRemarkSet:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: Your friend's profile has been changed
|
title: Your friend's profile has been changed
|
||||||
desc: Your friend's profile has been changed
|
desc: Your friend's profile has been changed
|
||||||
ext: Your friend's profile has been changed
|
ext: Your friend's profile has been changed
|
||||||
@@ -258,7 +260,7 @@ blackAdded:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: blocked a user
|
title: blocked a user
|
||||||
desc: blocked a user
|
desc: blocked a user
|
||||||
ext: blocked a user
|
ext: blocked a user
|
||||||
@@ -268,7 +270,7 @@ blackDeleted:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: Remove a blocked user
|
title: Remove a blocked user
|
||||||
desc: Remove a blocked user
|
desc: Remove a blocked user
|
||||||
ext: Remove a blocked user
|
ext: Remove a blocked user
|
||||||
@@ -278,7 +280,7 @@ friendInfoUpdated:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: friend info updated
|
title: friend info updated
|
||||||
desc: friend info updated
|
desc: friend info updated
|
||||||
ext: friend info updated
|
ext: friend info updated
|
||||||
@@ -289,7 +291,7 @@ userInfoUpdated:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: userInfo updated
|
title: userInfo updated
|
||||||
desc: userInfo updated
|
desc: userInfo updated
|
||||||
ext: userInfo updated
|
ext: userInfo updated
|
||||||
@@ -310,7 +312,7 @@ conversationChanged:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: conversation changed
|
title: conversation changed
|
||||||
desc: conversation changed
|
desc: conversation changed
|
||||||
ext: conversation changed
|
ext: conversation changed
|
||||||
@@ -320,7 +322,7 @@ conversationSetPrivate:
|
|||||||
reliabilityLevel: 1
|
reliabilityLevel: 1
|
||||||
unreadCount: false
|
unreadCount: false
|
||||||
offlinePush:
|
offlinePush:
|
||||||
enable: true
|
enable: false
|
||||||
title: burn after reading
|
title: burn after reading
|
||||||
desc: burn after reading
|
desc: burn after reading
|
||||||
ext: burn after reading
|
ext: burn after reading
|
||||||
|
|||||||
+15
-2
@@ -1,9 +1,22 @@
|
|||||||
secret: openIM123
|
secret: openIM123
|
||||||
|
rpcRegisterName:
|
||||||
|
user: user
|
||||||
|
friend: friend
|
||||||
|
msg: msg
|
||||||
|
push: push
|
||||||
|
messageGateway: messageGateway
|
||||||
|
group: group
|
||||||
|
auth: auth
|
||||||
|
conversation: conversation
|
||||||
|
third: third
|
||||||
|
|
||||||
imAdminUserID: [ imAdmin ]
|
imAdminUserID: [ imAdmin ]
|
||||||
|
|
||||||
# 1: For Android, iOS, Windows, Mac, and web platforms, only one instance can be online at a time
|
# 1: For Android, iOS, Windows, Mac, and web platforms, only one instance can be online at a time
|
||||||
multiLogin:
|
multiLogin:
|
||||||
policy: 1
|
policy: 1
|
||||||
# max num of tokens in one end
|
maxNumOneEnd: 30
|
||||||
maxNumOneEnd: 30
|
|
||||||
|
rpcMaxBodySize:
|
||||||
|
requestMaxBodySize: 8388608
|
||||||
|
responseMaxBodySize: 8388608
|
||||||
|
|||||||
+50
-3
@@ -99,15 +99,62 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
#KAFKA_HEAP_OPTS: "-Xms128m -Xmx256m"
|
#KAFKA_HEAP_OPTS: "-Xms128m -Xmx256m"
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
|
# Unique identifier for the Kafka node (required in controller mode)
|
||||||
KAFKA_CFG_NODE_ID: 0
|
KAFKA_CFG_NODE_ID: 0
|
||||||
|
# Defines the roles this Kafka node plays: broker, controller, or both
|
||||||
KAFKA_CFG_PROCESS_ROLES: controller,broker
|
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
|
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093
|
||||||
KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
|
# Specifies which listener is used for controller-to-controller communication
|
||||||
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
|
KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
|
||||||
|
# Default number of partitions for new topics
|
||||||
KAFKA_NUM_PARTITIONS: 8
|
KAFKA_NUM_PARTITIONS: 8
|
||||||
|
# Whether to enable automatic topic creation
|
||||||
KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "true"
|
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:
|
networks:
|
||||||
- openim
|
- openim
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ require (
|
|||||||
github.com/gorilla/websocket v1.5.1
|
github.com/gorilla/websocket v1.5.1
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/openimsdk/protocol v0.0.72-alpha.71
|
github.com/openimsdk/protocol v0.0.73-alpha.12
|
||||||
github.com/openimsdk/tools v0.0.50-alpha.72
|
github.com/openimsdk/tools v0.0.50-alpha.84
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.18.0
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
@@ -35,7 +35,7 @@ require (
|
|||||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||||
github.com/kelindar/bitmap v1.5.2
|
github.com/kelindar/bitmap v1.5.2
|
||||||
github.com/likexian/gokit v0.25.13
|
github.com/likexian/gokit v0.25.13
|
||||||
github.com/openimsdk/gomake v0.0.14-alpha.5
|
github.com/openimsdk/gomake v0.0.15-alpha.5
|
||||||
github.com/redis/go-redis/v9 v9.4.0
|
github.com/redis/go-redis/v9 v9.4.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
@@ -43,9 +43,6 @@ require (
|
|||||||
go.etcd.io/etcd/client/v3 v3.5.13
|
go.etcd.io/etcd/client/v3 v3.5.13
|
||||||
go.uber.org/automaxprocs v1.5.3
|
go.uber.org/automaxprocs v1.5.3
|
||||||
golang.org/x/sync v0.8.0
|
golang.org/x/sync v0.8.0
|
||||||
k8s.io/api v0.31.2
|
|
||||||
k8s.io/apimachinery v0.31.2
|
|
||||||
k8s.io/client-go v0.31.2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -201,6 +198,9 @@ require (
|
|||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gorm.io/gorm v1.25.8 // 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/klog/v2 v2.130.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||||
|
|||||||
@@ -345,12 +345,12 @@ github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA
|
|||||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
github.com/onsi/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 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
|
||||||
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
||||||
github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y=
|
github.com/openimsdk/gomake v0.0.15-alpha.5 h1:eEZCEHm+NsmcO3onXZPIUbGFCYPYbsX5beV3ZyOsGhY=
|
||||||
github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
|
github.com/openimsdk/gomake v0.0.15-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
|
||||||
github.com/openimsdk/protocol v0.0.72-alpha.71 h1:R3utzOlqepaJWTAmnfJi4ccUM/XIoFasSyjQMOipM70=
|
github.com/openimsdk/protocol v0.0.73-alpha.12 h1:2NYawXeHChYUeSme6QJ9pOLh+Empce2WmwEtbP4JvKk=
|
||||||
github.com/openimsdk/protocol v0.0.72-alpha.71/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw=
|
github.com/openimsdk/protocol v0.0.73-alpha.12/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw=
|
||||||
github.com/openimsdk/tools v0.0.50-alpha.72 h1:d/vaZjIfvrNp3EeRJEIiamBO7HiPx6CP4wiuq8NpfzY=
|
github.com/openimsdk/tools v0.0.50-alpha.84 h1:jN60Ys/0edZjL/TDmm/5VSJFP4pGYRipkWqhILJbq/8=
|
||||||
github.com/openimsdk/tools v0.0.50-alpha.72/go.mod h1:B+oqV0zdewN7OiEHYJm+hW+8/Te7B8tHHgD8rK5ZLZk=
|
github.com/openimsdk/tools v0.0.50-alpha.84/go.mod h1:n2poR3asX1e1XZce4O+MOWAp+X02QJRFvhcLCXZdzRo=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
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/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
|
|||||||
+311
-310
@@ -1,312 +1,313 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
//
|
||||||
"encoding/json"
|
//import (
|
||||||
"reflect"
|
// "encoding/json"
|
||||||
"strconv"
|
// "reflect"
|
||||||
"time"
|
// "strconv"
|
||||||
|
// "time"
|
||||||
"github.com/gin-gonic/gin"
|
//
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/apistruct"
|
// "github.com/gin-gonic/gin"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
// "github.com/openimsdk/open-im-server/v3/pkg/apistruct"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
// "github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
// "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
// "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
||||||
"github.com/openimsdk/tools/apiresp"
|
// "github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/errs"
|
// "github.com/openimsdk/tools/apiresp"
|
||||||
"github.com/openimsdk/tools/log"
|
// "github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/utils/runtimeenv"
|
// "github.com/openimsdk/tools/log"
|
||||||
clientv3 "go.etcd.io/etcd/client/v3"
|
// "github.com/openimsdk/tools/utils/runtimeenv"
|
||||||
)
|
// clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
//)
|
||||||
const (
|
//
|
||||||
// wait for Restart http call return
|
//const (
|
||||||
waitHttp = time.Millisecond * 200
|
// // wait for Restart http call return
|
||||||
)
|
// waitHttp = time.Millisecond * 200
|
||||||
|
//)
|
||||||
type ConfigManager struct {
|
//
|
||||||
imAdminUserID []string
|
//type ConfigManager struct {
|
||||||
config *config.AllConfig
|
// imAdminUserID []string
|
||||||
client *clientv3.Client
|
// config *config.AllConfig
|
||||||
|
// client *clientv3.Client
|
||||||
configPath string
|
//
|
||||||
runtimeEnv string
|
// configPath string
|
||||||
}
|
// runtimeEnv string
|
||||||
|
//}
|
||||||
func NewConfigManager(IMAdminUserID []string, cfg *config.AllConfig, client *clientv3.Client, configPath string, runtimeEnv string) *ConfigManager {
|
//
|
||||||
cm := &ConfigManager{
|
//func NewConfigManager(IMAdminUserID []string, cfg *config.AllConfig, client *clientv3.Client, configPath string, runtimeEnv string) *ConfigManager {
|
||||||
imAdminUserID: IMAdminUserID,
|
// cm := &ConfigManager{
|
||||||
config: cfg,
|
// imAdminUserID: IMAdminUserID,
|
||||||
client: client,
|
// config: cfg,
|
||||||
configPath: configPath,
|
// client: client,
|
||||||
runtimeEnv: runtimeEnv,
|
// configPath: configPath,
|
||||||
}
|
// runtimeEnv: runtimeEnv,
|
||||||
return cm
|
// }
|
||||||
}
|
// return cm
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) CheckAdmin(c *gin.Context) {
|
//
|
||||||
if err := authverify.CheckAdmin(c, cm.imAdminUserID); err != nil {
|
//func (cm *ConfigManager) CheckAdmin(c *gin.Context) {
|
||||||
apiresp.GinError(c, err)
|
// if err := authverify.CheckAdmin(c, cm.imAdminUserID); err != nil {
|
||||||
c.Abort()
|
// apiresp.GinError(c, err)
|
||||||
}
|
// c.Abort()
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) GetConfig(c *gin.Context) {
|
//
|
||||||
var req apistruct.GetConfigReq
|
//func (cm *ConfigManager) GetConfig(c *gin.Context) {
|
||||||
if err := c.BindJSON(&req); err != nil {
|
// var req apistruct.GetConfigReq
|
||||||
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
// if err := c.BindJSON(&req); err != nil {
|
||||||
return
|
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||||
}
|
// return
|
||||||
conf := cm.config.Name2Config(req.ConfigName)
|
// }
|
||||||
if conf == nil {
|
// conf := cm.config.Name2Config(req.ConfigName)
|
||||||
apiresp.GinError(c, errs.ErrArgs.WithDetail("config name not found").Wrap())
|
// if conf == nil {
|
||||||
return
|
// apiresp.GinError(c, errs.ErrArgs.WithDetail("config name not found").Wrap())
|
||||||
}
|
// return
|
||||||
b, err := json.Marshal(conf)
|
// }
|
||||||
if err != nil {
|
// b, err := json.Marshal(conf)
|
||||||
apiresp.GinError(c, err)
|
// if err != nil {
|
||||||
return
|
// apiresp.GinError(c, err)
|
||||||
}
|
// return
|
||||||
apiresp.GinSuccess(c, string(b))
|
// }
|
||||||
}
|
// apiresp.GinSuccess(c, string(b))
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) GetConfigList(c *gin.Context) {
|
//
|
||||||
var resp apistruct.GetConfigListResp
|
//func (cm *ConfigManager) GetConfigList(c *gin.Context) {
|
||||||
resp.ConfigNames = cm.config.GetConfigNames()
|
// var resp apistruct.GetConfigListResp
|
||||||
resp.Environment = runtimeenv.PrintRuntimeEnvironment()
|
// resp.ConfigNames = cm.config.GetConfigNames()
|
||||||
resp.Version = version.Version
|
// resp.Environment = runtimeenv.PrintRuntimeEnvironment()
|
||||||
|
// resp.Version = version.Version
|
||||||
apiresp.GinSuccess(c, resp)
|
//
|
||||||
}
|
// apiresp.GinSuccess(c, resp)
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) SetConfig(c *gin.Context) {
|
//
|
||||||
if cm.config.Discovery.Enable != config.ETCD {
|
//func (cm *ConfigManager) SetConfig(c *gin.Context) {
|
||||||
apiresp.GinError(c, errs.New("only etcd support set config").Wrap())
|
// if cm.config.Discovery.Enable != config.ETCD {
|
||||||
return
|
// apiresp.GinError(c, errs.New("only etcd support set config").Wrap())
|
||||||
}
|
// return
|
||||||
var req apistruct.SetConfigReq
|
// }
|
||||||
if err := c.BindJSON(&req); err != nil {
|
// var req apistruct.SetConfigReq
|
||||||
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
// if err := c.BindJSON(&req); err != nil {
|
||||||
return
|
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||||
}
|
// return
|
||||||
var err error
|
// }
|
||||||
switch req.ConfigName {
|
// var err error
|
||||||
case cm.config.Discovery.GetConfigFileName():
|
// switch req.ConfigName {
|
||||||
err = compareAndSave[config.Discovery](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Discovery.GetConfigFileName():
|
||||||
case cm.config.Kafka.GetConfigFileName():
|
// err = compareAndSave[config.Discovery](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Kafka](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Kafka.GetConfigFileName():
|
||||||
case cm.config.LocalCache.GetConfigFileName():
|
// err = compareAndSave[config.Kafka](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.LocalCache](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.LocalCache.GetConfigFileName():
|
||||||
case cm.config.Log.GetConfigFileName():
|
// err = compareAndSave[config.LocalCache](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Log](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Log.GetConfigFileName():
|
||||||
case cm.config.Minio.GetConfigFileName():
|
// err = compareAndSave[config.Log](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Minio](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Minio.GetConfigFileName():
|
||||||
case cm.config.Mongo.GetConfigFileName():
|
// err = compareAndSave[config.Minio](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Mongo](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Mongo.GetConfigFileName():
|
||||||
case cm.config.Notification.GetConfigFileName():
|
// err = compareAndSave[config.Mongo](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Notification](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Notification.GetConfigFileName():
|
||||||
case cm.config.API.GetConfigFileName():
|
// err = compareAndSave[config.Notification](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.API](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.API.GetConfigFileName():
|
||||||
case cm.config.CronTask.GetConfigFileName():
|
// err = compareAndSave[config.API](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.CronTask](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.CronTask.GetConfigFileName():
|
||||||
case cm.config.MsgGateway.GetConfigFileName():
|
// err = compareAndSave[config.CronTask](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.MsgGateway](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.MsgGateway.GetConfigFileName():
|
||||||
case cm.config.MsgTransfer.GetConfigFileName():
|
// err = compareAndSave[config.MsgGateway](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.MsgTransfer](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.MsgTransfer.GetConfigFileName():
|
||||||
case cm.config.Push.GetConfigFileName():
|
// err = compareAndSave[config.MsgTransfer](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Push](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Push.GetConfigFileName():
|
||||||
case cm.config.Auth.GetConfigFileName():
|
// err = compareAndSave[config.Push](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Auth](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Auth.GetConfigFileName():
|
||||||
case cm.config.Conversation.GetConfigFileName():
|
// err = compareAndSave[config.Auth](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Conversation](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Conversation.GetConfigFileName():
|
||||||
case cm.config.Friend.GetConfigFileName():
|
// err = compareAndSave[config.Conversation](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Friend](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Friend.GetConfigFileName():
|
||||||
case cm.config.Group.GetConfigFileName():
|
// err = compareAndSave[config.Friend](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Group](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Group.GetConfigFileName():
|
||||||
case cm.config.Msg.GetConfigFileName():
|
// err = compareAndSave[config.Group](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Msg](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Msg.GetConfigFileName():
|
||||||
case cm.config.Third.GetConfigFileName():
|
// err = compareAndSave[config.Msg](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Third](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Third.GetConfigFileName():
|
||||||
case cm.config.User.GetConfigFileName():
|
// err = compareAndSave[config.Third](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.User](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.User.GetConfigFileName():
|
||||||
case cm.config.Redis.GetConfigFileName():
|
// err = compareAndSave[config.User](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Redis](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Redis.GetConfigFileName():
|
||||||
case cm.config.Share.GetConfigFileName():
|
// err = compareAndSave[config.Redis](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Share](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Share.GetConfigFileName():
|
||||||
case cm.config.Webhooks.GetConfigFileName():
|
// err = compareAndSave[config.Share](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
err = compareAndSave[config.Webhooks](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
// case cm.config.Webhooks.GetConfigFileName():
|
||||||
default:
|
// err = compareAndSave[config.Webhooks](c, cm.config.Name2Config(req.ConfigName), &req, cm)
|
||||||
apiresp.GinError(c, errs.ErrArgs.Wrap())
|
// default:
|
||||||
return
|
// apiresp.GinError(c, errs.ErrArgs.Wrap())
|
||||||
}
|
// return
|
||||||
if err != nil {
|
// }
|
||||||
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
// if err != nil {
|
||||||
return
|
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||||
}
|
// return
|
||||||
apiresp.GinSuccess(c, nil)
|
// }
|
||||||
}
|
// apiresp.GinSuccess(c, nil)
|
||||||
|
//}
|
||||||
func compareAndSave[T any](c *gin.Context, old any, req *apistruct.SetConfigReq, cm *ConfigManager) error {
|
//
|
||||||
conf := new(T)
|
//func compareAndSave[T any](c *gin.Context, old any, req *apistruct.SetConfigReq, cm *ConfigManager) error {
|
||||||
err := json.Unmarshal([]byte(req.Data), &conf)
|
// conf := new(T)
|
||||||
if err != nil {
|
// err := json.Unmarshal([]byte(req.Data), &conf)
|
||||||
return errs.ErrArgs.WithDetail(err.Error()).Wrap()
|
// if err != nil {
|
||||||
}
|
// return errs.ErrArgs.WithDetail(err.Error()).Wrap()
|
||||||
eq := reflect.DeepEqual(old, conf)
|
// }
|
||||||
if eq {
|
// eq := reflect.DeepEqual(old, conf)
|
||||||
return nil
|
// if eq {
|
||||||
}
|
// return nil
|
||||||
data, err := json.Marshal(conf)
|
// }
|
||||||
if err != nil {
|
// data, err := json.Marshal(conf)
|
||||||
return errs.ErrArgs.WithDetail(err.Error()).Wrap()
|
// if err != nil {
|
||||||
}
|
// return errs.ErrArgs.WithDetail(err.Error()).Wrap()
|
||||||
_, err = cm.client.Put(c, etcd.BuildKey(req.ConfigName), string(data))
|
// }
|
||||||
if err != nil {
|
// _, err = cm.client.Put(c, etcd.BuildKey(req.ConfigName), string(data))
|
||||||
return errs.WrapMsg(err, "save to etcd failed")
|
// if err != nil {
|
||||||
}
|
// return errs.WrapMsg(err, "save to etcd failed")
|
||||||
return nil
|
// }
|
||||||
}
|
// return nil
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) ResetConfig(c *gin.Context) {
|
//
|
||||||
go func() {
|
//func (cm *ConfigManager) ResetConfig(c *gin.Context) {
|
||||||
if err := cm.resetConfig(c, true); err != nil {
|
// go func() {
|
||||||
log.ZError(c, "reset config err", err)
|
// if err := cm.resetConfig(c, true); err != nil {
|
||||||
}
|
// log.ZError(c, "reset config err", err)
|
||||||
}()
|
// }
|
||||||
apiresp.GinSuccess(c, nil)
|
// }()
|
||||||
}
|
// apiresp.GinSuccess(c, nil)
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) resetConfig(c *gin.Context, checkChange bool, ops ...clientv3.Op) error {
|
//
|
||||||
txn := cm.client.Txn(c)
|
//func (cm *ConfigManager) resetConfig(c *gin.Context, checkChange bool, ops ...clientv3.Op) error {
|
||||||
type initConf struct {
|
// txn := cm.client.Txn(c)
|
||||||
old any
|
// type initConf struct {
|
||||||
new any
|
// old any
|
||||||
}
|
// new any
|
||||||
configMap := map[string]*initConf{
|
// }
|
||||||
cm.config.Discovery.GetConfigFileName(): {old: &cm.config.Discovery, new: new(config.Discovery)},
|
// configMap := map[string]*initConf{
|
||||||
cm.config.Kafka.GetConfigFileName(): {old: &cm.config.Kafka, new: new(config.Kafka)},
|
// cm.config.Discovery.GetConfigFileName(): {old: &cm.config.Discovery, new: new(config.Discovery)},
|
||||||
cm.config.LocalCache.GetConfigFileName(): {old: &cm.config.LocalCache, new: new(config.LocalCache)},
|
// cm.config.Kafka.GetConfigFileName(): {old: &cm.config.Kafka, new: new(config.Kafka)},
|
||||||
cm.config.Log.GetConfigFileName(): {old: &cm.config.Log, new: new(config.Log)},
|
// cm.config.LocalCache.GetConfigFileName(): {old: &cm.config.LocalCache, new: new(config.LocalCache)},
|
||||||
cm.config.Minio.GetConfigFileName(): {old: &cm.config.Minio, new: new(config.Minio)},
|
// cm.config.Log.GetConfigFileName(): {old: &cm.config.Log, new: new(config.Log)},
|
||||||
cm.config.Mongo.GetConfigFileName(): {old: &cm.config.Mongo, new: new(config.Mongo)},
|
// cm.config.Minio.GetConfigFileName(): {old: &cm.config.Minio, new: new(config.Minio)},
|
||||||
cm.config.Notification.GetConfigFileName(): {old: &cm.config.Notification, new: new(config.Notification)},
|
// cm.config.Mongo.GetConfigFileName(): {old: &cm.config.Mongo, new: new(config.Mongo)},
|
||||||
cm.config.API.GetConfigFileName(): {old: &cm.config.API, new: new(config.API)},
|
// cm.config.Notification.GetConfigFileName(): {old: &cm.config.Notification, new: new(config.Notification)},
|
||||||
cm.config.CronTask.GetConfigFileName(): {old: &cm.config.CronTask, new: new(config.CronTask)},
|
// cm.config.API.GetConfigFileName(): {old: &cm.config.API, new: new(config.API)},
|
||||||
cm.config.MsgGateway.GetConfigFileName(): {old: &cm.config.MsgGateway, new: new(config.MsgGateway)},
|
// cm.config.CronTask.GetConfigFileName(): {old: &cm.config.CronTask, new: new(config.CronTask)},
|
||||||
cm.config.MsgTransfer.GetConfigFileName(): {old: &cm.config.MsgTransfer, new: new(config.MsgTransfer)},
|
// cm.config.MsgGateway.GetConfigFileName(): {old: &cm.config.MsgGateway, new: new(config.MsgGateway)},
|
||||||
cm.config.Push.GetConfigFileName(): {old: &cm.config.Push, new: new(config.Push)},
|
// cm.config.MsgTransfer.GetConfigFileName(): {old: &cm.config.MsgTransfer, new: new(config.MsgTransfer)},
|
||||||
cm.config.Auth.GetConfigFileName(): {old: &cm.config.Auth, new: new(config.Auth)},
|
// cm.config.Push.GetConfigFileName(): {old: &cm.config.Push, new: new(config.Push)},
|
||||||
cm.config.Conversation.GetConfigFileName(): {old: &cm.config.Conversation, new: new(config.Conversation)},
|
// cm.config.Auth.GetConfigFileName(): {old: &cm.config.Auth, new: new(config.Auth)},
|
||||||
cm.config.Friend.GetConfigFileName(): {old: &cm.config.Friend, new: new(config.Friend)},
|
// cm.config.Conversation.GetConfigFileName(): {old: &cm.config.Conversation, new: new(config.Conversation)},
|
||||||
cm.config.Group.GetConfigFileName(): {old: &cm.config.Group, new: new(config.Group)},
|
// cm.config.Friend.GetConfigFileName(): {old: &cm.config.Friend, new: new(config.Friend)},
|
||||||
cm.config.Msg.GetConfigFileName(): {old: &cm.config.Msg, new: new(config.Msg)},
|
// cm.config.Group.GetConfigFileName(): {old: &cm.config.Group, new: new(config.Group)},
|
||||||
cm.config.Third.GetConfigFileName(): {old: &cm.config.Third, new: new(config.Third)},
|
// cm.config.Msg.GetConfigFileName(): {old: &cm.config.Msg, new: new(config.Msg)},
|
||||||
cm.config.User.GetConfigFileName(): {old: &cm.config.User, new: new(config.User)},
|
// cm.config.Third.GetConfigFileName(): {old: &cm.config.Third, new: new(config.Third)},
|
||||||
cm.config.Redis.GetConfigFileName(): {old: &cm.config.Redis, new: new(config.Redis)},
|
// cm.config.User.GetConfigFileName(): {old: &cm.config.User, new: new(config.User)},
|
||||||
cm.config.Share.GetConfigFileName(): {old: &cm.config.Share, new: new(config.Share)},
|
// cm.config.Redis.GetConfigFileName(): {old: &cm.config.Redis, new: new(config.Redis)},
|
||||||
cm.config.Webhooks.GetConfigFileName(): {old: &cm.config.Webhooks, new: new(config.Webhooks)},
|
// 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 {
|
// changedKeys := make([]string, 0, len(configMap))
|
||||||
err := config.Load(
|
// for k, v := range configMap {
|
||||||
cm.configPath,
|
// err := config.Load(
|
||||||
k,
|
// cm.configPath,
|
||||||
config.EnvPrefixMap[k],
|
// k,
|
||||||
cm.runtimeEnv,
|
// config.EnvPrefixMap[k],
|
||||||
v.new,
|
// cm.runtimeEnv,
|
||||||
)
|
// v.new,
|
||||||
if err != nil {
|
// )
|
||||||
log.ZError(c, "load config failed", err)
|
// if err != nil {
|
||||||
continue
|
// log.ZError(c, "load config failed", err)
|
||||||
}
|
// continue
|
||||||
equal := reflect.DeepEqual(v.old, v.new)
|
// }
|
||||||
if !checkChange || !equal {
|
// equal := reflect.DeepEqual(v.old, v.new)
|
||||||
changedKeys = append(changedKeys, k)
|
// if !checkChange || !equal {
|
||||||
}
|
// changedKeys = append(changedKeys, k)
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
for _, k := range changedKeys {
|
//
|
||||||
data, err := json.Marshal(configMap[k].new)
|
// for _, k := range changedKeys {
|
||||||
if err != nil {
|
// data, err := json.Marshal(configMap[k].new)
|
||||||
log.ZError(c, "marshal config failed", err)
|
// if err != nil {
|
||||||
continue
|
// log.ZError(c, "marshal config failed", err)
|
||||||
}
|
// continue
|
||||||
ops = append(ops, clientv3.OpPut(etcd.BuildKey(k), string(data)))
|
// }
|
||||||
}
|
// ops = append(ops, clientv3.OpPut(etcd.BuildKey(k), string(data)))
|
||||||
if len(ops) > 0 {
|
// }
|
||||||
txn.Then(ops...)
|
// if len(ops) > 0 {
|
||||||
_, err := txn.Commit()
|
// txn.Then(ops...)
|
||||||
if err != nil {
|
// _, err := txn.Commit()
|
||||||
return errs.WrapMsg(err, "commit etcd txn failed")
|
// if err != nil {
|
||||||
}
|
// return errs.WrapMsg(err, "commit etcd txn failed")
|
||||||
}
|
// }
|
||||||
return nil
|
// }
|
||||||
}
|
// return nil
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) Restart(c *gin.Context) {
|
//
|
||||||
go cm.restart(c)
|
//func (cm *ConfigManager) Restart(c *gin.Context) {
|
||||||
apiresp.GinSuccess(c, nil)
|
// go cm.restart(c)
|
||||||
}
|
// apiresp.GinSuccess(c, nil)
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) restart(c *gin.Context) {
|
//
|
||||||
time.Sleep(waitHttp) // wait for Restart http call return
|
//func (cm *ConfigManager) restart(c *gin.Context) {
|
||||||
t := time.Now().Unix()
|
// time.Sleep(waitHttp) // wait for Restart http call return
|
||||||
_, err := cm.client.Put(c, etcd.BuildKey(etcd.RestartKey), strconv.Itoa(int(t)))
|
// t := time.Now().Unix()
|
||||||
if err != nil {
|
// _, err := cm.client.Put(c, etcd.BuildKey(etcd.RestartKey), strconv.Itoa(int(t)))
|
||||||
log.ZError(c, "restart etcd put key failed", err)
|
// 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 {
|
//func (cm *ConfigManager) SetEnableConfigManager(c *gin.Context) {
|
||||||
apiresp.GinError(c, errs.New("only etcd support config manager").Wrap())
|
// if cm.config.Discovery.Enable != config.ETCD {
|
||||||
return
|
// apiresp.GinError(c, errs.New("only etcd support config manager").Wrap())
|
||||||
}
|
// return
|
||||||
var req apistruct.SetEnableConfigManagerReq
|
// }
|
||||||
if err := c.BindJSON(&req); err != nil {
|
// var req apistruct.SetEnableConfigManagerReq
|
||||||
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
// if err := c.BindJSON(&req); err != nil {
|
||||||
return
|
// apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||||
}
|
// return
|
||||||
var enableStr string
|
// }
|
||||||
if req.Enable {
|
// var enableStr string
|
||||||
enableStr = etcd.Enable
|
// if req.Enable {
|
||||||
} else {
|
// enableStr = etcd.Enable
|
||||||
enableStr = etcd.Disable
|
// } else {
|
||||||
}
|
// enableStr = etcd.Disable
|
||||||
resp, err := cm.client.Get(c, etcd.BuildKey(etcd.EnableConfigCenterKey))
|
// }
|
||||||
if err != nil {
|
// resp, err := cm.client.Get(c, etcd.BuildKey(etcd.EnableConfigCenterKey))
|
||||||
apiresp.GinError(c, errs.WrapMsg(err, "getEnableConfigManager failed"))
|
// if err != nil {
|
||||||
return
|
// apiresp.GinError(c, errs.WrapMsg(err, "getEnableConfigManager failed"))
|
||||||
}
|
// return
|
||||||
if !(resp.Count > 0 && string(resp.Kvs[0].Value) == etcd.Enable) && req.Enable {
|
// }
|
||||||
go func() {
|
// if !(resp.Count > 0 && string(resp.Kvs[0].Value) == etcd.Enable) && req.Enable {
|
||||||
time.Sleep(waitHttp) // wait for Restart http call return
|
// go func() {
|
||||||
err := cm.resetConfig(c, false, clientv3.OpPut(etcd.BuildKey(etcd.EnableConfigCenterKey), enableStr))
|
// time.Sleep(waitHttp) // wait for Restart http call return
|
||||||
if err != nil {
|
// err := cm.resetConfig(c, false, clientv3.OpPut(etcd.BuildKey(etcd.EnableConfigCenterKey), enableStr))
|
||||||
log.ZError(c, "resetConfig failed", err)
|
// if err != nil {
|
||||||
}
|
// log.ZError(c, "resetConfig failed", err)
|
||||||
}()
|
// }
|
||||||
} else {
|
// }()
|
||||||
_, err = cm.client.Put(c, etcd.BuildKey(etcd.EnableConfigCenterKey), enableStr)
|
// } else {
|
||||||
if err != nil {
|
// _, err = cm.client.Put(c, etcd.BuildKey(etcd.EnableConfigCenterKey), enableStr)
|
||||||
apiresp.GinError(c, errs.WrapMsg(err, "setEnableConfigManager failed"))
|
// if err != nil {
|
||||||
return
|
// apiresp.GinError(c, errs.WrapMsg(err, "setEnableConfigManager failed"))
|
||||||
}
|
// return
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
apiresp.GinSuccess(c, nil)
|
//
|
||||||
}
|
// apiresp.GinSuccess(c, nil)
|
||||||
|
//}
|
||||||
func (cm *ConfigManager) GetEnableConfigManager(c *gin.Context) {
|
//
|
||||||
resp, err := cm.client.Get(c, etcd.BuildKey(etcd.EnableConfigCenterKey))
|
//func (cm *ConfigManager) GetEnableConfigManager(c *gin.Context) {
|
||||||
if err != nil {
|
// resp, err := cm.client.Get(c, etcd.BuildKey(etcd.EnableConfigCenterKey))
|
||||||
apiresp.GinError(c, errs.WrapMsg(err, "getEnableConfigManager failed"))
|
// if err != nil {
|
||||||
return
|
// apiresp.GinError(c, errs.WrapMsg(err, "getEnableConfigManager failed"))
|
||||||
}
|
// return
|
||||||
var enable bool
|
// }
|
||||||
if resp.Count > 0 && string(resp.Kvs[0].Value) == etcd.Enable {
|
// var enable bool
|
||||||
enable = true
|
// if resp.Count > 0 && string(resp.Kvs[0].Value) == etcd.Enable {
|
||||||
}
|
// enable = true
|
||||||
apiresp.GinSuccess(c, &apistruct.GetEnableConfigManagerResp{Enable: enable})
|
// }
|
||||||
}
|
// apiresp.GinSuccess(c, &apistruct.GetEnableConfigManagerResp{Enable: enable})
|
||||||
|
//}
|
||||||
|
|||||||
@@ -114,3 +114,7 @@ func (o *FriendApi) GetIncrementalBlacks(c *gin.Context) {
|
|||||||
func (o *FriendApi) GetFullFriendUserIDs(c *gin.Context) {
|
func (o *FriendApi) GetFullFriendUserIDs(c *gin.Context) {
|
||||||
a2r.Call(c, relation.FriendClient.GetFullFriendUserIDs, o.Client)
|
a2r.Call(c, relation.FriendClient.GetFullFriendUserIDs, o.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *FriendApi) GetSelfUnhandledApplyCount(c *gin.Context) {
|
||||||
|
a2r.Call(c, relation.FriendClient.GetSelfUnhandledApplyCount, o.Client)
|
||||||
|
}
|
||||||
|
|||||||
@@ -165,3 +165,7 @@ func (o *GroupApi) GetFullGroupMemberUserIDs(c *gin.Context) {
|
|||||||
func (o *GroupApi) GetFullJoinGroupIDs(c *gin.Context) {
|
func (o *GroupApi) GetFullJoinGroupIDs(c *gin.Context) {
|
||||||
a2r.Call(c, group.GroupClient.GetFullJoinGroupIDs, o.Client)
|
a2r.Call(c, group.GroupClient.GetFullJoinGroupIDs, o.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *GroupApi) GetGroupApplicationUnhandledCount(c *gin.Context) {
|
||||||
|
a2r.Call(c, group.GroupClient.GetGroupApplicationUnhandledCount, o.Client)
|
||||||
|
}
|
||||||
|
|||||||
+36
-60
@@ -1,17 +1,3 @@
|
|||||||
// 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
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -26,45 +12,46 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discovery"
|
"github.com/openimsdk/tools/mw"
|
||||||
disetcd "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
"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/open-im-server/v3/pkg/common/prommetrics"
|
||||||
|
"github.com/openimsdk/tools/discovery"
|
||||||
"github.com/openimsdk/tools/discovery/etcd"
|
"github.com/openimsdk/tools/discovery/etcd"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mw"
|
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
|
||||||
"github.com/openimsdk/tools/utils/jsonutil"
|
"github.com/openimsdk/tools/utils/jsonutil"
|
||||||
"github.com/openimsdk/tools/utils/network"
|
|
||||||
"github.com/openimsdk/tools/utils/runtimeenv"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
*conf.AllConfig
|
API config.API
|
||||||
|
Share config.Share
|
||||||
RuntimeEnv string
|
Discovery config.Discovery
|
||||||
ConfigPath string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(ctx context.Context, index int, config *Config) error {
|
func Start(ctx context.Context, index int, cfg *Config) error {
|
||||||
apiPort, err := datautil.GetElemByIndex(config.API.Api.Ports, index)
|
apiPort, err := datautil.GetElemByIndex(cfg.API.Api.Ports, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config.RuntimeEnv = runtimeenv.PrintRuntimeEnvironment()
|
var client discovery.SvcDiscoveryRegistry
|
||||||
|
|
||||||
client, err := kdisc.NewDiscoveryRegister(&config.Discovery, config.RuntimeEnv, []string{
|
// Determine whether zk is passed according to whether it is a clustered deployment
|
||||||
config.Discovery.RpcService.MessageGateway,
|
client, err = kdisc.NewDiscoveryRegister(&cfg.Discovery, &cfg.Share, []string{
|
||||||
|
cfg.Share.RpcRegisterName.MessageGateway,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errs.WrapMsg(err, "failed to register discovery service")
|
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")))
|
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
|
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
netDone = make(chan struct{}, 1)
|
netDone = make(chan struct{}, 1)
|
||||||
@@ -72,6 +59,10 @@ func Start(ctx context.Context, index int, config *Config) error {
|
|||||||
prometheusPort int
|
prometheusPort int
|
||||||
)
|
)
|
||||||
|
|
||||||
|
router, err := newGinRouter(ctx, client, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
registerIP, err := network.GetRpcRegisterIP("")
|
registerIP, err := network.GetRpcRegisterIP("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -88,20 +79,16 @@ func Start(ctx context.Context, index int, config *Config) error {
|
|||||||
return listener, port, nil
|
return listener, port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.API.Prometheus.AutoSetPorts && config.Discovery.Enable != conf.ETCD {
|
if cfg.API.Prometheus.AutoSetPorts && cfg.Discovery.Enable != config.ETCD {
|
||||||
return errs.New("only etcd support autoSetPorts", "RegisterName", "api").Wrap()
|
return errs.New("only etcd support autoSetPorts", "RegisterName", "api").Wrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
router, err := newGinRouter(ctx, client, config)
|
if cfg.API.Prometheus.Enable {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if config.API.Prometheus.Enable {
|
|
||||||
var (
|
var (
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
)
|
)
|
||||||
|
|
||||||
if config.API.Prometheus.AutoSetPorts {
|
if cfg.API.Prometheus.AutoSetPorts {
|
||||||
listener, prometheusPort, err = getAutoPort()
|
listener, prometheusPort, err = getAutoPort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -114,7 +101,7 @@ func Start(ctx context.Context, index int, config *Config) error {
|
|||||||
return errs.WrapMsg(err, "etcd put err")
|
return errs.WrapMsg(err, "etcd put err")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
prometheusPort, err = datautil.GetElemByIndex(config.API.Prometheus.Ports, index)
|
prometheusPort, err = datautil.GetElemByIndex(cfg.API.Prometheus.Ports, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -132,41 +119,30 @@ func Start(ctx context.Context, index int, config *Config) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
address := net.JoinHostPort(network.GetListenIP(config.API.Api.ListenIP), strconv.Itoa(apiPort))
|
address := net.JoinHostPort(network.GetListenIP(cfg.API.Api.ListenIP), strconv.Itoa(apiPort))
|
||||||
|
|
||||||
server := http.Server{Addr: address, Handler: router}
|
server := http.Server{Addr: address, Handler: router}
|
||||||
log.CInfo(ctx, "API server is initializing", "runtimeEnv", config.RuntimeEnv, "address", address, "apiPort", apiPort, "prometheusPort", prometheusPort)
|
log.CInfo(ctx, "API server is initializing", "address", address, "apiPort", apiPort, "prometheusPort", prometheusPort)
|
||||||
go func() {
|
go func() {
|
||||||
err = server.ListenAndServe()
|
err = server.ListenAndServe()
|
||||||
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
netErr = errs.WrapMsg(err, fmt.Sprintf("api start err: %s", server.Addr))
|
netErr = errs.WrapMsg(err, fmt.Sprintf("api start err: %s", server.Addr))
|
||||||
netDone <- struct{}{}
|
netDone <- struct{}{}
|
||||||
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if config.Discovery.Enable == conf.ETCD {
|
|
||||||
cm := disetcd.NewConfigManager(client.(*etcd.SvcDiscoveryRegistryImpl).GetClient(), config.GetConfigNames())
|
|
||||||
cm.Watch(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGTERM)
|
signal.Notify(sigs, syscall.SIGTERM)
|
||||||
|
|
||||||
shutdown := func() error {
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
defer cancel()
|
||||||
defer cancel()
|
|
||||||
err := server.Shutdown(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return errs.WrapMsg(err, "shutdown err")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
disetcd.RegisterShutDown(shutdown)
|
|
||||||
select {
|
select {
|
||||||
case <-sigs:
|
case <-sigs:
|
||||||
program.SIGTERMExit()
|
program.SIGTERMExit()
|
||||||
if err := shutdown(); err != nil {
|
err := server.Shutdown(ctx)
|
||||||
return err
|
if err != nil {
|
||||||
|
return errs.WrapMsg(err, "shutdown err")
|
||||||
}
|
}
|
||||||
case <-netDone:
|
case <-netDone:
|
||||||
close(netDone)
|
close(netDone)
|
||||||
|
|||||||
+61
-21
@@ -2,10 +2,14 @@ package jssdk
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
|
||||||
"sort"
|
"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/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/openimsdk/protocol/conversation"
|
"github.com/openimsdk/protocol/conversation"
|
||||||
"github.com/openimsdk/protocol/jssdk"
|
"github.com/openimsdk/protocol/jssdk"
|
||||||
"github.com/openimsdk/protocol/msg"
|
"github.com/openimsdk/protocol/msg"
|
||||||
@@ -109,10 +113,7 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
|||||||
if len(conversationIDs) == 0 {
|
if len(conversationIDs) == 0 {
|
||||||
return &jssdk.GetActiveConversationsResp{}, nil
|
return &jssdk.GetActiveConversationsResp{}, nil
|
||||||
}
|
}
|
||||||
readSeq, err := x.msgClient.GetHasReadSeqs(ctx, conversationIDs, req.OwnerUserID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
activeConversation, err := x.msgClient.GetActiveConversation(ctx, conversationIDs)
|
activeConversation, err := x.msgClient.GetActiveConversation(ctx, conversationIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -120,6 +121,10 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
|||||||
if len(activeConversation) == 0 {
|
if len(activeConversation) == 0 {
|
||||||
return &jssdk.GetActiveConversationsResp{}, nil
|
return &jssdk.GetActiveConversationsResp{}, nil
|
||||||
}
|
}
|
||||||
|
readSeq, err := x.msgClient.GetHasReadSeqs(ctx, conversationIDs, req.OwnerUserID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
sortConversations := sortActiveConversations{
|
sortConversations := sortActiveConversations{
|
||||||
Conversation: activeConversation,
|
Conversation: activeConversation,
|
||||||
}
|
}
|
||||||
@@ -147,6 +152,7 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
x.checkMessagesAndGetLastMessage(ctx, req.OwnerUserID, msgs)
|
||||||
conversationMap := datautil.SliceToMap(conversations, func(c *conversation.Conversation) string {
|
conversationMap := datautil.SliceToMap(conversations, func(c *conversation.Conversation) string {
|
||||||
return c.ConversationID
|
return c.ConversationID
|
||||||
})
|
})
|
||||||
@@ -156,16 +162,15 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
|||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var lastMsg *sdkws.MsgData
|
|
||||||
if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
|
if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
|
||||||
lastMsg = msgList.Msgs[0]
|
resp = append(resp, &jssdk.ConversationMsg{
|
||||||
|
Conversation: conv,
|
||||||
|
LastMsg: msgList.Msgs[0],
|
||||||
|
MaxSeq: c.MaxSeq,
|
||||||
|
ReadSeq: readSeq[c.ConversationID],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
resp = append(resp, &jssdk.ConversationMsg{
|
|
||||||
Conversation: conv,
|
|
||||||
LastMsg: lastMsg,
|
|
||||||
MaxSeq: c.MaxSeq,
|
|
||||||
ReadSeq: readSeq[c.ConversationID],
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if err := x.fillConversations(ctx, resp); err != nil {
|
if err := x.fillConversations(ctx, resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -219,18 +224,18 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
x.checkMessagesAndGetLastMessage(ctx, req.OwnerUserID, msgs)
|
||||||
resp := make([]*jssdk.ConversationMsg, 0, len(conversations))
|
resp := make([]*jssdk.ConversationMsg, 0, len(conversations))
|
||||||
for _, c := range conversations {
|
for _, c := range conversations {
|
||||||
var lastMsg *sdkws.MsgData
|
|
||||||
if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
|
if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
|
||||||
lastMsg = msgList.Msgs[0]
|
resp = append(resp, &jssdk.ConversationMsg{
|
||||||
|
Conversation: c,
|
||||||
|
LastMsg: msgList.Msgs[0],
|
||||||
|
MaxSeq: maxSeqs[c.ConversationID],
|
||||||
|
ReadSeq: readSeqs[c.ConversationID],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
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 {
|
if err := x.fillConversations(ctx, resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -247,3 +252,38 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
|
|||||||
UnreadCount: unreadCount,
|
UnreadCount: unreadCount,
|
||||||
}, nil
|
}, 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}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ package jssdk
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/openimsdk/tools/a2r"
|
"github.com/openimsdk/tools/a2r"
|
||||||
"github.com/openimsdk/tools/apiresp"
|
"github.com/openimsdk/tools/apiresp"
|
||||||
@@ -12,6 +9,8 @@ import (
|
|||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func field[A, B, C any](ctx context.Context, fn func(ctx context.Context, req *A, opts ...grpc.CallOption) (*B, error), req *A, get func(*B) C) (C, error) {
|
func field[A, B, C any](ctx context.Context, fn func(ctx context.Context, req *A, opts ...grpc.CallOption) (*B, error), req *A, get func(*B) C) (C, error) {
|
||||||
|
|||||||
+19
-31
@@ -248,44 +248,24 @@ func (m *MessageApi) SendMessage(c *gin.Context) {
|
|||||||
|
|
||||||
func (m *MessageApi) SendBusinessNotification(c *gin.Context) {
|
func (m *MessageApi) SendBusinessNotification(c *gin.Context) {
|
||||||
req := struct {
|
req := struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
SendUserID string `json:"sendUserID" binding:"required"`
|
SendUserID string `json:"sendUserID" binding:"required"`
|
||||||
RecvUserID string `json:"recvUserID"`
|
RecvUserID string `json:"recvUserID" binding:"required"`
|
||||||
RecvGroupID string `json:"recvGroupID"`
|
|
||||||
SendMsg bool `json:"sendMsg"`
|
|
||||||
ReliabilityLevel *int `json:"reliabilityLevel"`
|
|
||||||
}{}
|
}{}
|
||||||
if err := c.BindJSON(&req); err != nil {
|
if err := c.BindJSON(&req); err != nil {
|
||||||
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.RecvUserID == "" && req.RecvGroupID == "" {
|
|
||||||
apiresp.GinError(c, errs.ErrArgs.WrapMsg("recvUserID and recvGroupID cannot be empty at the same time"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if req.RecvUserID != "" && req.RecvGroupID != "" {
|
|
||||||
apiresp.GinError(c, errs.ErrArgs.WrapMsg("recvUserID and recvGroupID cannot be set at the same time"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var sessionType int32
|
|
||||||
if req.RecvUserID != "" {
|
|
||||||
sessionType = constant.SingleChatType
|
|
||||||
} else {
|
|
||||||
sessionType = constant.ReadGroupChatType
|
|
||||||
}
|
|
||||||
if req.ReliabilityLevel == nil {
|
|
||||||
req.ReliabilityLevel = datautil.ToPtr(1)
|
|
||||||
}
|
|
||||||
if !authverify.IsAppManagerUid(c, m.imAdminUserID) {
|
if !authverify.IsAppManagerUid(c, m.imAdminUserID) {
|
||||||
apiresp.GinError(c, errs.ErrNoPermission.WrapMsg("only app manager can send message"))
|
apiresp.GinError(c, errs.ErrNoPermission.WrapMsg("only app manager can send message"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sendMsgReq := msg.SendMsgReq{
|
sendMsgReq := msg.SendMsgReq{
|
||||||
MsgData: &sdkws.MsgData{
|
MsgData: &sdkws.MsgData{
|
||||||
SendID: req.SendUserID,
|
SendID: req.SendUserID,
|
||||||
RecvID: req.RecvUserID,
|
RecvID: req.RecvUserID,
|
||||||
GroupID: req.RecvGroupID,
|
|
||||||
Content: []byte(jsonutil.StructToJsonString(&sdkws.NotificationElem{
|
Content: []byte(jsonutil.StructToJsonString(&sdkws.NotificationElem{
|
||||||
Detail: jsonutil.StructToJsonString(&struct {
|
Detail: jsonutil.StructToJsonString(&struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
@@ -294,14 +274,14 @@ func (m *MessageApi) SendBusinessNotification(c *gin.Context) {
|
|||||||
})),
|
})),
|
||||||
MsgFrom: constant.SysMsgType,
|
MsgFrom: constant.SysMsgType,
|
||||||
ContentType: constant.BusinessNotification,
|
ContentType: constant.BusinessNotification,
|
||||||
SessionType: sessionType,
|
SessionType: constant.SingleChatType,
|
||||||
CreateTime: timeutil.GetCurrentTimestampByMill(),
|
CreateTime: timeutil.GetCurrentTimestampByMill(),
|
||||||
ClientMsgID: idutil.GetMsgIDByMD5(mcontext.GetOpUserID(c)),
|
ClientMsgID: idutil.GetMsgIDByMD5(mcontext.GetOpUserID(c)),
|
||||||
Options: config.GetOptionsByNotification(config.NotificationConfig{
|
Options: config.GetOptionsByNotification(config.NotificationConfig{
|
||||||
IsSendMsg: req.SendMsg,
|
IsSendMsg: false,
|
||||||
ReliabilityLevel: *req.ReliabilityLevel,
|
ReliabilityLevel: 1,
|
||||||
UnreadCount: false,
|
UnreadCount: false,
|
||||||
}),
|
}, nil),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
respPb, err := m.Client.SendMsg(c, &sendMsgReq)
|
respPb, err := m.Client.SendMsg(c, &sendMsgReq)
|
||||||
@@ -391,3 +371,11 @@ func (m *MessageApi) SearchMsg(c *gin.Context) {
|
|||||||
func (m *MessageApi) GetServerTime(c *gin.Context) {
|
func (m *MessageApi) GetServerTime(c *gin.Context) {
|
||||||
a2r.Call(c, msg.MsgClient.GetServerTime, m.Client)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"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/prommetrics"
|
||||||
"github.com/openimsdk/tools/apiresp"
|
"github.com/openimsdk/tools/apiresp"
|
||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
@@ -20,18 +20,18 @@ type PrometheusDiscoveryApi struct {
|
|||||||
client *clientv3.Client
|
client *clientv3.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPrometheusDiscoveryApi(config *Config, client discovery.SvcDiscoveryRegistry) *PrometheusDiscoveryApi {
|
func NewPrometheusDiscoveryApi(cfg *Config, client discovery.SvcDiscoveryRegistry) *PrometheusDiscoveryApi {
|
||||||
api := &PrometheusDiscoveryApi{
|
api := &PrometheusDiscoveryApi{
|
||||||
config: config,
|
config: cfg,
|
||||||
}
|
}
|
||||||
if config.Discovery.Enable == conf.ETCD {
|
if cfg.Discovery.Enable == config.ETCD {
|
||||||
api.client = client.(*etcd.SvcDiscoveryRegistryImpl).GetClient()
|
api.client = client.(*etcd.SvcDiscoveryRegistryImpl).GetClient()
|
||||||
}
|
}
|
||||||
return api
|
return api
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Enable(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Enable(c *gin.Context) {
|
||||||
if p.config.Discovery.Enable != conf.ETCD {
|
if p.config.Discovery.Enable != config.ETCD {
|
||||||
c.JSON(http.StatusOK, []struct{}{})
|
c.JSON(http.StatusOK, []struct{}{})
|
||||||
c.Abort()
|
c.Abort()
|
||||||
}
|
}
|
||||||
@@ -74,39 +74,39 @@ func (p *PrometheusDiscoveryApi) Api(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) User(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) User(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.User)
|
p.discovery(c, p.config.Share.RpcRegisterName.User)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Group(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Group(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.Group)
|
p.discovery(c, p.config.Share.RpcRegisterName.Group)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Msg(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Msg(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.Msg)
|
p.discovery(c, p.config.Share.RpcRegisterName.Msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Friend(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Friend(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.Friend)
|
p.discovery(c, p.config.Share.RpcRegisterName.Friend)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Conversation(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Conversation(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.Conversation)
|
p.discovery(c, p.config.Share.RpcRegisterName.Conversation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Third(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Third(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.Third)
|
p.discovery(c, p.config.Share.RpcRegisterName.Third)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Auth(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Auth(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.Auth)
|
p.discovery(c, p.config.Share.RpcRegisterName.Auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) Push(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) Push(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.Push)
|
p.discovery(c, p.config.Share.RpcRegisterName.Push)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) MessageGateway(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) MessageGateway(c *gin.Context) {
|
||||||
p.discovery(c, p.config.Discovery.RpcService.MessageGateway)
|
p.discovery(c, p.config.Share.RpcRegisterName.MessageGateway)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusDiscoveryApi) MessageTransfer(c *gin.Context) {
|
func (p *PrometheusDiscoveryApi) MessageTransfer(c *gin.Context) {
|
||||||
|
|||||||
+28
-47
@@ -5,29 +5,29 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-contrib/gzip"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/gin-gonic/gin/binding"
|
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/api/jssdk"
|
|
||||||
"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/servererrs"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||||
pbAuth "github.com/openimsdk/protocol/auth"
|
pbAuth "github.com/openimsdk/protocol/auth"
|
||||||
"github.com/openimsdk/protocol/constant"
|
|
||||||
"github.com/openimsdk/protocol/conversation"
|
"github.com/openimsdk/protocol/conversation"
|
||||||
"github.com/openimsdk/protocol/group"
|
"github.com/openimsdk/protocol/group"
|
||||||
"github.com/openimsdk/protocol/msg"
|
"github.com/openimsdk/protocol/msg"
|
||||||
"github.com/openimsdk/protocol/relation"
|
"github.com/openimsdk/protocol/relation"
|
||||||
"github.com/openimsdk/protocol/third"
|
"github.com/openimsdk/protocol/third"
|
||||||
"github.com/openimsdk/protocol/user"
|
"github.com/openimsdk/protocol/user"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/v3/internal/api/jssdk"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/gzip"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"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/protocol/constant"
|
||||||
"github.com/openimsdk/tools/apiresp"
|
"github.com/openimsdk/tools/apiresp"
|
||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
"github.com/openimsdk/tools/discovery/etcd"
|
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mw"
|
"github.com/openimsdk/tools/mw"
|
||||||
clientv3 "go.etcd.io/etcd/client/v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -52,32 +52,32 @@ func prommetricsGin() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cfg *Config) (*gin.Engine, error) {
|
func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, config *Config) (*gin.Engine, error) {
|
||||||
authConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Auth)
|
authConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
userConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
groupConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Group)
|
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
friendConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Friend)
|
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conversationConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Conversation)
|
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
thirdConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Third)
|
thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
msgConn, err := client.GetConn(ctx, cfg.Discovery.RpcService.Msg)
|
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
||||||
_ = v.RegisterValidation("required_if", RequiredIf)
|
_ = v.RegisterValidation("required_if", RequiredIf)
|
||||||
}
|
}
|
||||||
switch cfg.API.Api.CompressionLevel {
|
switch config.API.Api.CompressionLevel {
|
||||||
case NoCompression:
|
case NoCompression:
|
||||||
case DefaultCompression:
|
case DefaultCompression:
|
||||||
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||||
@@ -95,12 +95,11 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
case BestSpeed:
|
case BestSpeed:
|
||||||
r.Use(gzip.Gzip(gzip.BestSpeed))
|
r.Use(gzip.Gzip(gzip.BestSpeed))
|
||||||
}
|
}
|
||||||
r.Use(prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(),
|
r.Use(prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(), mw.GinParseOperationID(), GinParseToken(rpcli.NewAuthClient(authConn)))
|
||||||
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)
|
||||||
u := NewUserApi(user.NewUserClient(userConn), client, cfg.Discovery.RpcService)
|
userRouterGroup := r.Group("/user")
|
||||||
{
|
{
|
||||||
userRouterGroup := r.Group("/user")
|
|
||||||
userRouterGroup.POST("/user_register", u.UserRegister)
|
userRouterGroup.POST("/user_register", u.UserRegister)
|
||||||
userRouterGroup.POST("/update_user_info", u.UpdateUserInfo)
|
userRouterGroup.POST("/update_user_info", u.UpdateUserInfo)
|
||||||
userRouterGroup.POST("/update_user_info_ex", u.UpdateUserInfoEx)
|
userRouterGroup.POST("/update_user_info_ex", u.UpdateUserInfoEx)
|
||||||
@@ -150,6 +149,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
friendRouterGroup.POST("/update_friends", f.UpdateFriends)
|
friendRouterGroup.POST("/update_friends", f.UpdateFriends)
|
||||||
friendRouterGroup.POST("/get_incremental_friends", f.GetIncrementalFriends)
|
friendRouterGroup.POST("/get_incremental_friends", f.GetIncrementalFriends)
|
||||||
friendRouterGroup.POST("/get_full_friend_user_ids", f.GetFullFriendUserIDs)
|
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(group.NewGroupClient(groupConn))
|
||||||
@@ -186,6 +186,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
groupRouterGroup.POST("/get_incremental_group_members_batch", g.GetIncrementalGroupMemberBatch)
|
groupRouterGroup.POST("/get_incremental_group_members_batch", g.GetIncrementalGroupMemberBatch)
|
||||||
groupRouterGroup.POST("/get_full_group_member_user_ids", g.GetFullGroupMemberUserIDs)
|
groupRouterGroup.POST("/get_full_group_member_user_ids", g.GetFullGroupMemberUserIDs)
|
||||||
groupRouterGroup.POST("/get_full_join_group_ids", g.GetFullJoinGroupIDs)
|
groupRouterGroup.POST("/get_full_join_group_ids", g.GetFullJoinGroupIDs)
|
||||||
|
groupRouterGroup.POST("/get_group_application_unhandled_count", g.GetGroupApplicationUnhandledCount)
|
||||||
}
|
}
|
||||||
// certificate
|
// certificate
|
||||||
{
|
{
|
||||||
@@ -199,7 +200,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
}
|
}
|
||||||
// Third service
|
// Third service
|
||||||
{
|
{
|
||||||
t := NewThirdApi(third.NewThirdClient(thirdConn), cfg.API.Prometheus.GrafanaURL)
|
t := NewThirdApi(third.NewThirdClient(thirdConn), config.API.Prometheus.GrafanaURL)
|
||||||
thirdGroup := r.Group("/third")
|
thirdGroup := r.Group("/third")
|
||||||
thirdGroup.GET("/prometheus", t.GetPrometheus)
|
thirdGroup.GET("/prometheus", t.GetPrometheus)
|
||||||
thirdGroup.POST("/fcm_update_token", t.FcmUpdateToken)
|
thirdGroup.POST("/fcm_update_token", t.FcmUpdateToken)
|
||||||
@@ -223,7 +224,6 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
objectGroup.GET("/*name", t.ObjectRedirect)
|
objectGroup.GET("/*name", t.ObjectRedirect)
|
||||||
}
|
}
|
||||||
// Message
|
// Message
|
||||||
m := NewMessageApi(msg.NewMsgClient(msgConn), rpcli.NewUserClient(userConn), cfg.Share.IMAdminUserID)
|
|
||||||
{
|
{
|
||||||
msgGroup := r.Group("/msg")
|
msgGroup := r.Group("/msg")
|
||||||
msgGroup.POST("/newest_seq", m.GetSeq)
|
msgGroup.POST("/newest_seq", m.GetSeq)
|
||||||
@@ -280,7 +280,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
jssdk.POST("/get_active_conversations", j.GetActiveConversations)
|
jssdk.POST("/get_active_conversations", j.GetActiveConversations)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
pd := NewPrometheusDiscoveryApi(cfg, client)
|
pd := NewPrometheusDiscoveryApi(config, client)
|
||||||
proDiscoveryGroup := r.Group("/prometheus_discovery", pd.Enable)
|
proDiscoveryGroup := r.Group("/prometheus_discovery", pd.Enable)
|
||||||
proDiscoveryGroup.GET("/api", pd.Api)
|
proDiscoveryGroup.GET("/api", pd.Api)
|
||||||
proDiscoveryGroup.GET("/user", pd.User)
|
proDiscoveryGroup.GET("/user", pd.User)
|
||||||
@@ -294,25 +294,6 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, cf
|
|||||||
proDiscoveryGroup.GET("/msg_gateway", pd.MessageGateway)
|
proDiscoveryGroup.GET("/msg_gateway", pd.MessageGateway)
|
||||||
proDiscoveryGroup.GET("/msg_transfer", pd.MessageTransfer)
|
proDiscoveryGroup.GET("/msg_transfer", pd.MessageTransfer)
|
||||||
}
|
}
|
||||||
|
|
||||||
var etcdClient *clientv3.Client
|
|
||||||
if cfg.Discovery.Enable == config.ETCD {
|
|
||||||
etcdClient = client.(*etcd.SvcDiscoveryRegistryImpl).GetClient()
|
|
||||||
}
|
|
||||||
cm := NewConfigManager(cfg.Share.IMAdminUserID, cfg.AllConfig, etcdClient, cfg.ConfigPath, cfg.RuntimeEnv)
|
|
||||||
{
|
|
||||||
|
|
||||||
configGroup := r.Group("/config", cm.CheckAdmin)
|
|
||||||
configGroup.POST("/get_config_list", cm.GetConfigList)
|
|
||||||
configGroup.POST("/get_config", cm.GetConfig)
|
|
||||||
configGroup.POST("/set_config", cm.SetConfig)
|
|
||||||
configGroup.POST("/reset_config", cm.ResetConfig)
|
|
||||||
configGroup.POST("/set_enable_config_manager", cm.SetEnableConfigManager)
|
|
||||||
configGroup.POST("/get_enable_config_manager", cm.GetEnableConfigManager)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
r.POST("/restart", cm.CheckAdmin, cm.Restart)
|
|
||||||
}
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ import (
|
|||||||
type UserApi struct {
|
type UserApi struct {
|
||||||
Client user.UserClient
|
Client user.UserClient
|
||||||
discov discovery.SvcDiscoveryRegistry
|
discov discovery.SvcDiscoveryRegistry
|
||||||
config config.RpcService
|
config config.RpcRegisterName
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserApi(client user.UserClient, discov discovery.SvcDiscoveryRegistry, config config.RpcService) UserApi {
|
func NewUserApi(client user.UserClient, discov discovery.SvcDiscoveryRegistry, config config.RpcRegisterName) UserApi {
|
||||||
return UserApi{Client: client, discov: discov, config: config}
|
return UserApi{Client: client, discov: discov, config: config}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) InitServer(ctx context.Context, config *Config, disCov discovery.SvcDiscoveryRegistry, server *grpc.Server) error {
|
func (s *Server) InitServer(ctx context.Context, config *Config, disCov discovery.SvcDiscoveryRegistry, server *grpc.Server) error {
|
||||||
userConn, err := disCov.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -54,19 +54,13 @@ func (s *Server) InitServer(ctx context.Context, config *Config, disCov discover
|
|||||||
func (s *Server) Start(ctx context.Context, index int, conf *Config) error {
|
func (s *Server) Start(ctx context.Context, index int, conf *Config) error {
|
||||||
return startrpc.Start(ctx, &conf.Discovery, &conf.MsgGateway.Prometheus, conf.MsgGateway.ListenIP,
|
return startrpc.Start(ctx, &conf.Discovery, &conf.MsgGateway.Prometheus, conf.MsgGateway.ListenIP,
|
||||||
conf.MsgGateway.RPC.RegisterIP,
|
conf.MsgGateway.RPC.RegisterIP,
|
||||||
conf.MsgGateway.RPC.AutoSetPorts, conf.MsgGateway.RPC.Ports, index,
|
conf.MsgGateway.RPC.AutoSetPorts,
|
||||||
conf.Discovery.RpcService.MessageGateway,
|
conf.MsgGateway.RPC.Ports, index,
|
||||||
nil,
|
conf.Share.RpcRegisterName.MessageGateway,
|
||||||
|
&conf.Share,
|
||||||
conf,
|
conf,
|
||||||
[]string{
|
[]string{
|
||||||
conf.Share.GetConfigFileName(),
|
conf.Share.RpcRegisterName.MessageGateway,
|
||||||
conf.Discovery.GetConfigFileName(),
|
|
||||||
conf.MsgGateway.GetConfigFileName(),
|
|
||||||
conf.WebhooksConfig.GetConfigFileName(),
|
|
||||||
conf.RedisConfig.GetConfigFileName(),
|
|
||||||
},
|
|
||||||
[]string{
|
|
||||||
conf.Discovery.RpcService.MessageGateway,
|
|
||||||
},
|
},
|
||||||
s.InitServer,
|
s.InitServer,
|
||||||
)
|
)
|
||||||
@@ -74,7 +68,7 @@ func (s *Server) Start(ctx context.Context, index int, conf *Config) error {
|
|||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
msggateway.UnimplementedMsgGatewayServer
|
msggateway.UnimplementedMsgGatewayServer
|
||||||
|
rpcPort int
|
||||||
LongConnServer LongConnServer
|
LongConnServer LongConnServer
|
||||||
config *Config
|
config *Config
|
||||||
pushTerminal map[int]struct{}
|
pushTerminal map[int]struct{}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package msggateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -11,20 +10,18 @@ import (
|
|||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
|
||||||
"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"
|
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"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/prommetrics"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
"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/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
"github.com/openimsdk/protocol/msggateway"
|
"github.com/openimsdk/protocol/msggateway"
|
||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
|
"github.com/openimsdk/tools/mcontext"
|
||||||
"github.com/openimsdk/tools/utils/stringutil"
|
"github.com/openimsdk/tools/utils/stringutil"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
@@ -76,19 +73,19 @@ type kickHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WsServer) SetDiscoveryRegistry(ctx context.Context, disCov discovery.SvcDiscoveryRegistry, config *Config) error {
|
func (ws *WsServer) SetDiscoveryRegistry(ctx context.Context, disCov discovery.SvcDiscoveryRegistry, config *Config) error {
|
||||||
userConn, err := disCov.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pushConn, err := disCov.GetConn(ctx, config.Discovery.RpcService.Push)
|
pushConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Push)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
authConn, err := disCov.GetConn(ctx, config.Discovery.RpcService.Auth)
|
authConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msgConn, err := disCov.GetConn(ctx, config.Discovery.RpcService.Msg)
|
msgConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -133,7 +130,7 @@ func NewWsServer(msgGatewayConfig *Config, opts ...Option) *WsServer {
|
|||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&config)
|
o(&config)
|
||||||
}
|
}
|
||||||
//userRpcClient := rpcclient.NewUserRpcClient(client, config.Discovery.RpcService.User, config.Share.IMAdminUserID)
|
//userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||||
|
|
||||||
v := validator.New()
|
v := validator.New()
|
||||||
return &WsServer{
|
return &WsServer{
|
||||||
@@ -185,28 +182,21 @@ func (ws *WsServer) Run(done chan error) error {
|
|||||||
go func() {
|
go func() {
|
||||||
http.HandleFunc("/", ws.wsHandler)
|
http.HandleFunc("/", ws.wsHandler)
|
||||||
err := server.ListenAndServe()
|
err := server.ListenAndServe()
|
||||||
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
defer close(netDone)
|
||||||
|
if err != nil && err != http.ErrServerClosed {
|
||||||
netErr = errs.WrapMsg(err, "ws start err", server.Addr)
|
netErr = errs.WrapMsg(err, "ws start err", server.Addr)
|
||||||
netDone <- struct{}{}
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||||
shutDown := func() error {
|
defer cancel()
|
||||||
|
var err error
|
||||||
|
select {
|
||||||
|
case err = <-done:
|
||||||
sErr := server.Shutdown(ctx)
|
sErr := server.Shutdown(ctx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return errs.WrapMsg(sErr, "shutdown err")
|
return errs.WrapMsg(sErr, "shutdown err")
|
||||||
}
|
}
|
||||||
close(shutdownDone)
|
close(shutdownDone)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
etcd.RegisterShutDown(shutDown)
|
|
||||||
defer cancel()
|
|
||||||
var err error
|
|
||||||
select {
|
|
||||||
case err = <-done:
|
|
||||||
if err := shutDown(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -219,19 +209,23 @@ func (ws *WsServer) Run(done chan error) error {
|
|||||||
var concurrentRequest = 3
|
var concurrentRequest = 3
|
||||||
|
|
||||||
func (ws *WsServer) sendUserOnlineInfoToOtherNode(ctx context.Context, client *Client) error {
|
func (ws *WsServer) sendUserOnlineInfoToOtherNode(ctx context.Context, client *Client) error {
|
||||||
conns, err := ws.disCov.GetConns(ctx, ws.msgGatewayConfig.Discovery.RpcService.MessageGateway)
|
conns, err := ws.disCov.GetConns(ctx, ws.msgGatewayConfig.Share.RpcRegisterName.MessageGateway)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(conns) == 0 || (len(conns) == 1 && ws.disCov.IsSelfNode(conns[0])) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
wg := errgroup.Group{}
|
wg := errgroup.Group{}
|
||||||
wg.SetLimit(concurrentRequest)
|
wg.SetLimit(concurrentRequest)
|
||||||
|
|
||||||
// Online push user online message to other node
|
// Online push user online message to other node
|
||||||
for _, v := range conns {
|
for _, v := range conns {
|
||||||
v := v
|
v := v
|
||||||
log.ZDebug(ctx, " sendUserOnlineInfoToOtherNode conn ", "target", v.Target())
|
log.ZDebug(ctx, "sendUserOnlineInfoToOtherNode conn")
|
||||||
if v.Target() == ws.disCov.GetSelfConnTarget() {
|
if ws.disCov.IsSelfNode(v) {
|
||||||
log.ZDebug(ctx, "Filter out this node", "node", v.Target())
|
log.ZDebug(ctx, "Filter out this node")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +236,7 @@ func (ws *WsServer) sendUserOnlineInfoToOtherNode(ctx context.Context, client *C
|
|||||||
PlatformID: int32(client.PlatformID), Token: client.token,
|
PlatformID: int32(client.PlatformID), Token: client.token,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ZWarn(ctx, "MultiTerminalLoginCheck err", err, "node", v.Target())
|
log.ZWarn(ctx, "MultiTerminalLoginCheck err", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
disetcd "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
|
||||||
"github.com/openimsdk/tools/discovery"
|
|
||||||
"github.com/openimsdk/tools/discovery/etcd"
|
"github.com/openimsdk/tools/discovery/etcd"
|
||||||
"github.com/openimsdk/tools/utils/jsonutil"
|
"github.com/openimsdk/tools/utils/jsonutil"
|
||||||
"github.com/openimsdk/tools/utils/network"
|
"github.com/openimsdk/tools/utils/network"
|
||||||
@@ -37,10 +35,10 @@ import (
|
|||||||
"github.com/openimsdk/tools/db/mongoutil"
|
"github.com/openimsdk/tools/db/mongoutil"
|
||||||
"github.com/openimsdk/tools/db/redisutil"
|
"github.com/openimsdk/tools/db/redisutil"
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
"github.com/openimsdk/tools/utils/runtimeenv"
|
|
||||||
|
|
||||||
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
discRegister "github.com/openimsdk/open-im-server/v3/pkg/common/discovery"
|
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/common/storage/controller"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
@@ -59,8 +57,6 @@ type MsgTransfer struct {
|
|||||||
historyMongoCH *OnlineHistoryMongoConsumerHandler
|
historyMongoCH *OnlineHistoryMongoConsumerHandler
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
||||||
runTimeEnv string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@@ -74,9 +70,8 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Start(ctx context.Context, index int, config *Config) error {
|
func Start(ctx context.Context, index int, config *Config) error {
|
||||||
runTimeEnv := runtimeenv.PrintRuntimeEnvironment()
|
|
||||||
|
|
||||||
log.CInfo(ctx, "MSG-TRANSFER server is initializing", "runTimeEnv", runTimeEnv, "prometheusPorts",
|
log.CInfo(ctx, "MSG-TRANSFER server is initializing", "prometheusPorts",
|
||||||
config.MsgTransfer.Prometheus.Ports, "index", index)
|
config.MsgTransfer.Prometheus.Ports, "index", index)
|
||||||
|
|
||||||
mgocli, err := mongoutil.NewMongoDB(ctx, config.MongodbConfig.Build())
|
mgocli, err := mongoutil.NewMongoDB(ctx, config.MongodbConfig.Build())
|
||||||
@@ -87,27 +82,13 @@ func Start(ctx context.Context, index int, config *Config) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
client, err := discRegister.NewDiscoveryRegister(&config.Discovery, runTimeEnv, nil)
|
client, err := discRegister.NewDiscoveryRegister(&config.Discovery, &config.Share, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||||
|
|
||||||
if config.Discovery.Enable == conf.ETCD {
|
|
||||||
cm := disetcd.NewConfigManager(client.(*etcd.SvcDiscoveryRegistryImpl).GetClient(), []string{
|
|
||||||
config.MsgTransfer.GetConfigFileName(),
|
|
||||||
config.RedisConfig.GetConfigFileName(),
|
|
||||||
config.MongodbConfig.GetConfigFileName(),
|
|
||||||
config.KafkaConfig.GetConfigFileName(),
|
|
||||||
config.Share.GetConfigFileName(),
|
|
||||||
config.WebhooksConfig.GetConfigFileName(),
|
|
||||||
config.Discovery.GetConfigFileName(),
|
|
||||||
conf.LogConfigFileName,
|
|
||||||
})
|
|
||||||
cm.Watch(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
msgDocModel, err := mgo.NewMsgMongo(mgocli.GetDB())
|
msgDocModel, err := mgo.NewMsgMongo(mgocli.GetDB())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -139,13 +120,11 @@ func Start(ctx context.Context, index int, config *Config) error {
|
|||||||
msgTransfer := &MsgTransfer{
|
msgTransfer := &MsgTransfer{
|
||||||
historyCH: historyCH,
|
historyCH: historyCH,
|
||||||
historyMongoCH: historyMongoCH,
|
historyMongoCH: historyMongoCH,
|
||||||
runTimeEnv: runTimeEnv,
|
|
||||||
}
|
}
|
||||||
|
return msgTransfer.Start(index, config)
|
||||||
return msgTransfer.Start(index, config, client)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MsgTransfer) Start(index int, config *Config, client discovery.SvcDiscoveryRegistry) error {
|
func (m *MsgTransfer) Start(index int, cfg *Config) error {
|
||||||
m.ctx, m.cancel = context.WithCancel(context.Background())
|
m.ctx, m.cancel = context.WithCancel(context.Background())
|
||||||
var (
|
var (
|
||||||
netDone = make(chan struct{}, 1)
|
netDone = make(chan struct{}, 1)
|
||||||
@@ -160,6 +139,11 @@ func (m *MsgTransfer) Start(index int, config *Config, client discovery.SvcDisco
|
|||||||
return err
|
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("")
|
registerIP, err := network.GetRpcRegisterIP("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -176,17 +160,17 @@ func (m *MsgTransfer) Start(index int, config *Config, client discovery.SvcDisco
|
|||||||
return listener, port, nil
|
return listener, port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.MsgTransfer.Prometheus.AutoSetPorts && config.Discovery.Enable != conf.ETCD {
|
if cfg.MsgTransfer.Prometheus.AutoSetPorts && cfg.Discovery.Enable != conf.ETCD {
|
||||||
return errs.New("only etcd support autoSetPorts", "RegisterName", "api").Wrap()
|
return errs.New("only etcd support autoSetPorts", "RegisterName", "api").Wrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.MsgTransfer.Prometheus.Enable {
|
if cfg.MsgTransfer.Prometheus.Enable {
|
||||||
var (
|
var (
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
prometheusPort int
|
prometheusPort int
|
||||||
)
|
)
|
||||||
|
|
||||||
if config.MsgTransfer.Prometheus.AutoSetPorts {
|
if cfg.MsgTransfer.Prometheus.AutoSetPorts {
|
||||||
listener, prometheusPort, err = getAutoPort()
|
listener, prometheusPort, err = getAutoPort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -199,7 +183,7 @@ func (m *MsgTransfer) Start(index int, config *Config, client discovery.SvcDisco
|
|||||||
return errs.WrapMsg(err, "etcd put err")
|
return errs.WrapMsg(err, "etcd put err")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
prometheusPort, err = datautil.GetElemByIndex(config.MsgTransfer.Prometheus.Ports, index)
|
prometheusPort, err = datautil.GetElemByIndex(cfg.MsgTransfer.Prometheus.Ports, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,17 +18,22 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
|
||||||
"github.com/openimsdk/tools/discovery"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/IBM/sarama"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||||
|
"github.com/openimsdk/tools/discovery"
|
||||||
|
|
||||||
"github.com/go-redis/redis"
|
"github.com/go-redis/redis"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||||
|
|
||||||
|
"github.com/IBM/sarama"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
"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/msgprocessor"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/tools/batcher"
|
"github.com/openimsdk/open-im-server/v3/pkg/tools/batcher"
|
||||||
"github.com/openimsdk/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
@@ -37,9 +42,7 @@ import (
|
|||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mcontext"
|
"github.com/openimsdk/tools/mcontext"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
"github.com/openimsdk/tools/utils/stringutil"
|
"github.com/openimsdk/tools/utils/stringutil"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -82,11 +85,11 @@ func NewOnlineHistoryRedisConsumerHandler(ctx context.Context, client discovery.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
groupConn, err := client.GetConn(ctx, config.Discovery.RpcService.Group)
|
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conversationConn, err := client.GetConn(ctx, config.Discovery.RpcService.Conversation)
|
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -138,53 +141,48 @@ func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, channelID
|
|||||||
|
|
||||||
func (och *OnlineHistoryRedisConsumerHandler) doSetReadSeq(ctx context.Context, msgs []*ContextMsg) {
|
func (och *OnlineHistoryRedisConsumerHandler) doSetReadSeq(ctx context.Context, msgs []*ContextMsg) {
|
||||||
|
|
||||||
var conversationID string
|
// Outer map: conversationID -> (userID -> maxHasReadSeq)
|
||||||
var userSeqMap map[string]int64
|
conversationUserSeq := make(map[string]map[string]int64)
|
||||||
|
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
if msg.message.ContentType != constant.HasReadReceipt {
|
if msg.message.ContentType != constant.HasReadReceipt {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var elem sdkws.NotificationElem
|
var elem sdkws.NotificationElem
|
||||||
if err := json.Unmarshal(msg.message.Content, &elem); err != nil {
|
if err := json.Unmarshal(msg.message.Content, &elem); err != nil {
|
||||||
log.ZWarn(ctx, "handlerConversationRead Unmarshal NotificationElem msg err", err, "msg", msg)
|
log.ZWarn(ctx, "Unmarshal NotificationElem error", err, "msg", msg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var tips sdkws.MarkAsReadTips
|
var tips sdkws.MarkAsReadTips
|
||||||
if err := json.Unmarshal([]byte(elem.Detail), &tips); err != nil {
|
if err := json.Unmarshal([]byte(elem.Detail), &tips); err != nil {
|
||||||
log.ZWarn(ctx, "handlerConversationRead Unmarshal MarkAsReadTips msg err", err, "msg", msg)
|
log.ZWarn(ctx, "Unmarshal MarkAsReadTips error", err, "msg", msg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
//The conversation ID for each batch of messages processed by the batcher is the same.
|
if len(tips.ConversationID) == 0 || tips.HasReadSeq < 0 {
|
||||||
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
|
continue
|
||||||
}
|
}
|
||||||
if userSeqMap == nil {
|
|
||||||
userSeqMap = make(map[string]int64)
|
|
||||||
}
|
|
||||||
|
|
||||||
if userSeqMap[tips.MarkAsReadUserID] > tips.HasReadSeq {
|
// Calculate the max seq from tips.Seqs
|
||||||
continue
|
for _, seq := range tips.Seqs {
|
||||||
|
if tips.HasReadSeq < seq {
|
||||||
|
tips.HasReadSeq = seq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
userSeqMap[tips.MarkAsReadUserID] = tips.HasReadSeq
|
|
||||||
}
|
}
|
||||||
if userSeqMap == nil {
|
log.ZInfo(ctx, "doSetReadSeq", "conversationUserSeq", conversationUserSeq)
|
||||||
return
|
|
||||||
}
|
// persist to db
|
||||||
if len(conversationID) == 0 {
|
for convID, userSeqMap := range conversationUserSeq {
|
||||||
log.ZWarn(ctx, "conversation err", nil, "conversationID", conversationID)
|
if err := och.msgTransferDatabase.SetHasReadSeqToDB(ctx, convID, userSeqMap); err != nil {
|
||||||
}
|
log.ZWarn(ctx, "SetHasReadSeqToDB error", err, "conversationID", convID, "userSeqMap", userSeqMap)
|
||||||
if err := och.msgTransferDatabase.SetHasReadSeqToDB(ctx, conversationID, userSeqMap); err != nil {
|
}
|
||||||
log.ZWarn(ctx, "set read seq to db error", err, "conversationID", conversationID, "userSeqMap", userSeqMap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -288,6 +286,7 @@ func (och *OnlineHistoryRedisConsumerHandler) handleMsg(ctx context.Context, key
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isNewConversation {
|
if isNewConversation {
|
||||||
|
ctx := storageList[0].ctx
|
||||||
switch msg.SessionType {
|
switch msg.SessionType {
|
||||||
case constant.ReadGroupChatType:
|
case constant.ReadGroupChatType:
|
||||||
log.ZDebug(ctx, "group chat first create conversation", "conversationID",
|
log.ZDebug(ctx, "group chat first create conversation", "conversationID",
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ import (
|
|||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"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/prommetrics"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
"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"
|
pbmsg "github.com/openimsdk/protocol/msg"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -73,10 +73,14 @@ func (mc *OnlineHistoryMongoConsumerHandler) handleChatWs2Mongo(ctx context.Cont
|
|||||||
} else {
|
} else {
|
||||||
prommetrics.MsgInsertMongoSuccessCounter.Inc()
|
prommetrics.MsgInsertMongoSuccessCounter.Inc()
|
||||||
}
|
}
|
||||||
var seqs []int64
|
//var seqs []int64
|
||||||
for _, msg := range msgFromMQ.MsgData {
|
//for _, msg := range msgFromMQ.MsgData {
|
||||||
seqs = append(seqs, msg.Seq)
|
// 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)
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*OnlineHistoryMongoConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
|
func (*OnlineHistoryMongoConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { 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"
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options"
|
"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/prommetrics"
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||||
"github.com/openimsdk/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
pbpush "github.com/openimsdk/protocol/push"
|
pbpush "github.com/openimsdk/protocol/push"
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
"github.com/openimsdk/tools/utils/jsonutil"
|
"github.com/openimsdk/tools/utils/jsonutil"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,19 +2,15 @@ package push
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/openimsdk/protocol/msggateway"
|
"github.com/openimsdk/protocol/msggateway"
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
"github.com/openimsdk/tools/errs"
|
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type OnlinePusher interface {
|
type OnlinePusher interface {
|
||||||
@@ -42,16 +38,15 @@ func (u emptyOnlinePusher) GetOnlinePushFailedUserIDs(ctx context.Context, msg *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewOnlinePusher(disCov discovery.SvcDiscoveryRegistry, config *Config) OnlinePusher {
|
func NewOnlinePusher(disCov discovery.SvcDiscoveryRegistry, config *Config) OnlinePusher {
|
||||||
|
|
||||||
if config.runTimeEnv == conf.KUBERNETES {
|
|
||||||
return NewDefaultAllNode(disCov, config)
|
|
||||||
}
|
|
||||||
switch config.Discovery.Enable {
|
switch config.Discovery.Enable {
|
||||||
case conf.ETCD:
|
case "k8s":
|
||||||
|
return NewK8sStaticConsistentHash(disCov, config)
|
||||||
|
case "zookeeper":
|
||||||
|
return NewDefaultAllNode(disCov, config)
|
||||||
|
case "etcd":
|
||||||
return NewDefaultAllNode(disCov, config)
|
return NewDefaultAllNode(disCov, config)
|
||||||
default:
|
default:
|
||||||
log.ZError(context.Background(), "NewOnlinePusher is error", errs.Wrap(errors.New("unsupported discovery type")), "type", config.Discovery.Enable)
|
return newEmptyOnlinePusher()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +61,7 @@ func NewDefaultAllNode(disCov discovery.SvcDiscoveryRegistry, config *Config) *D
|
|||||||
|
|
||||||
func (d *DefaultAllNode) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws.MsgData,
|
func (d *DefaultAllNode) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws.MsgData,
|
||||||
pushToUserIDs []string) (wsResults []*msggateway.SingleMsgToUserResults, err error) {
|
pushToUserIDs []string) (wsResults []*msggateway.SingleMsgToUserResults, err error) {
|
||||||
conns, err := d.disCov.GetConns(ctx, d.config.Discovery.RpcService.MessageGateway)
|
conns, err := d.disCov.GetConns(ctx, d.config.Share.RpcRegisterName.MessageGateway)
|
||||||
if len(conns) == 0 {
|
if len(conns) == 0 {
|
||||||
log.ZWarn(ctx, "get gateway conn 0 ", nil)
|
log.ZWarn(ctx, "get gateway conn 0 ", nil)
|
||||||
} else {
|
} else {
|
||||||
@@ -166,7 +161,7 @@ func (k *K8sStaticConsistentHash) GetConnsAndOnlinePush(ctx context.Context, msg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.ZDebug(ctx, "genUsers send hosts struct:", "usersHost", usersHost)
|
log.ZDebug(ctx, "genUsers send hosts struct:", "usersHost", usersHost)
|
||||||
var usersConns = make(map[*grpc.ClientConn][]string)
|
var usersConns = make(map[grpc.ClientConnInterface][]string)
|
||||||
for host, userIds := range usersHost {
|
for host, userIds := range usersHost {
|
||||||
tconn, _ := k.disCov.GetConn(ctx, host)
|
tconn, _ := k.disCov.GetConn(ctx, host)
|
||||||
usersConns[tconn] = userIds
|
usersConns[tconn] = userIds
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options"
|
"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/prommetrics"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
"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/common/webhook"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
"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/rpccache"
|
||||||
@@ -25,7 +26,6 @@ import (
|
|||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mcontext"
|
"github.com/openimsdk/tools/mcontext"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
"github.com/openimsdk/tools/utils/jsonutil"
|
"github.com/openimsdk/tools/utils/jsonutil"
|
||||||
"github.com/openimsdk/tools/utils/timeutil"
|
"github.com/openimsdk/tools/utils/timeutil"
|
||||||
@@ -58,19 +58,19 @@ func NewConsumerHandler(ctx context.Context, config *Config, database controller
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
userConn, err := client.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
groupConn, err := client.GetConn(ctx, config.Discovery.RpcService.Group)
|
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
msgConn, err := client.GetConn(ctx, config.Discovery.RpcService.Msg)
|
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conversationConn, err := client.GetConn(ctx, config.Discovery.RpcService.Conversation)
|
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -142,6 +142,7 @@ func (c *ConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim s
|
|||||||
|
|
||||||
for msg := range claim.Messages() {
|
for msg := range claim.Messages() {
|
||||||
ctx := c.pushConsumerGroup.GetContextFromMsg(msg)
|
ctx := c.pushConsumerGroup.GetContextFromMsg(msg)
|
||||||
|
ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUserID[0])
|
||||||
c.handleMs2PsChat(ctx, msg.Value)
|
c.handleMs2PsChat(ctx, msg.Value)
|
||||||
sess.MarkMessage(msg, "")
|
sess.MarkMessage(msg, "")
|
||||||
}
|
}
|
||||||
@@ -208,7 +209,10 @@ func (c *ConsumerHandler) shouldPushOffline(_ context.Context, msg *sdkws.MsgDat
|
|||||||
if !isOfflinePush {
|
if !isOfflinePush {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if msg.ContentType == constant.SignalingNotification {
|
switch msg.ContentType {
|
||||||
|
case constant.RoomParticipantsConnectedNotification:
|
||||||
|
return false
|
||||||
|
case constant.RoomParticipantsDisconnectedNotification:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userConn, err := client.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -187,12 +187,12 @@ func (s *authServer) ForceLogout(ctx context.Context, req *pbauth.ForceLogoutReq
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *authServer) forceKickOff(ctx context.Context, userID string, platformID int32) error {
|
func (s *authServer) forceKickOff(ctx context.Context, userID string, platformID int32) error {
|
||||||
conns, err := s.RegisterCenter.GetConns(ctx, s.config.Discovery.RpcService.MessageGateway)
|
conns, err := s.RegisterCenter.GetConns(ctx, s.config.Share.RpcRegisterName.MessageGateway)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, v := range conns {
|
for _, v := range conns {
|
||||||
log.ZDebug(ctx, "forceKickOff", "conn", v.Target())
|
log.ZDebug(ctx, "forceKickOff", "userID", userID, "platformID", platformID)
|
||||||
client := msggateway.NewMsgGatewayClient(v)
|
client := msggateway.NewMsgGatewayClient(v)
|
||||||
kickReq := &msggateway.KickUserOfflineReq{KickUserIDList: []string{userID}, PlatformID: platformID}
|
kickReq := &msggateway.KickUserOfflineReq{KickUserIDList: []string{userID}, PlatformID: platformID}
|
||||||
_, err := client.KickUserOffline(ctx, kickReq)
|
_, err := client.KickUserOffline(ctx, kickReq)
|
||||||
|
|||||||
@@ -79,15 +79,15 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userConn, err := client.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
groupConn, err := client.GetConn(ctx, config.Discovery.RpcService.Group)
|
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msgConn, err := client.GetConn(ctx, config.Discovery.RpcService.Msg)
|
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -238,14 +238,12 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
|
|||||||
if req.Conversation == nil {
|
if req.Conversation == nil {
|
||||||
return nil, errs.ErrArgs.WrapMsg("conversation must not be nil")
|
return nil, errs.ErrArgs.WrapMsg("conversation must not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Conversation.ConversationType == constant.WriteGroupChatType {
|
if req.Conversation.ConversationType == constant.WriteGroupChatType {
|
||||||
groupInfo, err := c.groupClient.GetGroupInfo(ctx, req.Conversation.GroupID)
|
groupInfo, err := c.groupClient.GetGroupInfo(ctx, req.Conversation.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if groupInfo == nil {
|
|
||||||
return nil, servererrs.ErrGroupIDNotFound.WrapMsg(req.Conversation.GroupID)
|
|
||||||
}
|
|
||||||
if groupInfo.Status == constant.GroupStatusDismissed {
|
if groupInfo.Status == constant.GroupStatusDismissed {
|
||||||
return nil, servererrs.ErrDismissedAlready.WrapMsg("group dismissed")
|
return nil, servererrs.ErrDismissedAlready.WrapMsg("group dismissed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,21 +16,22 @@ package conversation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"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/rpcli"
|
||||||
"github.com/openimsdk/protocol/msg"
|
"github.com/openimsdk/protocol/msg"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
|
||||||
"github.com/openimsdk/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConversationNotificationSender struct {
|
type ConversationNotificationSender struct {
|
||||||
*rpcclient.NotificationSender
|
*notification.NotificationSender
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConversationNotificationSender(conf *config.Notification, msgClient *rpcli.MsgClient) *ConversationNotificationSender {
|
func NewConversationNotificationSender(conf *config.Notification, msgClient *rpcli.MsgClient) *ConversationNotificationSender {
|
||||||
return &ConversationNotificationSender{rpcclient.NewNotificationSender(conf, rpcclient.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
return &ConversationNotificationSender{notification.NewNotificationSender(conf, notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||||
return msgClient.SendMsg(ctx, req)
|
return msgClient.SendMsg(ctx, req)
|
||||||
}))}
|
}))}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ func (s *groupServer) GetGroupInfoCache(ctx context.Context, req *pbgroup.GetGro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *groupServer) GetGroupMemberCache(ctx context.Context, req *pbgroup.GetGroupMemberCacheReq) (*pbgroup.GetGroupMemberCacheResp, error) {
|
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)
|
members, err := s.db.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package group
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
pbgroup "github.com/openimsdk/protocol/group"
|
pbgroup "github.com/openimsdk/protocol/group"
|
||||||
@@ -55,41 +56,52 @@ func UpdateGroupInfoMap(ctx context.Context, group *sdkws.GroupInfoForSet) map[s
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateGroupInfoExMap(ctx context.Context, group *pbgroup.SetGroupInfoExReq) (map[string]any, error) {
|
func UpdateGroupInfoExMap(ctx context.Context, group *pbgroup.SetGroupInfoExReq) (m map[string]any, normalFlag, groupNameFlag, notificationFlag bool, err error) {
|
||||||
m := make(map[string]any)
|
m = make(map[string]any)
|
||||||
|
|
||||||
if group.GroupName != nil {
|
if group.GroupName != nil {
|
||||||
if group.GroupName.Value != "" {
|
if strings.TrimSpace(group.GroupName.Value) != "" {
|
||||||
m["group_name"] = group.GroupName.Value
|
m["group_name"] = group.GroupName.Value
|
||||||
|
groupNameFlag = true
|
||||||
} else {
|
} else {
|
||||||
return nil, errs.ErrArgs.WrapMsg("group name is empty")
|
return nil, normalFlag, notificationFlag, groupNameFlag, errs.ErrArgs.WrapMsg("group name is empty")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if group.Notification != nil {
|
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"] = group.Notification.Value
|
||||||
m["notification_update_time"] = time.Now()
|
|
||||||
m["notification_user_id"] = mcontext.GetOpUserID(ctx)
|
m["notification_user_id"] = mcontext.GetOpUserID(ctx)
|
||||||
|
m["notification_update_time"] = time.Now()
|
||||||
}
|
}
|
||||||
if group.Introduction != nil {
|
if group.Introduction != nil {
|
||||||
m["introduction"] = group.Introduction.Value
|
m["introduction"] = group.Introduction.Value
|
||||||
|
normalFlag = true
|
||||||
}
|
}
|
||||||
if group.FaceURL != nil {
|
if group.FaceURL != nil {
|
||||||
m["face_url"] = group.FaceURL.Value
|
m["face_url"] = group.FaceURL.Value
|
||||||
|
normalFlag = true
|
||||||
}
|
}
|
||||||
if group.NeedVerification != nil {
|
if group.NeedVerification != nil {
|
||||||
m["need_verification"] = group.NeedVerification.Value
|
m["need_verification"] = group.NeedVerification.Value
|
||||||
|
normalFlag = true
|
||||||
}
|
}
|
||||||
if group.LookMemberInfo != nil {
|
if group.LookMemberInfo != nil {
|
||||||
m["look_member_info"] = group.LookMemberInfo.Value
|
m["look_member_info"] = group.LookMemberInfo.Value
|
||||||
|
normalFlag = true
|
||||||
}
|
}
|
||||||
if group.ApplyMemberFriend != nil {
|
if group.ApplyMemberFriend != nil {
|
||||||
m["apply_member_friend"] = group.ApplyMemberFriend.Value
|
m["apply_member_friend"] = group.ApplyMemberFriend.Value
|
||||||
|
normalFlag = true
|
||||||
}
|
}
|
||||||
if group.Ex != nil {
|
if group.Ex != nil {
|
||||||
m["ex"] = group.Ex.Value
|
m["ex"] = group.Ex.Value
|
||||||
|
normalFlag = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, normalFlag, groupNameFlag, notificationFlag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateGroupStatusMap(status int) map[string]any {
|
func UpdateGroupStatusMap(status int) map[string]any {
|
||||||
|
|||||||
+159
-78
@@ -17,28 +17,30 @@ package group
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"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/servererrs"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/common"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/common"
|
||||||
"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/common/storage/database/mgo"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
|
||||||
|
"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/msgprocessor"
|
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/grouphash"
|
"github.com/openimsdk/open-im-server/v3/pkg/notification/grouphash"
|
||||||
"github.com/openimsdk/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
pbconv "github.com/openimsdk/protocol/conversation"
|
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||||
pbgroup "github.com/openimsdk/protocol/group"
|
pbgroup "github.com/openimsdk/protocol/group"
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/protocol/wrapperspb"
|
"github.com/openimsdk/protocol/wrapperspb"
|
||||||
@@ -102,15 +104,15 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
|||||||
//msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
//msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||||
//conversationRpcClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
//conversationRpcClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||||
|
|
||||||
userConn, err := client.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msgConn, err := client.GetConn(ctx, config.Discovery.RpcService.Msg)
|
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
conversationConn, err := client.GetConn(ctx, config.Discovery.RpcService.Conversation)
|
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -288,13 +290,14 @@ func (g *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.notification.GroupCreatedNotification(ctx, tips)
|
g.notification.GroupCreatedNotification(ctx, tips, req.SendMessage)
|
||||||
|
|
||||||
if req.GroupInfo.Notification != "" {
|
if req.GroupInfo.Notification != "" {
|
||||||
|
notificationFlag := true
|
||||||
g.notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{
|
g.notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{
|
||||||
Group: tips.Group,
|
Group: tips.Group,
|
||||||
OpUser: tips.OpUser,
|
OpUser: tips.OpUser,
|
||||||
})
|
}, ¬ificationFlag)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqCallBackAfter := &pbgroup.CreateGroupReq{
|
reqCallBackAfter := &pbgroup.CreateGroupReq{
|
||||||
@@ -392,6 +395,8 @@ func (g *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
|
|||||||
if err := g.PopulateGroupMember(ctx, groupMember); err != nil {
|
if err := g.PopulateGroupMember(ctx, groupMember); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
opUserID = mcontext.GetOpUserID(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := g.webhookBeforeInviteUserToGroup(ctx, &g.config.WebhooksConfig.BeforeInviteUserToGroup, req); err != nil && err != servererrs.ErrCallbackContinue {
|
if err := g.webhookBeforeInviteUserToGroup(ctx, &g.config.WebhooksConfig.BeforeInviteUserToGroup, req); err != nil && err != servererrs.ErrCallbackContinue {
|
||||||
@@ -421,12 +426,13 @@ func (g *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
|
|||||||
ReqMessage: request.ReqMsg,
|
ReqMessage: request.ReqMsg,
|
||||||
JoinSource: request.JoinSource,
|
JoinSource: request.JoinSource,
|
||||||
InviterUserID: request.InviterUserID,
|
InviterUserID: request.InviterUserID,
|
||||||
})
|
}, request)
|
||||||
}
|
}
|
||||||
return &pbgroup.InviteUserToGroupResp{}, nil
|
return &pbgroup.InviteUserToGroupResp{}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var groupMembers []*model.GroupMember
|
var groupMembers []*model.GroupMember
|
||||||
for _, userID := range req.InvitedUserIDs {
|
for _, userID := range req.InvitedUserIDs {
|
||||||
member := &model.GroupMember{
|
member := &model.GroupMember{
|
||||||
@@ -447,12 +453,25 @@ func (g *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := g.db.CreateGroup(ctx, nil, groupMembers); err != nil {
|
const singleQuantity = 50
|
||||||
return nil, err
|
for start := 0; start < len(groupMembers); start += singleQuantity {
|
||||||
}
|
end := start + singleQuantity
|
||||||
|
if end > len(groupMembers) {
|
||||||
|
end = len(groupMembers)
|
||||||
|
}
|
||||||
|
currentMembers := groupMembers[start:end]
|
||||||
|
|
||||||
if err = g.notification.GroupApplicationAgreeMemberEnterNotification(ctx, req.GroupID, opUserID, req.InvitedUserIDs...); err != nil {
|
if err := g.db.CreateGroup(ctx, nil, currentMembers); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userIDs := datautil.Slice(currentMembers, func(e *model.GroupMember) string {
|
||||||
|
return e.UserID
|
||||||
|
})
|
||||||
|
|
||||||
|
if err = g.notification.GroupApplicationAgreeMemberEnterNotification(ctx, req.GroupID, req.SendMessage, opUserID, userIDs...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return &pbgroup.InviteUserToGroupResp{}, nil
|
return &pbgroup.InviteUserToGroupResp{}, nil
|
||||||
}
|
}
|
||||||
@@ -472,7 +491,25 @@ func (g *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
|
|||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *groupServer) checkAdminOrInGroup(ctx context.Context, groupID string) error {
|
||||||
|
if authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
opUserID := mcontext.GetOpUserID(ctx)
|
||||||
|
members, err := g.db.FindGroupMembers(ctx, groupID, []string{opUserID})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(members) == 0 {
|
||||||
|
return errs.ErrNoPermission.WrapMsg("op user not in group")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (g *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
|
func (g *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
|
||||||
|
if err := g.checkAdminOrInGroup(ctx, req.GroupID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
total int64
|
total int64
|
||||||
members []*model.GroupMember
|
members []*model.GroupMember
|
||||||
@@ -481,7 +518,7 @@ func (g *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGr
|
|||||||
if req.Keyword == "" {
|
if req.Keyword == "" {
|
||||||
total, members, err = g.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
|
total, members, err = g.db.PageGetGroupMember(ctx, req.GroupID, req.Pagination)
|
||||||
} else {
|
} else {
|
||||||
members, err = g.db.FindGroupMemberAll(ctx, req.GroupID)
|
total, members, err = g.db.SearchGroupMember(ctx, req.GroupID, req.Keyword, req.Pagination)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -489,27 +526,6 @@ func (g *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGr
|
|||||||
if err := g.PopulateGroupMember(ctx, members...); err != nil {
|
if err := g.PopulateGroupMember(ctx, members...); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if req.Keyword != "" {
|
|
||||||
groupMembers := make([]*model.GroupMember, 0)
|
|
||||||
for _, member := range members {
|
|
||||||
if member.UserID == req.Keyword {
|
|
||||||
groupMembers = append(groupMembers, member)
|
|
||||||
total++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if member.Nickname == req.Keyword {
|
|
||||||
groupMembers = append(groupMembers, member)
|
|
||||||
total++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
members := datautil.Paginate(groupMembers, int(req.Pagination.GetPageNumber()), int(req.Pagination.GetShowNumber()))
|
|
||||||
return &pbgroup.GetGroupMemberListResp{
|
|
||||||
Total: uint32(total),
|
|
||||||
Members: datautil.Batch(convert.Db2PbGroupMember, members),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
return &pbgroup.GetGroupMemberListResp{
|
return &pbgroup.GetGroupMemberListResp{
|
||||||
Total: uint32(total),
|
Total: uint32(total),
|
||||||
Members: datautil.Batch(convert.Db2PbGroupMember, members),
|
Members: datautil.Batch(convert.Db2PbGroupMember, members),
|
||||||
@@ -617,7 +633,7 @@ func (g *groupServer) KickGroupMember(ctx context.Context, req *pbgroup.KickGrou
|
|||||||
for _, userID := range req.KickedUserIDs {
|
for _, userID := range req.KickedUserIDs {
|
||||||
tips.KickedUserList = append(tips.KickedUserList, convert.Db2PbGroupMember(memberMap[userID]))
|
tips.KickedUserList = append(tips.KickedUserList, convert.Db2PbGroupMember(memberMap[userID]))
|
||||||
}
|
}
|
||||||
g.notification.MemberKickedNotification(ctx, tips)
|
g.notification.MemberKickedNotification(ctx, tips, req.SendMessage)
|
||||||
if err := g.deleteMemberAndSetConversationSeq(ctx, req.GroupID, req.KickedUserIDs); err != nil {
|
if err := g.deleteMemberAndSetConversationSeq(ctx, req.GroupID, req.KickedUserIDs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -633,6 +649,9 @@ func (g *groupServer) GetGroupMembersInfo(ctx context.Context, req *pbgroup.GetG
|
|||||||
if req.GroupID == "" {
|
if req.GroupID == "" {
|
||||||
return nil, errs.ErrArgs.WrapMsg("groupID empty")
|
return nil, errs.ErrArgs.WrapMsg("groupID empty")
|
||||||
}
|
}
|
||||||
|
if err := g.checkAdminOrInGroup(ctx, req.GroupID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
members, err := g.getGroupMembersInfo(ctx, req.GroupID, req.UserIDs)
|
members, err := g.getGroupMembersInfo(ctx, req.GroupID, req.UserIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -660,15 +679,34 @@ func (g *groupServer) getGroupMembersInfo(ctx context.Context, groupID string, u
|
|||||||
|
|
||||||
// GetGroupApplicationList handles functions that get a list of group requests.
|
// GetGroupApplicationList handles functions that get a list of group requests.
|
||||||
func (g *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.GetGroupApplicationListReq) (*pbgroup.GetGroupApplicationListResp, error) {
|
func (g *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.GetGroupApplicationListReq) (*pbgroup.GetGroupApplicationListResp, error) {
|
||||||
groupIDs, err := g.db.FindUserManagedGroupID(ctx, req.FromUserID)
|
var (
|
||||||
if err != nil {
|
groupIDs []string
|
||||||
return nil, err
|
err error
|
||||||
|
)
|
||||||
|
if len(req.GroupIDs) == 0 {
|
||||||
|
groupIDs, err = g.db.FindUserManagedGroupID(ctx, req.FromUserID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req.GroupIDs = datautil.Distinct(req.GroupIDs)
|
||||||
|
if !authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) {
|
||||||
|
for _, groupID := range req.GroupIDs {
|
||||||
|
if err := g.CheckGroupAdmin(ctx, groupID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupIDs = req.GroupIDs
|
||||||
}
|
}
|
||||||
resp := &pbgroup.GetGroupApplicationListResp{}
|
resp := &pbgroup.GetGroupApplicationListResp{}
|
||||||
if len(groupIDs) == 0 {
|
if len(groupIDs) == 0 {
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
total, groupRequests, err := g.db.PageGroupRequest(ctx, groupIDs, req.Pagination)
|
handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
|
||||||
|
return int(e)
|
||||||
|
})
|
||||||
|
total, groupRequests, err := g.db.PageGroupRequest(ctx, groupIDs, handleResults, req.Pagination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -733,6 +771,23 @@ func (g *groupServer) GetGroupsInfo(ctx context.Context, req *pbgroup.GetGroupsI
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *groupServer) GetGroupApplicationUnhandledCount(ctx context.Context, req *pbgroup.GetGroupApplicationUnhandledCountReq) (*pbgroup.GetGroupApplicationUnhandledCountResp, error) {
|
||||||
|
if err := authverify.CheckAccessV3(ctx, req.UserID, g.config.Share.IMAdminUserID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
groupIDs, err := g.db.FindUserManagedGroupID(ctx, req.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
count, err := g.db.GetGroupApplicationUnhandledCount(ctx, groupIDs, req.Time)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pbgroup.GetGroupApplicationUnhandledCountResp{
|
||||||
|
Count: count,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (g *groupServer) getGroupsInfo(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) {
|
func (g *groupServer) getGroupsInfo(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) {
|
||||||
if len(groupIDs) == 0 {
|
if len(groupIDs) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -826,8 +881,14 @@ func (g *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
|
|||||||
if member == nil {
|
if member == nil {
|
||||||
log.ZDebug(ctx, "GroupApplicationResponse", "member is nil")
|
log.ZDebug(ctx, "GroupApplicationResponse", "member is nil")
|
||||||
} else {
|
} else {
|
||||||
if err = g.notification.GroupApplicationAgreeMemberEnterNotification(ctx, req.GroupID, groupRequest.InviterUserID, req.FromUserID); err != nil {
|
if groupRequest.InviterUserID == "" {
|
||||||
return nil, err
|
if err = g.notification.MemberEnterNotification(ctx, req.GroupID, req.FromUserID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = g.notification.GroupApplicationAgreeMemberEnterNotification(ctx, req.GroupID, nil, groupRequest.InviterUserID, req.FromUserID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case constant.GroupResponseRefuse:
|
case constant.GroupResponseRefuse:
|
||||||
@@ -908,7 +969,7 @@ func (g *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
|
|||||||
if err = g.db.CreateGroupRequest(ctx, []*model.GroupRequest{&groupRequest}); err != nil {
|
if err = g.db.CreateGroupRequest(ctx, []*model.GroupRequest{&groupRequest}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
g.notification.JoinGroupApplicationNotification(ctx, req)
|
g.notification.JoinGroupApplicationNotification(ctx, req, &groupRequest)
|
||||||
return &pbgroup.JoinGroupResp{}, nil
|
return &pbgroup.JoinGroupResp{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1014,7 +1075,7 @@ func (g *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
|
|||||||
if req.GroupInfoForSet.Notification != "" {
|
if req.GroupInfoForSet.Notification != "" {
|
||||||
num -= 3
|
num -= 3
|
||||||
func() {
|
func() {
|
||||||
conversation := &pbconv.ConversationReq{
|
conversation := &pbconversation.ConversationReq{
|
||||||
ConversationID: msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, req.GroupInfoForSet.GroupID),
|
ConversationID: msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, req.GroupInfoForSet.GroupID),
|
||||||
ConversationType: constant.ReadGroupChatType,
|
ConversationType: constant.ReadGroupChatType,
|
||||||
GroupID: req.GroupInfoForSet.GroupID,
|
GroupID: req.GroupInfoForSet.GroupID,
|
||||||
@@ -1029,7 +1090,8 @@ func (g *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
|
|||||||
log.ZWarn(ctx, "SetConversations", err, "UserIDs", resp.UserIDs, "conversation", conversation)
|
log.ZWarn(ctx, "SetConversations", err, "UserIDs", resp.UserIDs, "conversation", conversation)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
g.notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser})
|
notficationFlag := true
|
||||||
|
g.notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser}, ¬ficationFlag)
|
||||||
}
|
}
|
||||||
if req.GroupInfoForSet.GroupName != "" {
|
if req.GroupInfoForSet.GroupName != "" {
|
||||||
num--
|
num--
|
||||||
@@ -1090,7 +1152,7 @@ func (g *groupServer) SetGroupInfoEx(ctx context.Context, req *pbgroup.SetGroupI
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedData, err := UpdateGroupInfoExMap(ctx, req)
|
updatedData, normalFlag, groupNameFlag, notificationFlag, err := UpdateGroupInfoExMap(ctx, req)
|
||||||
if len(updatedData) == 0 {
|
if len(updatedData) == 0 {
|
||||||
return &pbgroup.SetGroupInfoExResp{}, nil
|
return &pbgroup.SetGroupInfoExResp{}, nil
|
||||||
}
|
}
|
||||||
@@ -1118,41 +1180,38 @@ func (g *groupServer) SetGroupInfoEx(ctx context.Context, req *pbgroup.SetGroupI
|
|||||||
tips.OpUser = g.groupMemberDB2PB(opMember, 0)
|
tips.OpUser = g.groupMemberDB2PB(opMember, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
num := len(updatedData)
|
if notificationFlag {
|
||||||
|
|
||||||
if req.Notification != nil {
|
|
||||||
num -= 3
|
|
||||||
|
|
||||||
if req.Notification.Value != "" {
|
if req.Notification.Value != "" {
|
||||||
func() {
|
conversation := &pbconversation.ConversationReq{
|
||||||
conversation := &pbconv.ConversationReq{
|
ConversationID: msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, req.GroupID),
|
||||||
ConversationID: msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, req.GroupID),
|
ConversationType: constant.ReadGroupChatType,
|
||||||
ConversationType: constant.ReadGroupChatType,
|
GroupID: req.GroupID,
|
||||||
GroupID: req.GroupID,
|
}
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := g.GetGroupMemberUserIDs(ctx, &pbgroup.GetGroupMemberUserIDsReq{GroupID: req.GroupID})
|
resp, err := g.GetGroupMemberUserIDs(ctx, &pbgroup.GetGroupMemberUserIDsReq{GroupID: req.GroupID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ZWarn(ctx, "GetGroupMemberIDs is failed.", err)
|
log.ZWarn(ctx, "GetGroupMemberIDs is failed.", err)
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.GroupNotification}
|
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.GroupNotification}
|
||||||
if err := g.conversationClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
|
if err := g.conversationClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
|
||||||
log.ZWarn(ctx, "SetConversations", err, "UserIDs", resp.UserIDs, "conversation", conversation)
|
log.ZWarn(ctx, "SetConversations", err, "UserIDs", resp.UserIDs, "conversation", conversation)
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
|
|
||||||
g.notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser})
|
g.notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser}, ¬ificationFlag)
|
||||||
|
} else {
|
||||||
|
notificationFlag = false
|
||||||
|
g.notification.GroupInfoSetAnnouncementNotification(ctx, &sdkws.GroupInfoSetAnnouncementTips{Group: tips.Group, OpUser: tips.OpUser}, ¬ificationFlag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.GroupName != nil {
|
if groupNameFlag {
|
||||||
num--
|
|
||||||
g.notification.GroupInfoSetNameNotification(ctx, &sdkws.GroupInfoSetNameTips{Group: tips.Group, OpUser: tips.OpUser})
|
g.notification.GroupInfoSetNameNotification(ctx, &sdkws.GroupInfoSetNameTips{Group: tips.Group, OpUser: tips.OpUser})
|
||||||
}
|
}
|
||||||
|
|
||||||
if num > 0 {
|
// if updatedData > 0, send the normal notification
|
||||||
|
if normalFlag {
|
||||||
g.notification.GroupInfoSetNotification(ctx, tips)
|
g.notification.GroupInfoSetNotification(ctx, tips)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1274,6 +1333,9 @@ func (g *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbgroup.GetGroupMembersCMSReq) (*pbgroup.GetGroupMembersCMSResp, error) {
|
func (g *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbgroup.GetGroupMembersCMSReq) (*pbgroup.GetGroupMembersCMSResp, error) {
|
||||||
|
if err := g.checkAdminOrInGroup(ctx, req.GroupID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
total, members, err := g.db.SearchGroupMember(ctx, req.UserName, req.GroupID, req.Pagination)
|
total, members, err := g.db.SearchGroupMember(ctx, req.UserName, req.GroupID, req.Pagination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1294,7 +1356,10 @@ func (g *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
total, requests, err := g.db.PageGroupRequestUser(ctx, req.UserID, req.Pagination)
|
handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
|
||||||
|
return int(e)
|
||||||
|
})
|
||||||
|
total, requests, err := g.db.PageGroupRequestUser(ctx, req.UserID, req.GroupIDs, handleResults, req.Pagination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1372,7 +1437,7 @@ func (g *groupServer) DismissGroup(ctx context.Context, req *pbgroup.DismissGrou
|
|||||||
if mcontext.GetOpUserID(ctx) == owner.UserID {
|
if mcontext.GetOpUserID(ctx) == owner.UserID {
|
||||||
tips.OpUser = g.groupMemberDB2PB(owner, 0)
|
tips.OpUser = g.groupMemberDB2PB(owner, 0)
|
||||||
}
|
}
|
||||||
g.notification.GroupDismissedNotification(ctx, tips)
|
g.notification.GroupDismissedNotification(ctx, tips, req.SendMessage)
|
||||||
}
|
}
|
||||||
membersID, err := g.db.FindGroupMemberUserID(ctx, group.GroupID)
|
membersID, err := g.db.FindGroupMemberUserID(ctx, group.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1649,6 +1714,11 @@ func (g *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbgroup.Get
|
|||||||
if datautil.Duplicate(req.GroupIDs) {
|
if datautil.Duplicate(req.GroupIDs) {
|
||||||
return nil, errs.ErrArgs.WrapMsg("groupIDs duplicate")
|
return nil, errs.ErrArgs.WrapMsg("groupIDs duplicate")
|
||||||
}
|
}
|
||||||
|
for _, groupID := range req.GroupIDs {
|
||||||
|
if err := g.checkAdminOrInGroup(ctx, groupID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
groups, err := g.db.FindGroup(ctx, req.GroupIDs)
|
groups, err := g.db.FindGroup(ctx, req.GroupIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1677,6 +1747,9 @@ func (g *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbgroup.Ge
|
|||||||
if len(req.GroupIDs) == 0 {
|
if len(req.GroupIDs) == 0 {
|
||||||
return nil, errs.ErrArgs.WrapMsg("groupIDs empty")
|
return nil, errs.ErrArgs.WrapMsg("groupIDs empty")
|
||||||
}
|
}
|
||||||
|
if err := authverify.CheckAccessV3(ctx, req.UserID, g.config.Share.IMAdminUserID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
members, err := g.db.FindGroupMemberUser(ctx, req.GroupIDs, req.UserID)
|
members, err := g.db.FindGroupMemberUser(ctx, req.GroupIDs, req.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1696,6 +1769,11 @@ func (g *groupServer) GetGroupMemberUserIDs(ctx context.Context, req *pbgroup.Ge
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if !authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) {
|
||||||
|
if !datautil.Contain(mcontext.GetOpUserID(ctx), userIDs...) {
|
||||||
|
return nil, errs.ErrNoPermission.WrapMsg("opUser no permission")
|
||||||
|
}
|
||||||
|
}
|
||||||
return &pbgroup.GetGroupMemberUserIDsResp{
|
return &pbgroup.GetGroupMemberUserIDsResp{
|
||||||
UserIDs: userIDs,
|
UserIDs: userIDs,
|
||||||
}, nil
|
}, nil
|
||||||
@@ -1705,6 +1783,9 @@ func (g *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req *pbgroup.
|
|||||||
if len(req.RoleLevels) == 0 {
|
if len(req.RoleLevels) == 0 {
|
||||||
return nil, errs.ErrArgs.WrapMsg("RoleLevels empty")
|
return nil, errs.ErrArgs.WrapMsg("RoleLevels empty")
|
||||||
}
|
}
|
||||||
|
if err := g.checkAdminOrInGroup(ctx, req.GroupID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
members, err := g.db.FindGroupMemberRoleLevels(ctx, req.GroupID, req.RoleLevels)
|
members, err := g.db.FindGroupMemberRoleLevels(ctx, req.GroupID, req.RoleLevels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
"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/authverify"
|
||||||
@@ -52,11 +53,11 @@ const (
|
|||||||
|
|
||||||
func NewNotificationSender(db controller.GroupDatabase, config *Config, userClient *rpcli.UserClient, msgClient *rpcli.MsgClient, conversationClient *rpcli.ConversationClient) *NotificationSender {
|
func NewNotificationSender(db controller.GroupDatabase, config *Config, userClient *rpcli.UserClient, msgClient *rpcli.MsgClient, conversationClient *rpcli.ConversationClient) *NotificationSender {
|
||||||
return &NotificationSender{
|
return &NotificationSender{
|
||||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig,
|
NotificationSender: notification.NewNotificationSender(&config.NotificationConfig,
|
||||||
rpcclient.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||||
return msgClient.SendMsg(ctx, req)
|
return msgClient.SendMsg(ctx, req)
|
||||||
}),
|
}),
|
||||||
rpcclient.WithUserRpcClient(userClient.GetUserInfo),
|
notification.WithUserRpcClient(userClient.GetUserInfo),
|
||||||
),
|
),
|
||||||
getUsersInfo: func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error) {
|
getUsersInfo: func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error) {
|
||||||
users, err := userClient.GetUsersInfo(ctx, userIDs)
|
users, err := userClient.GetUsersInfo(ctx, userIDs)
|
||||||
@@ -73,7 +74,7 @@ func NewNotificationSender(db controller.GroupDatabase, config *Config, userClie
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NotificationSender struct {
|
type NotificationSender struct {
|
||||||
*rpcclient.NotificationSender
|
*notification.NotificationSender
|
||||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||||
db controller.GroupDatabase
|
db controller.GroupDatabase
|
||||||
config *Config
|
config *Config
|
||||||
@@ -233,17 +234,17 @@ func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMember, appMang
|
|||||||
return result, nil
|
return result, nil
|
||||||
} */
|
} */
|
||||||
|
|
||||||
func (g *NotificationSender) fillOpUser(ctx context.Context, opUser **sdkws.GroupMemberFullInfo, groupID string) (err error) {
|
func (g *NotificationSender) fillOpUser(ctx context.Context, targetUser **sdkws.GroupMemberFullInfo, groupID string) (err error) {
|
||||||
return g.fillOpUserByUserID(ctx, mcontext.GetOpUserID(ctx), opUser, groupID)
|
return g.fillUserByUserID(ctx, mcontext.GetOpUserID(ctx), targetUser, groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) fillOpUserByUserID(ctx context.Context, userID string, opUser **sdkws.GroupMemberFullInfo, groupID string) error {
|
func (g *NotificationSender) fillUserByUserID(ctx context.Context, userID string, targetUser **sdkws.GroupMemberFullInfo, groupID string) error {
|
||||||
if opUser == nil {
|
if targetUser == nil {
|
||||||
return errs.ErrInternalServer.WrapMsg("**sdkws.GroupMemberFullInfo is nil")
|
return errs.ErrInternalServer.WrapMsg("**sdkws.GroupMemberFullInfo is nil")
|
||||||
}
|
}
|
||||||
if groupID != "" {
|
if groupID != "" {
|
||||||
if authverify.IsManagerUserID(userID, g.config.Share.IMAdminUserID) {
|
if authverify.IsManagerUserID(userID, g.config.Share.IMAdminUserID) {
|
||||||
*opUser = &sdkws.GroupMemberFullInfo{
|
*targetUser = &sdkws.GroupMemberFullInfo{
|
||||||
GroupID: groupID,
|
GroupID: groupID,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
RoleLevel: constant.GroupAdmin,
|
RoleLevel: constant.GroupAdmin,
|
||||||
@@ -252,7 +253,7 @@ func (g *NotificationSender) fillOpUserByUserID(ctx context.Context, userID stri
|
|||||||
} else {
|
} else {
|
||||||
member, err := g.db.TakeGroupMember(ctx, groupID, userID)
|
member, err := g.db.TakeGroupMember(ctx, groupID, userID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
*opUser = g.groupMemberDB2PB(member, 0)
|
*targetUser = g.groupMemberDB2PB(member, 0)
|
||||||
} else if !(errors.Is(err, mongo.ErrNoDocuments) || errs.ErrRecordNotFound.Is(err)) {
|
} else if !(errors.Is(err, mongo.ErrNoDocuments) || errs.ErrRecordNotFound.Is(err)) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -262,8 +263,8 @@ func (g *NotificationSender) fillOpUserByUserID(ctx context.Context, userID stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if *opUser == nil {
|
if *targetUser == nil {
|
||||||
*opUser = &sdkws.GroupMemberFullInfo{
|
*targetUser = &sdkws.GroupMemberFullInfo{
|
||||||
GroupID: groupID,
|
GroupID: groupID,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Nickname: user.Nickname,
|
Nickname: user.Nickname,
|
||||||
@@ -271,11 +272,11 @@ func (g *NotificationSender) fillOpUserByUserID(ctx context.Context, userID stri
|
|||||||
OperatorUserID: userID,
|
OperatorUserID: userID,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (*opUser).Nickname == "" {
|
if (*targetUser).Nickname == "" {
|
||||||
(*opUser).Nickname = user.Nickname
|
(*targetUser).Nickname = user.Nickname
|
||||||
}
|
}
|
||||||
if (*opUser).FaceURL == "" {
|
if (*targetUser).FaceURL == "" {
|
||||||
(*opUser).FaceURL = user.FaceURL
|
(*targetUser).FaceURL = user.FaceURL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -283,7 +284,8 @@ func (g *NotificationSender) fillOpUserByUserID(ctx context.Context, userID stri
|
|||||||
|
|
||||||
func (g *NotificationSender) setVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string) {
|
func (g *NotificationSender) setVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string) {
|
||||||
versions := versionctx.GetVersionLog(ctx).Get()
|
versions := versionctx.GetVersionLog(ctx).Get()
|
||||||
for _, coll := range versions {
|
for i := len(versions) - 1; i >= 0; i-- {
|
||||||
|
coll := versions[i]
|
||||||
if coll.Name == collName && coll.Doc.DID == id {
|
if coll.Name == collName && coll.Doc.DID == id {
|
||||||
*version = uint64(coll.Doc.Version)
|
*version = uint64(coll.Doc.Version)
|
||||||
*versionID = coll.Doc.ID.Hex()
|
*versionID = coll.Doc.ID.Hex()
|
||||||
@@ -307,7 +309,7 @@ func (g *NotificationSender) setSortVersion(ctx context.Context, version *uint64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips) {
|
func (g *NotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips, SendMessage *bool) {
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -318,7 +320,7 @@ func (g *NotificationSender) GroupCreatedNotification(ctx context.Context, tips
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupCreatedNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupCreatedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) GroupInfoSetNotification(ctx context.Context, tips *sdkws.GroupInfoSetTips) {
|
func (g *NotificationSender) GroupInfoSetNotification(ctx context.Context, tips *sdkws.GroupInfoSetTips) {
|
||||||
@@ -332,7 +334,7 @@ func (g *NotificationSender) GroupInfoSetNotification(ctx context.Context, tips
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNotification, tips, rpcclient.WithRpcGetUserName())
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNotification, tips, notification.WithRpcGetUserName())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) GroupInfoSetNameNotification(ctx context.Context, tips *sdkws.GroupInfoSetNameTips) {
|
func (g *NotificationSender) GroupInfoSetNameNotification(ctx context.Context, tips *sdkws.GroupInfoSetNameTips) {
|
||||||
@@ -349,7 +351,7 @@ func (g *NotificationSender) GroupInfoSetNameNotification(ctx context.Context, t
|
|||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNameNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNameNotification, tips)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Context, tips *sdkws.GroupInfoSetAnnouncementTips) {
|
func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Context, tips *sdkws.GroupInfoSetAnnouncementTips, sendMessage *bool) {
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -360,16 +362,49 @@ func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Co
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetAnnouncementNotification, tips, rpcclient.WithRpcGetUserName())
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetAnnouncementNotification, tips, notification.WithRpcGetUserName(), notification.WithSendMessage(sendMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbgroup.JoinGroupReq) {
|
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) {
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err)
|
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
|
var group *sdkws.GroupInfo
|
||||||
group, err = g.getGroupInfo(ctx, req.GroupID)
|
group, err = g.getGroupInfo(ctx, req.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -385,7 +420,13 @@ func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Contex
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
userIDs = append(userIDs, req.InviterUserID, mcontext.GetOpUserID(ctx))
|
userIDs = append(userIDs, req.InviterUserID, mcontext.GetOpUserID(ctx))
|
||||||
tips := &sdkws.JoinGroupApplicationTips{Group: group, Applicant: user, ReqMsg: req.ReqMessage}
|
tips := &sdkws.JoinGroupApplicationTips{
|
||||||
|
Group: group,
|
||||||
|
Applicant: user,
|
||||||
|
ReqMsg: req.ReqMessage,
|
||||||
|
Uuid: g.uuid(),
|
||||||
|
Request: request,
|
||||||
|
}
|
||||||
for _, userID := range datautil.Distinct(userIDs) {
|
for _, userID := range datautil.Distinct(userIDs) {
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.JoinGroupApplicationNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.JoinGroupApplicationNotification, tips)
|
||||||
}
|
}
|
||||||
@@ -415,6 +456,11 @@ func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Co
|
|||||||
log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err)
|
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
|
var group *sdkws.GroupInfo
|
||||||
group, err = g.getGroupInfo(ctx, req.GroupID)
|
group, err = g.getGroupInfo(ctx, req.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -430,8 +476,14 @@ func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Co
|
|||||||
if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil {
|
if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
tips := &sdkws.GroupApplicationAcceptedTips{
|
||||||
|
Group: group,
|
||||||
|
OpUser: opUser,
|
||||||
|
HandleMsg: req.HandledMsg,
|
||||||
|
Uuid: g.uuid(),
|
||||||
|
Request: request,
|
||||||
|
}
|
||||||
for _, userID := range append(userIDs, req.FromUserID) {
|
for _, userID := range append(userIDs, req.FromUserID) {
|
||||||
tips := &sdkws.GroupApplicationAcceptedTips{Group: group, OpUser: opUser, HandleMsg: req.HandledMsg}
|
|
||||||
if userID == req.FromUserID {
|
if userID == req.FromUserID {
|
||||||
tips.ReceiverAs = applicantReceiver
|
tips.ReceiverAs = applicantReceiver
|
||||||
} else {
|
} else {
|
||||||
@@ -448,6 +500,11 @@ func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Co
|
|||||||
log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err)
|
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
|
var group *sdkws.GroupInfo
|
||||||
group, err = g.getGroupInfo(ctx, req.GroupID)
|
group, err = g.getGroupInfo(ctx, req.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -463,8 +520,14 @@ func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Co
|
|||||||
if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil {
|
if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
tips := &sdkws.GroupApplicationRejectedTips{
|
||||||
|
Group: group,
|
||||||
|
OpUser: opUser,
|
||||||
|
HandleMsg: req.HandledMsg,
|
||||||
|
Uuid: g.uuid(),
|
||||||
|
Request: request,
|
||||||
|
}
|
||||||
for _, userID := range append(userIDs, req.FromUserID) {
|
for _, userID := range append(userIDs, req.FromUserID) {
|
||||||
tips := &sdkws.GroupApplicationAcceptedTips{Group: group, OpUser: opUser, HandleMsg: req.HandledMsg}
|
|
||||||
if userID == req.FromUserID {
|
if userID == req.FromUserID {
|
||||||
tips.ReceiverAs = applicantReceiver
|
tips.ReceiverAs = applicantReceiver
|
||||||
} else {
|
} else {
|
||||||
@@ -505,7 +568,7 @@ func (g *NotificationSender) GroupOwnerTransferredNotification(ctx context.Conte
|
|||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupOwnerTransferredNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupOwnerTransferredNotification, tips)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips) {
|
func (g *NotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips, SendMessage *bool) {
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -516,10 +579,14 @@ func (g *NotificationSender) MemberKickedNotification(ctx context.Context, tips
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.MemberKickedNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.MemberKickedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx context.Context, groupID string, invitedOpUserID string, entrantUserID ...string) error {
|
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 {
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -556,20 +623,18 @@ func (g *NotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx co
|
|||||||
InvitedUserList: users,
|
InvitedUserList: users,
|
||||||
}
|
}
|
||||||
opUserID := mcontext.GetOpUserID(ctx)
|
opUserID := mcontext.GetOpUserID(ctx)
|
||||||
if err = g.fillOpUserByUserID(ctx, opUserID, &tips.OpUser, tips.Group.GroupID); err != nil {
|
if err = g.fillUserByUserID(ctx, opUserID, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch {
|
if invitedOpUserID == opUserID {
|
||||||
case invitedOpUserID == "":
|
|
||||||
case invitedOpUserID == opUserID:
|
|
||||||
tips.InviterUser = tips.OpUser
|
tips.InviterUser = tips.OpUser
|
||||||
default:
|
} else {
|
||||||
if err = g.fillOpUserByUserID(ctx, invitedOpUserID, &tips.InviterUser, tips.Group.GroupID); err != nil {
|
if err = g.fillUserByUserID(ctx, invitedOpUserID, &tips.InviterUser, tips.Group.GroupID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,7 +679,7 @@ func (g *NotificationSender) MemberEnterNotification(ctx context.Context, groupI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) GroupDismissedNotification(ctx context.Context, tips *sdkws.GroupDismissedTips) {
|
func (g *NotificationSender) GroupDismissedNotification(ctx context.Context, tips *sdkws.GroupDismissedTips, SendMessage *bool) {
|
||||||
var err error
|
var err error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -624,7 +689,7 @@ func (g *NotificationSender) GroupDismissedNotification(ctx context.Context, tip
|
|||||||
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupDismissedNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupDismissedNotification, tips, notification.WithSendMessage(SendMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *NotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) {
|
func (g *NotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) {
|
||||||
@@ -781,7 +846,7 @@ func (g *NotificationSender) GroupMemberSetToAdminNotification(ctx context.Conte
|
|||||||
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
g.setSortVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID, &tips.GroupSortVersion)
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToAdminNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToAdminNotification, tips)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,6 +871,6 @@ func (g *NotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx contex
|
|||||||
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
if err = g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID)
|
g.setSortVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID, &tips.GroupSortVersion)
|
||||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToOrdinaryUserNotification, tips)
|
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToOrdinaryUserNotification, tips)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||||
"github.com/openimsdk/protocol/group"
|
"github.com/openimsdk/protocol/group"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
)
|
)
|
||||||
@@ -26,6 +27,9 @@ func (s *groupServer) GroupCreateCount(ctx context.Context, req *group.GroupCrea
|
|||||||
if req.Start > req.End {
|
if req.Start > req.End {
|
||||||
return nil, errs.ErrArgs.WrapMsg("start > end: %d > %d", 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)
|
total, err := s.db.CountTotal(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
+43
-153
@@ -12,15 +12,23 @@ import (
|
|||||||
pbgroup "github.com/openimsdk/protocol/group"
|
pbgroup "github.com/openimsdk/protocol/group"
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/mcontext"
|
||||||
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *groupServer) GetFullGroupMemberUserIDs(ctx context.Context, req *pbgroup.GetFullGroupMemberUserIDsReq) (*pbgroup.GetFullGroupMemberUserIDsResp, error) {
|
const versionSyncLimit = 500
|
||||||
vl, err := s.db.FindMaxGroupMemberVersionCache(ctx, req.GroupID)
|
|
||||||
|
func (g *groupServer) GetFullGroupMemberUserIDs(ctx context.Context, req *pbgroup.GetFullGroupMemberUserIDsReq) (*pbgroup.GetFullGroupMemberUserIDsResp, error) {
|
||||||
|
userIDs, err := g.db.FindGroupMemberUserID(ctx, req.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
userIDs, err := s.db.FindGroupMemberUserID(ctx, req.GroupID)
|
if !authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) {
|
||||||
|
if !datautil.Contain(mcontext.GetOpUserID(ctx), userIDs...) {
|
||||||
|
return nil, errs.ErrNoPermission.WrapMsg("op user not in group")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vl, err := g.db.FindMaxGroupMemberVersionCache(ctx, req.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -37,6 +45,9 @@ func (s *groupServer) GetFullGroupMemberUserIDs(ctx context.Context, req *pbgrou
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *groupServer) GetFullJoinGroupIDs(ctx context.Context, req *pbgroup.GetFullJoinGroupIDsReq) (*pbgroup.GetFullJoinGroupIDsResp, error) {
|
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)
|
vl, err := s.db.FindMaxJoinGroupVersionCache(ctx, req.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -58,6 +69,9 @@ func (s *groupServer) GetFullJoinGroupIDs(ctx context.Context, req *pbgroup.GetF
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *groupServer) GetIncrementalGroupMember(ctx context.Context, req *pbgroup.GetIncrementalGroupMemberReq) (*pbgroup.GetIncrementalGroupMemberResp, error) {
|
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)
|
group, err := s.db.TakeGroup(ctx, req.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -132,152 +146,8 @@ func (s *groupServer) GetIncrementalGroupMember(ctx context.Context, req *pbgrou
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *groupServer) BatchGetIncrementalGroupMember(ctx context.Context, req *pbgroup.BatchGetIncrementalGroupMemberReq) (resp *pbgroup.BatchGetIncrementalGroupMemberResp, err error) {
|
func (g *groupServer) GetIncrementalJoinGroup(ctx context.Context, req *pbgroup.GetIncrementalJoinGroupReq) (*pbgroup.GetIncrementalJoinGroupResp, error) {
|
||||||
type VersionInfo struct {
|
if err := authverify.CheckAccessV3(ctx, req.UserID, g.config.Share.IMAdminUserID); err != nil {
|
||||||
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
|
return nil, err
|
||||||
}
|
}
|
||||||
opt := incrversion.Option[*sdkws.GroupInfo, pbgroup.GetIncrementalJoinGroupResp]{
|
opt := incrversion.Option[*sdkws.GroupInfo, pbgroup.GetIncrementalJoinGroupResp]{
|
||||||
@@ -285,9 +155,9 @@ func (s *groupServer) GetIncrementalJoinGroup(ctx context.Context, req *pbgroup.
|
|||||||
VersionKey: req.UserID,
|
VersionKey: req.UserID,
|
||||||
VersionID: req.VersionID,
|
VersionID: req.VersionID,
|
||||||
VersionNumber: req.Version,
|
VersionNumber: req.Version,
|
||||||
Version: s.db.FindJoinIncrVersion,
|
Version: g.db.FindJoinIncrVersion,
|
||||||
CacheMaxVersion: s.db.FindMaxJoinGroupVersionCache,
|
CacheMaxVersion: g.db.FindMaxJoinGroupVersionCache,
|
||||||
Find: s.getGroupsInfo,
|
Find: g.getGroupsInfo,
|
||||||
Resp: func(version *model.VersionLog, delIDs []string, insertList, updateList []*sdkws.GroupInfo, full bool) *pbgroup.GetIncrementalJoinGroupResp {
|
Resp: func(version *model.VersionLog, delIDs []string, insertList, updateList []*sdkws.GroupInfo, full bool) *pbgroup.GetIncrementalJoinGroupResp {
|
||||||
return &pbgroup.GetIncrementalJoinGroupResp{
|
return &pbgroup.GetIncrementalJoinGroupResp{
|
||||||
VersionID: version.ID.Hex(),
|
VersionID: version.ID.Hex(),
|
||||||
@@ -301,3 +171,23 @@ func (s *groupServer) GetIncrementalJoinGroup(ctx context.Context, req *pbgroup.
|
|||||||
}
|
}
|
||||||
return opt.Build()
|
return opt.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *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 := g.GetIncrementalGroupMember(ctx, memberReq)
|
||||||
|
if err != nil {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MsgNotificationSender struct {
|
type MsgNotificationSender struct {
|
||||||
*rpcclient.NotificationSender
|
*notification.NotificationSender
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMsgNotificationSender(config *Config, opts ...rpcclient.NotificationSenderOptions) *MsgNotificationSender {
|
func NewMsgNotificationSender(config *Config, opts ...notification.NotificationSenderOptions) *MsgNotificationSender {
|
||||||
return &MsgNotificationSender{rpcclient.NewNotificationSender(&config.NotificationConfig, opts...)}
|
return &MsgNotificationSender{notification.NewNotificationSender(&config.NotificationConfig, opts...)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MsgNotificationSender) UserDeleteMsgsNotification(ctx context.Context, userID, conversationID string, seqs []int64) {
|
func (m *MsgNotificationSender) UserDeleteMsgsNotification(ctx context.Context, userID, conversationID string, seqs []int64) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package msg
|
|||||||
import (
|
import (
|
||||||
"context"
|
"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/rpcli"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
@@ -28,7 +29,6 @@ import (
|
|||||||
"github.com/openimsdk/tools/db/redisutil"
|
"github.com/openimsdk/tools/db/redisutil"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
"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/rpccache"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||||
"github.com/openimsdk/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
"github.com/openimsdk/protocol/conversation"
|
"github.com/openimsdk/protocol/conversation"
|
||||||
@@ -64,7 +64,7 @@ type msgServer struct {
|
|||||||
GroupLocalCache *rpccache.GroupLocalCache // Local cache for group data.
|
GroupLocalCache *rpccache.GroupLocalCache // Local cache for group data.
|
||||||
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
|
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
|
||||||
Handlers MessageInterceptorChain // Chain of handlers for processing messages.
|
Handlers MessageInterceptorChain // Chain of handlers for processing messages.
|
||||||
notificationSender *rpcclient.NotificationSender // RPC client for sending notifications.
|
notificationSender *notification.NotificationSender // RPC client for sending notifications.
|
||||||
msgNotificationSender *MsgNotificationSender // RPC client for sending msg notifications.
|
msgNotificationSender *MsgNotificationSender // RPC client for sending msg notifications.
|
||||||
config *Config // Global configuration settings.
|
config *Config // Global configuration settings.
|
||||||
webhookClient *webhook.Client
|
webhookClient *webhook.Client
|
||||||
@@ -104,19 +104,19 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userConn, err := client.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
groupConn, err := client.GetConn(ctx, config.Discovery.RpcService.Group)
|
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
friendConn, err := client.GetConn(ctx, config.Discovery.RpcService.Friend)
|
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
conversationConn, err := client.GetConn(ctx, config.Discovery.RpcService.Conversation)
|
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -133,8 +133,8 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
|||||||
conversationClient: conversationClient,
|
conversationClient: conversationClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.notificationSender = rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithLocalSendMsg(s.SendMsg))
|
s.notificationSender = notification.NewNotificationSender(&config.NotificationConfig, notification.WithLocalSendMsg(s.SendMsg))
|
||||||
s.msgNotificationSender = NewMsgNotificationSender(config, rpcclient.WithLocalSendMsg(s.SendMsg))
|
s.msgNotificationSender = NewMsgNotificationSender(config, notification.WithLocalSendMsg(s.SendMsg))
|
||||||
|
|
||||||
msg.RegisterMsgServer(server, s)
|
msg.RegisterMsgServer(server, s)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package relation
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||||
|
|
||||||
"github.com/openimsdk/tools/mq/memamq"
|
"github.com/openimsdk/tools/mq/memamq"
|
||||||
@@ -92,32 +93,34 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
userConn, err := client.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msgConn, err := client.GetConn(ctx, config.Discovery.RpcService.Msg)
|
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userClient := rpcli.NewUserClient(userConn)
|
userClient := rpcli.NewUserClient(userConn)
|
||||||
|
|
||||||
|
database := controller.NewFriendDatabase(
|
||||||
|
friendMongoDB,
|
||||||
|
friendRequestMongoDB,
|
||||||
|
redis.NewFriendCacheRedis(rdb, &config.LocalCacheConfig, friendMongoDB, redis.GetRocksCacheOptions()),
|
||||||
|
mgocli.GetTx(),
|
||||||
|
)
|
||||||
// Initialize notification sender
|
// Initialize notification sender
|
||||||
notificationSender := NewFriendNotificationSender(
|
notificationSender := NewFriendNotificationSender(
|
||||||
&config.NotificationConfig,
|
&config.NotificationConfig,
|
||||||
rpcli.NewMsgClient(msgConn),
|
rpcli.NewMsgClient(msgConn),
|
||||||
WithRpcFunc(userClient.GetUsersInfo),
|
WithRpcFunc(userClient.GetUsersInfo),
|
||||||
|
WithFriendDB(database),
|
||||||
)
|
)
|
||||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||||
|
|
||||||
// Register Friend server with refactored MongoDB and Redis integrations
|
// Register Friend server with refactored MongoDB and Redis integrations
|
||||||
relation.RegisterFriendServer(server, &friendServer{
|
relation.RegisterFriendServer(server, &friendServer{
|
||||||
db: controller.NewFriendDatabase(
|
db: database,
|
||||||
friendMongoDB,
|
|
||||||
friendRequestMongoDB,
|
|
||||||
redis.NewFriendCacheRedis(rdb, &config.LocalCacheConfig, friendMongoDB, redis.GetRocksCacheOptions()),
|
|
||||||
mgocli.GetTx(),
|
|
||||||
),
|
|
||||||
blackDatabase: controller.NewBlackDatabase(
|
blackDatabase: controller.NewBlackDatabase(
|
||||||
blackMongoDB,
|
blackMongoDB,
|
||||||
redis.NewBlackCacheRedis(rdb, &config.LocalCacheConfig, blackMongoDB, redis.GetRocksCacheOptions()),
|
redis.NewBlackCacheRedis(rdb, &config.LocalCacheConfig, blackMongoDB, redis.GetRocksCacheOptions()),
|
||||||
@@ -191,7 +194,7 @@ func (s *friendServer) ImportFriends(ctx context.Context, req *relation.ImportFr
|
|||||||
FromUserID: req.OwnerUserID,
|
FromUserID: req.OwnerUserID,
|
||||||
ToUserID: userID,
|
ToUserID: userID,
|
||||||
HandleResult: constant.FriendResponseAgree,
|
HandleResult: constant.FriendResponseAgree,
|
||||||
})
|
}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.webhookAfterImportFriends(ctx, &s.config.WebhooksConfig.AfterImportFriends, req)
|
s.webhookAfterImportFriends(ctx, &s.config.WebhooksConfig.AfterImportFriends, req)
|
||||||
@@ -220,7 +223,7 @@ func (s *friendServer) RespondFriendApply(ctx context.Context, req *relation.Res
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.webhookAfterAddFriendAgree(ctx, &s.config.WebhooksConfig.AfterAddFriendAgree, req)
|
s.webhookAfterAddFriendAgree(ctx, &s.config.WebhooksConfig.AfterAddFriendAgree, req)
|
||||||
s.notificationSender.FriendApplicationAgreedNotification(ctx, req)
|
s.notificationSender.FriendApplicationAgreedNotification(ctx, req, true)
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
if req.HandleResult == constant.FriendResponseRefuse {
|
if req.HandleResult == constant.FriendResponseRefuse {
|
||||||
@@ -281,6 +284,9 @@ func (s *friendServer) SetFriendRemark(ctx context.Context, req *relation.SetFri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *friendServer) GetFriendInfo(ctx context.Context, req *relation.GetFriendInfoReq) (*relation.GetFriendInfoResp, error) {
|
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)
|
friends, err := s.db.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -293,6 +299,9 @@ func (s *friendServer) GetDesignatedFriends(ctx context.Context, req *relation.G
|
|||||||
if datautil.Duplicate(req.FriendUserIDs) {
|
if datautil.Duplicate(req.FriendUserIDs) {
|
||||||
return nil, errs.ErrArgs.WrapMsg("friend userID repeated")
|
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)
|
friends, err := s.getFriend(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -322,7 +331,7 @@ func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp = &relation.GetDesignatedFriendsApplyResp{}
|
resp = &relation.GetDesignatedFriendsApplyResp{}
|
||||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userClient.GetUsersInfoMap)
|
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.getCommonUserMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -335,13 +344,16 @@ func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *rel
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
total, friendRequests, err := s.db.PageFriendRequestToMe(ctx, req.UserID, req.Pagination)
|
handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
|
||||||
|
return int(e)
|
||||||
|
})
|
||||||
|
total, friendRequests, err := s.db.PageFriendRequestToMe(ctx, req.UserID, handleResults, req.Pagination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = &relation.GetPaginationFriendsApplyToResp{}
|
resp = &relation.GetPaginationFriendsApplyToResp{}
|
||||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userClient.GetUsersInfoMap)
|
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.getCommonUserMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -358,12 +370,15 @@ func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *r
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
total, friendRequests, err := s.db.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination)
|
handleResults := datautil.Slice(req.HandleResults, func(e int32) int {
|
||||||
|
return int(e)
|
||||||
|
})
|
||||||
|
total, friendRequests, err := s.db.PageFriendRequestFromMe(ctx, req.UserID, handleResults, req.Pagination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userClient.GetUsersInfoMap)
|
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.getCommonUserMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -427,6 +442,10 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *relatio
|
|||||||
return nil, errs.ErrArgs.WrapMsg("userIDList repeated")
|
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.userClient.GetUsersInfoMap(ctx, req.UserIDList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -506,6 +525,10 @@ func (s *friendServer) UpdateFriends(
|
|||||||
return nil, errs.ErrArgs.WrapMsg("friendIDList repeated")
|
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)
|
_, err := s.db.FindFriendsWithError(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -531,3 +554,28 @@ func (s *friendServer) UpdateFriends(
|
|||||||
s.notificationSender.FriendsInfoUpdateNotification(ctx, req.OwnerUserID, req.FriendUserIDs)
|
s.notificationSender.FriendsInfoUpdateNotification(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||||
return resp, nil
|
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) 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,8 +16,12 @@ package relation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||||
"github.com/openimsdk/protocol/msg"
|
"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/database"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
||||||
@@ -36,7 +40,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FriendNotificationSender struct {
|
type FriendNotificationSender struct {
|
||||||
*rpcclient.NotificationSender
|
*notification.NotificationSender
|
||||||
// Target not found err
|
// Target not found err
|
||||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||||
// db controller
|
// db controller
|
||||||
@@ -51,9 +55,7 @@ func WithFriendDB(db controller.FriendDatabase) friendNotificationSenderOptions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithDBFunc(
|
func WithDBFunc(fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error)) friendNotificationSenderOptions {
|
||||||
fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error),
|
|
||||||
) friendNotificationSenderOptions {
|
|
||||||
return func(s *FriendNotificationSender) {
|
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 []common_user.CommonUser, err error) {
|
||||||
users, err := fn(ctx, userIDs)
|
users, err := fn(ctx, userIDs)
|
||||||
@@ -69,9 +71,7 @@ func WithDBFunc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithRpcFunc(
|
func WithRpcFunc(fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error)) friendNotificationSenderOptions {
|
||||||
fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error),
|
|
||||||
) friendNotificationSenderOptions {
|
|
||||||
return func(s *FriendNotificationSender) {
|
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 []common_user.CommonUser, err error) {
|
||||||
users, err := fn(ctx, userIDs)
|
users, err := fn(ctx, userIDs)
|
||||||
@@ -89,7 +89,7 @@ func WithRpcFunc(
|
|||||||
|
|
||||||
func NewFriendNotificationSender(conf *config.Notification, msgClient *rpcli.MsgClient, opts ...friendNotificationSenderOptions) *FriendNotificationSender {
|
func NewFriendNotificationSender(conf *config.Notification, msgClient *rpcli.MsgClient, opts ...friendNotificationSenderOptions) *FriendNotificationSender {
|
||||||
f := &FriendNotificationSender{
|
f := &FriendNotificationSender{
|
||||||
NotificationSender: rpcclient.NewNotificationSender(conf, rpcclient.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
NotificationSender: notification.NewNotificationSender(conf, notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||||
return msgClient.SendMsg(ctx, req)
|
return msgClient.SendMsg(ctx, req)
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
@@ -99,10 +99,7 @@ func NewFriendNotificationSender(conf *config.Notification, msgClient *rpcli.Msg
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FriendNotificationSender) getUsersInfoMap(
|
func (f *FriendNotificationSender) getUsersInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error) {
|
||||||
ctx context.Context,
|
|
||||||
userIDs []string,
|
|
||||||
) (map[string]*sdkws.UserInfo, error) {
|
|
||||||
users, err := f.getUsersInfo(ctx, userIDs)
|
users, err := f.getUsersInfo(ctx, userIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -115,10 +112,7 @@ func (f *FriendNotificationSender) getUsersInfoMap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint:unused
|
//nolint:unused
|
||||||
func (f *FriendNotificationSender) getFromToUserNickname(
|
func (f *FriendNotificationSender) getFromToUserNickname(ctx context.Context, fromUserID, toUserID string) (string, string, error) {
|
||||||
ctx context.Context,
|
|
||||||
fromUserID, toUserID string,
|
|
||||||
) (string, string, error) {
|
|
||||||
users, err := f.getUsersInfoMap(ctx, []string{fromUserID, toUserID})
|
users, err := f.getUsersInfoMap(ctx, []string{fromUserID, toUserID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", nil
|
return "", "", nil
|
||||||
@@ -131,60 +125,113 @@ func (f *FriendNotificationSender) UserInfoUpdatedNotification(ctx context.Conte
|
|||||||
f.Notification(ctx, mcontext.GetOpUserID(ctx), changedUserID, constant.UserInfoUpdatedNotification, &tips)
|
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) {
|
func (f *FriendNotificationSender) FriendApplicationAddNotification(ctx context.Context, req *relation.ApplyToAddFriendReq) {
|
||||||
tips := sdkws.FriendApplicationTips{FromToUserID: &sdkws.FromToUserID{
|
request, err := f.getFriendRequests(ctx, req.FromUserID, req.ToUserID)
|
||||||
FromUserID: req.FromUserID,
|
if err != nil {
|
||||||
ToUserID: req.ToUserID,
|
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,
|
||||||
|
}
|
||||||
f.Notification(ctx, req.FromUserID, req.ToUserID, constant.FriendApplicationNotification, &tips)
|
f.Notification(ctx, req.FromUserID, req.ToUserID, constant.FriendApplicationNotification, &tips)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FriendNotificationSender) FriendApplicationAgreedNotification(
|
func (f *FriendNotificationSender) FriendApplicationAgreedNotification(ctx context.Context, req *relation.RespondFriendApplyReq, checkReq bool) {
|
||||||
ctx context.Context,
|
var (
|
||||||
req *relation.RespondFriendApplyReq,
|
request *sdkws.FriendRequest
|
||||||
) {
|
err error
|
||||||
tips := sdkws.FriendApplicationApprovedTips{FromToUserID: &sdkws.FromToUserID{
|
)
|
||||||
FromUserID: req.FromUserID,
|
if checkReq {
|
||||||
ToUserID: req.ToUserID,
|
request, err = f.getFriendRequests(ctx, req.FromUserID, req.ToUserID)
|
||||||
}, HandleMsg: req.HandleMsg}
|
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,
|
||||||
|
}
|
||||||
f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationApprovedNotification, &tips)
|
f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationApprovedNotification, &tips)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FriendNotificationSender) FriendApplicationRefusedNotification(
|
func (f *FriendNotificationSender) FriendApplicationRefusedNotification(ctx context.Context, req *relation.RespondFriendApplyReq) {
|
||||||
ctx context.Context,
|
request, err := f.getFriendRequests(ctx, req.FromUserID, req.ToUserID)
|
||||||
req *relation.RespondFriendApplyReq,
|
if err != nil {
|
||||||
) {
|
log.ZError(ctx, "FriendApplicationRefusedNotification get friend request", err, "fromUserID", req.FromUserID, "toUserID", req.ToUserID)
|
||||||
tips := sdkws.FriendApplicationApprovedTips{FromToUserID: &sdkws.FromToUserID{
|
return
|
||||||
FromUserID: req.FromUserID,
|
}
|
||||||
ToUserID: req.ToUserID,
|
tips := sdkws.FriendApplicationRejectedTips{
|
||||||
}, HandleMsg: req.HandleMsg}
|
FromToUserID: &sdkws.FromToUserID{
|
||||||
|
FromUserID: req.FromUserID,
|
||||||
|
ToUserID: req.ToUserID,
|
||||||
|
},
|
||||||
|
HandleMsg: req.HandleMsg,
|
||||||
|
Request: request,
|
||||||
|
}
|
||||||
f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationRejectedNotification, &tips)
|
f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationRejectedNotification, &tips)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FriendNotificationSender) FriendAddedNotification(
|
//func (f *FriendNotificationSender) FriendAddedNotification(ctx context.Context, operationID, opUserID, fromUserID, toUserID string) error {
|
||||||
ctx context.Context,
|
// tips := sdkws.FriendAddedTips{Friend: &sdkws.FriendInfo{}, OpUser: &sdkws.PublicUserInfo{}}
|
||||||
operationID, opUserID, fromUserID, toUserID string,
|
// user, err := f.getUsersInfo(ctx, []string{opUserID})
|
||||||
) error {
|
// if err != nil {
|
||||||
tips := sdkws.FriendAddedTips{Friend: &sdkws.FriendInfo{}, OpUser: &sdkws.PublicUserInfo{}}
|
// return err
|
||||||
user, err := f.getUsersInfo(ctx, []string{opUserID})
|
// }
|
||||||
if err != nil {
|
// tips.OpUser.UserID = user[0].GetUserID()
|
||||||
return err
|
// tips.OpUser.Ex = user[0].GetEx()
|
||||||
}
|
// tips.OpUser.Nickname = user[0].GetNickname()
|
||||||
tips.OpUser.UserID = user[0].GetUserID()
|
// tips.OpUser.FaceURL = user[0].GetFaceURL()
|
||||||
tips.OpUser.Ex = user[0].GetEx()
|
// friends, err := f.db.FindFriendsWithError(ctx, fromUserID, []string{toUserID})
|
||||||
tips.OpUser.Nickname = user[0].GetNickname()
|
// if err != nil {
|
||||||
tips.OpUser.FaceURL = user[0].GetFaceURL()
|
// return err
|
||||||
friends, err := f.db.FindFriendsWithError(ctx, fromUserID, []string{toUserID})
|
// }
|
||||||
if err != nil {
|
// tips.Friend, err = convert.FriendDB2Pb(ctx, friends[0], f.getUsersInfoMap)
|
||||||
return err
|
// if err != nil {
|
||||||
}
|
// return err
|
||||||
tips.Friend, err = convert.FriendDB2Pb(ctx, friends[0], f.getUsersInfoMap)
|
// }
|
||||||
if err != nil {
|
// f.Notification(ctx, fromUserID, toUserID, constant.FriendAddedNotification, &tips)
|
||||||
return err
|
// return nil
|
||||||
}
|
//}
|
||||||
f.Notification(ctx, fromUserID, toUserID, constant.FriendAddedNotification, &tips)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FriendNotificationSender) FriendDeletedNotification(ctx context.Context, req *relation.DeleteFriendReq) {
|
func (f *FriendNotificationSender) FriendDeletedNotification(ctx context.Context, req *relation.DeleteFriendReq) {
|
||||||
tips := sdkws.FriendDeletedTips{FromToUserID: &sdkws.FromToUserID{
|
tips := sdkws.FriendDeletedTips{FromToUserID: &sdkws.FromToUserID{
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ package relation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/util/hashutil"
|
"github.com/openimsdk/open-im-server/v3/pkg/util/hashutil"
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/incrversion"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/incrversion"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||||
@@ -39,6 +40,9 @@ func (s *friendServer) NotificationUserInfoUpdate(ctx context.Context, req *rela
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *friendServer) GetFullFriendUserIDs(ctx context.Context, req *relation.GetFullFriendUserIDsReq) (*relation.GetFullFriendUserIDsResp, error) {
|
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)
|
vl, err := s.db.FindMaxFriendVersionCache(ctx, req.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||||
@@ -37,7 +38,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (t *thirdServer) PartLimit(ctx context.Context, req *third.PartLimitReq) (*third.PartLimitResp, error) {
|
func (t *thirdServer) PartLimit(ctx context.Context, req *third.PartLimitReq) (*third.PartLimitResp, error) {
|
||||||
limit := t.s3dataBase.PartLimit()
|
limit, err := t.s3dataBase.PartLimit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &third.PartLimitResp{
|
return &third.PartLimitResp{
|
||||||
MinPartSize: limit.MinPartSize,
|
MinPartSize: limit.MinPartSize,
|
||||||
MaxPartSize: limit.MaxPartSize,
|
MaxPartSize: limit.MaxPartSize,
|
||||||
|
|||||||
@@ -17,26 +17,28 @@ package third
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
|
||||||
"time"
|
"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/config"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
"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/common/storage/database/mgo"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
||||||
"github.com/openimsdk/tools/s3/aws"
|
|
||||||
"github.com/openimsdk/tools/s3/kodo"
|
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
|
||||||
"github.com/openimsdk/protocol/third"
|
"github.com/openimsdk/protocol/third"
|
||||||
"github.com/openimsdk/tools/db/mongoutil"
|
"github.com/openimsdk/tools/db/mongoutil"
|
||||||
"github.com/openimsdk/tools/db/redisutil"
|
"github.com/openimsdk/tools/db/redisutil"
|
||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
"github.com/openimsdk/tools/s3"
|
"github.com/openimsdk/tools/s3"
|
||||||
"github.com/openimsdk/tools/s3/cos"
|
"github.com/openimsdk/tools/s3/cos"
|
||||||
|
"github.com/openimsdk/tools/s3/kodo"
|
||||||
"github.com/openimsdk/tools/s3/minio"
|
"github.com/openimsdk/tools/s3/minio"
|
||||||
"github.com/openimsdk/tools/s3/oss"
|
"github.com/openimsdk/tools/s3/oss"
|
||||||
"google.golang.org/grpc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type thirdServer struct {
|
type thirdServer struct {
|
||||||
@@ -94,13 +96,15 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
|||||||
o, err = kodo.NewKodo(*config.RpcConfig.Object.Kodo.Build())
|
o, err = kodo.NewKodo(*config.RpcConfig.Object.Kodo.Build())
|
||||||
case "aws":
|
case "aws":
|
||||||
o, err = aws.NewAws(*config.RpcConfig.Object.Aws.Build())
|
o, err = aws.NewAws(*config.RpcConfig.Object.Aws.Build())
|
||||||
|
case "":
|
||||||
|
o = disable.NewDisable()
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("invalid object enable: %s", enable)
|
err = fmt.Errorf("invalid object enable: %s", enable)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
userConn, err := client.GetConn(ctx, config.Discovery.RpcService.User)
|
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package user
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||||
"github.com/openimsdk/protocol/msg"
|
"github.com/openimsdk/protocol/msg"
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UserNotificationSender struct {
|
type UserNotificationSender struct {
|
||||||
*rpcclient.NotificationSender
|
*notification.NotificationSender
|
||||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||||
// db controller
|
// db controller
|
||||||
db controller.UserDatabase
|
db controller.UserDatabase
|
||||||
@@ -63,7 +64,7 @@ func WithUserFunc(
|
|||||||
|
|
||||||
func NewUserNotificationSender(config *Config, msgClient *rpcli.MsgClient, opts ...userNotificationSenderOptions) *UserNotificationSender {
|
func NewUserNotificationSender(config *Config, msgClient *rpcli.MsgClient, opts ...userNotificationSenderOptions) *UserNotificationSender {
|
||||||
f := &UserNotificationSender{
|
f := &UserNotificationSender{
|
||||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
NotificationSender: notification.NewNotificationSender(&config.NotificationConfig, notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||||
return msgClient.SendMsg(ctx, req)
|
return msgClient.SendMsg(ctx, req)
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,15 +94,15 @@ func Start(ctx context.Context, config *Config, client registry.SvcDiscoveryRegi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
msgConn, err := client.GetConn(ctx, config.Discovery.RpcService.Msg)
|
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
groupConn, err := client.GetConn(ctx, config.Discovery.RpcService.Group)
|
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
friendConn, err := client.GetConn(ctx, config.Discovery.RpcService.Friend)
|
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-27
@@ -1,19 +1,30 @@
|
|||||||
|
// 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 tools
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discovery"
|
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||||
disetcd "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
|
||||||
pbconversation "github.com/openimsdk/protocol/conversation"
|
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||||
"github.com/openimsdk/protocol/msg"
|
"github.com/openimsdk/protocol/msg"
|
||||||
"github.com/openimsdk/protocol/third"
|
"github.com/openimsdk/protocol/third"
|
||||||
"github.com/openimsdk/tools/discovery/etcd"
|
|
||||||
|
|
||||||
"github.com/openimsdk/tools/mcontext"
|
"github.com/openimsdk/tools/mcontext"
|
||||||
"github.com/openimsdk/tools/mw"
|
"github.com/openimsdk/tools/mw"
|
||||||
"github.com/openimsdk/tools/utils/runtimeenv"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
|
||||||
@@ -26,51 +37,38 @@ type CronTaskConfig struct {
|
|||||||
CronTask config.CronTask
|
CronTask config.CronTask
|
||||||
Share config.Share
|
Share config.Share
|
||||||
Discovery config.Discovery
|
Discovery config.Discovery
|
||||||
|
|
||||||
runTimeEnv string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(ctx context.Context, conf *CronTaskConfig) error {
|
func Start(ctx context.Context, config *CronTaskConfig) error {
|
||||||
conf.runTimeEnv = runtimeenv.PrintRuntimeEnvironment()
|
log.CInfo(ctx, "CRON-TASK server is initializing", "chatRecordsClearTime", config.CronTask.CronExecuteTime, "msgDestructTime", config.CronTask.RetainChatRecords)
|
||||||
|
if config.CronTask.RetainChatRecords < 1 {
|
||||||
log.CInfo(ctx, "CRON-TASK server is initializing", "runTimeEnv", conf.runTimeEnv, "chatRecordsClearTime", conf.CronTask.CronExecuteTime, "msgDestructTime", conf.CronTask.RetainChatRecords)
|
|
||||||
if conf.CronTask.RetainChatRecords < 1 {
|
|
||||||
return errs.New("msg destruct time must be greater than 1").Wrap()
|
return errs.New("msg destruct time must be greater than 1").Wrap()
|
||||||
}
|
}
|
||||||
client, err := kdisc.NewDiscoveryRegister(&conf.Discovery, conf.runTimeEnv, nil)
|
client, err := kdisc.NewDiscoveryRegister(&config.Discovery, &config.Share, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errs.WrapMsg(err, "failed to register discovery service")
|
return errs.WrapMsg(err, "failed to register discovery service")
|
||||||
}
|
}
|
||||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
ctx = mcontext.SetOpUserID(ctx, conf.Share.IMAdminUserID[0])
|
ctx = mcontext.SetOpUserID(ctx, config.Share.IMAdminUserID[0])
|
||||||
|
|
||||||
msgConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Msg)
|
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
thirdConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Third)
|
thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
conversationConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Conversation)
|
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.Discovery.Enable == config.ETCD {
|
|
||||||
cm := disetcd.NewConfigManager(client.(*etcd.SvcDiscoveryRegistryImpl).GetClient(), []string{
|
|
||||||
conf.CronTask.GetConfigFileName(),
|
|
||||||
conf.Share.GetConfigFileName(),
|
|
||||||
conf.Discovery.GetConfigFileName(),
|
|
||||||
})
|
|
||||||
cm.Watch(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
srv := &cronServer{
|
srv := &cronServer{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
config: conf,
|
config: config,
|
||||||
cron: cron.New(),
|
cron: cron.New(),
|
||||||
msgClient: msg.NewMsgClient(msgConn),
|
msgClient: msg.NewMsgClient(msgConn),
|
||||||
conversationClient: pbconversation.NewConversationClient(conversationConn),
|
conversationClient: pbconversation.NewConversationClient(conversationConn),
|
||||||
@@ -86,7 +84,7 @@ func Start(ctx context.Context, conf *CronTaskConfig) error {
|
|||||||
if err := srv.registerClearUserMsg(); err != nil {
|
if err := srv.registerClearUserMsg(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.ZDebug(ctx, "start cron task", "CronExecuteTime", conf.CronTask.CronExecuteTime)
|
log.ZDebug(ctx, "start cron task", "CronExecuteTime", config.CronTask.CronExecuteTime)
|
||||||
srv.cron.Start()
|
srv.cron.Start()
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
|
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||||
|
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||||
|
"github.com/openimsdk/protocol/msg"
|
||||||
|
"github.com/openimsdk/protocol/third"
|
||||||
|
"github.com/openimsdk/tools/mcontext"
|
||||||
|
"github.com/openimsdk/tools/mw"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestName(t *testing.T) {
|
||||||
|
conf := &config.Discovery{
|
||||||
|
Enable: config.ETCD,
|
||||||
|
Etcd: config.Etcd{
|
||||||
|
RootDirectory: "openim",
|
||||||
|
Address: []string{"localhost:12379"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
client, err := kdisc.NewDiscoveryRegister(conf, "source")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
|
ctx := mcontext.SetOpUserID(context.Background(), "imAdmin")
|
||||||
|
msgConn, err := client.GetConn(ctx, "msg-rpc-service")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
thirdConn, err := client.GetConn(ctx, "third-rpc-service")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conversationConn, err := client.GetConn(ctx, "conversation-rpc-service")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
srv := &cronServer{
|
||||||
|
ctx: ctx,
|
||||||
|
config: &CronTaskConfig{
|
||||||
|
CronTask: config.CronTask{
|
||||||
|
RetainChatRecords: 1,
|
||||||
|
FileExpireTime: 1,
|
||||||
|
DeleteObjectType: []string{"msg-picture", "msg-file", "msg-voice", "msg-video", "msg-video-snapshot", "sdklog", ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cron: cron.New(),
|
||||||
|
msgClient: msg.NewMsgClient(msgConn),
|
||||||
|
conversationClient: pbconversation.NewConversationClient(conversationConn),
|
||||||
|
thirdClient: third.NewThirdClient(thirdConn),
|
||||||
|
}
|
||||||
|
srv.deleteMsg()
|
||||||
|
//srv.clearS3()
|
||||||
|
//srv.clearUserMsg()
|
||||||
|
}
|
||||||
+11
-2
@@ -4,14 +4,23 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/openimsdk/gomake/mageutil"
|
"flag"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/openimsdk/gomake/mageutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Default = Build
|
var Default = Build
|
||||||
|
|
||||||
func Build() {
|
func Build() {
|
||||||
mageutil.Build()
|
flag.Parse()
|
||||||
|
|
||||||
|
bin := flag.Args()
|
||||||
|
if len(bin) != 0 {
|
||||||
|
bin = bin[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
mageutil.Build(bin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start() {
|
func Start() {
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package apistruct
|
|
||||||
|
|
||||||
type GetConfigReq struct {
|
|
||||||
ConfigName string `json:"configName"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetConfigListResp struct {
|
|
||||||
Environment string `json:"environment"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
ConfigNames []string `json:"configNames"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetConfigReq struct {
|
|
||||||
ConfigName string `json:"configName"`
|
|
||||||
Data string `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetEnableConfigManagerReq struct {
|
|
||||||
Enable bool `json:"enable"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetEnableConfigManagerResp struct {
|
|
||||||
Enable bool `json:"enable"`
|
|
||||||
}
|
|
||||||
+4
-25
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/api"
|
"github.com/openimsdk/open-im-server/v3/internal/api"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -32,36 +31,16 @@ type ApiCmd struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewApiCmd() *ApiCmd {
|
func NewApiCmd() *ApiCmd {
|
||||||
apiConfig := api.Config{AllConfig: &config.AllConfig{}}
|
var apiConfig api.Config
|
||||||
ret := &ApiCmd{apiConfig: &apiConfig}
|
ret := &ApiCmd{apiConfig: &apiConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.DiscoveryConfigFilename: &apiConfig.Discovery,
|
OpenIMAPICfgFileName: &apiConfig.API,
|
||||||
config.KafkaConfigFileName: &apiConfig.Kafka,
|
ShareFileName: &apiConfig.Share,
|
||||||
config.LocalCacheConfigFileName: &apiConfig.LocalCache,
|
DiscoveryConfigFilename: &apiConfig.Discovery,
|
||||||
config.LogConfigFileName: &apiConfig.Log,
|
|
||||||
config.MinioConfigFileName: &apiConfig.Minio,
|
|
||||||
config.MongodbConfigFileName: &apiConfig.Mongo,
|
|
||||||
config.NotificationFileName: &apiConfig.Notification,
|
|
||||||
config.OpenIMAPICfgFileName: &apiConfig.API,
|
|
||||||
config.OpenIMCronTaskCfgFileName: &apiConfig.CronTask,
|
|
||||||
config.OpenIMMsgGatewayCfgFileName: &apiConfig.MsgGateway,
|
|
||||||
config.OpenIMMsgTransferCfgFileName: &apiConfig.MsgTransfer,
|
|
||||||
config.OpenIMPushCfgFileName: &apiConfig.Push,
|
|
||||||
config.OpenIMRPCAuthCfgFileName: &apiConfig.Auth,
|
|
||||||
config.OpenIMRPCConversationCfgFileName: &apiConfig.Conversation,
|
|
||||||
config.OpenIMRPCFriendCfgFileName: &apiConfig.Friend,
|
|
||||||
config.OpenIMRPCGroupCfgFileName: &apiConfig.Group,
|
|
||||||
config.OpenIMRPCMsgCfgFileName: &apiConfig.Msg,
|
|
||||||
config.OpenIMRPCThirdCfgFileName: &apiConfig.Third,
|
|
||||||
config.OpenIMRPCUserCfgFileName: &apiConfig.User,
|
|
||||||
config.RedisConfigFileName: &apiConfig.Redis,
|
|
||||||
config.ShareFileName: &apiConfig.Share,
|
|
||||||
config.WebhooksConfigFileName: &apiConfig.Webhooks,
|
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
|
ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
apiConfig.ConfigPath = ret.configPath
|
|
||||||
return ret.runE()
|
return ret.runE()
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
+6
-13
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/auth"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/auth"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,10 +35,10 @@ func NewAuthRpcCmd() *AuthRpcCmd {
|
|||||||
var authConfig auth.Config
|
var authConfig auth.Config
|
||||||
ret := &AuthRpcCmd{authConfig: &authConfig}
|
ret := &AuthRpcCmd{authConfig: &authConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMRPCAuthCfgFileName: &authConfig.RpcConfig,
|
OpenIMRPCAuthCfgFileName: &authConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &authConfig.RedisConfig,
|
RedisConfigFileName: &authConfig.RedisConfig,
|
||||||
config.ShareFileName: &authConfig.Share,
|
ShareFileName: &authConfig.Share,
|
||||||
config.DiscoveryConfigFilename: &authConfig.Discovery,
|
DiscoveryConfigFilename: &authConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -57,15 +56,9 @@ func (a *AuthRpcCmd) Exec() error {
|
|||||||
func (a *AuthRpcCmd) runE() error {
|
func (a *AuthRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.authConfig.Discovery, &a.authConfig.RpcConfig.Prometheus, a.authConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.authConfig.Discovery, &a.authConfig.RpcConfig.Prometheus, a.authConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.authConfig.RpcConfig.RPC.RegisterIP, a.authConfig.RpcConfig.RPC.AutoSetPorts, a.authConfig.RpcConfig.RPC.Ports,
|
a.authConfig.RpcConfig.RPC.RegisterIP, a.authConfig.RpcConfig.RPC.AutoSetPorts, a.authConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.authConfig.Discovery.RpcService.Auth, nil, a.authConfig,
|
a.Index(), a.authConfig.Share.RpcRegisterName.Auth, &a.authConfig.Share, a.authConfig,
|
||||||
[]string{
|
[]string{
|
||||||
a.authConfig.RpcConfig.GetConfigFileName(),
|
a.authConfig.Share.RpcRegisterName.MessageGateway,
|
||||||
a.authConfig.Share.GetConfigFileName(),
|
|
||||||
a.authConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.authConfig.Discovery.GetConfigFileName(),
|
|
||||||
},
|
|
||||||
[]string{
|
|
||||||
a.authConfig.Discovery.RpcService.MessageGateway,
|
|
||||||
},
|
},
|
||||||
auth.Start)
|
auth.Start)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/conversation"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/conversation"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,13 +35,13 @@ func NewConversationRpcCmd() *ConversationRpcCmd {
|
|||||||
var conversationConfig conversation.Config
|
var conversationConfig conversation.Config
|
||||||
ret := &ConversationRpcCmd{conversationConfig: &conversationConfig}
|
ret := &ConversationRpcCmd{conversationConfig: &conversationConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMRPCConversationCfgFileName: &conversationConfig.RpcConfig,
|
OpenIMRPCConversationCfgFileName: &conversationConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &conversationConfig.RedisConfig,
|
RedisConfigFileName: &conversationConfig.RedisConfig,
|
||||||
config.MongodbConfigFileName: &conversationConfig.MongodbConfig,
|
MongodbConfigFileName: &conversationConfig.MongodbConfig,
|
||||||
config.ShareFileName: &conversationConfig.Share,
|
ShareFileName: &conversationConfig.Share,
|
||||||
config.NotificationFileName: &conversationConfig.NotificationConfig,
|
NotificationFileName: &conversationConfig.NotificationConfig,
|
||||||
config.LocalCacheConfigFileName: &conversationConfig.LocalCacheConfig,
|
LocalCacheConfigFileName: &conversationConfig.LocalCacheConfig,
|
||||||
config.DiscoveryConfigFilename: &conversationConfig.Discovery,
|
DiscoveryConfigFilename: &conversationConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -59,15 +58,7 @@ func (a *ConversationRpcCmd) Exec() error {
|
|||||||
func (a *ConversationRpcCmd) runE() error {
|
func (a *ConversationRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.conversationConfig.Discovery, &a.conversationConfig.RpcConfig.Prometheus, a.conversationConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.conversationConfig.Discovery, &a.conversationConfig.RpcConfig.Prometheus, a.conversationConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.conversationConfig.RpcConfig.RPC.RegisterIP, a.conversationConfig.RpcConfig.RPC.AutoSetPorts, a.conversationConfig.RpcConfig.RPC.Ports,
|
a.conversationConfig.RpcConfig.RPC.RegisterIP, a.conversationConfig.RpcConfig.RPC.AutoSetPorts, a.conversationConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.conversationConfig.Discovery.RpcService.Conversation, &a.conversationConfig.NotificationConfig, a.conversationConfig,
|
a.Index(), a.conversationConfig.Share.RpcRegisterName.Conversation, &a.conversationConfig.Share, a.conversationConfig,
|
||||||
[]string{
|
nil,
|
||||||
a.conversationConfig.RpcConfig.GetConfigFileName(),
|
|
||||||
a.conversationConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.conversationConfig.MongodbConfig.GetConfigFileName(),
|
|
||||||
a.conversationConfig.NotificationConfig.GetConfigFileName(),
|
|
||||||
a.conversationConfig.Share.GetConfigFileName(),
|
|
||||||
a.conversationConfig.LocalCacheConfig.GetConfigFileName(),
|
|
||||||
a.conversationConfig.Discovery.GetConfigFileName(),
|
|
||||||
}, nil,
|
|
||||||
conversation.Start)
|
conversation.Start)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/tools"
|
"github.com/openimsdk/open-im-server/v3/internal/tools"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -35,9 +34,9 @@ func NewCronTaskCmd() *CronTaskCmd {
|
|||||||
var cronTaskConfig tools.CronTaskConfig
|
var cronTaskConfig tools.CronTaskConfig
|
||||||
ret := &CronTaskCmd{cronTaskConfig: &cronTaskConfig}
|
ret := &CronTaskCmd{cronTaskConfig: &cronTaskConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMCronTaskCfgFileName: &cronTaskConfig.CronTask,
|
OpenIMCronTaskCfgFileName: &cronTaskConfig.CronTask,
|
||||||
config.ShareFileName: &cronTaskConfig.Share,
|
ShareFileName: &cronTaskConfig.Share,
|
||||||
config.DiscoveryConfigFilename: &cronTaskConfig.Discovery,
|
DiscoveryConfigFilename: &cronTaskConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
|
|||||||
+10
-20
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/relation"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/relation"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,14 +35,14 @@ func NewFriendRpcCmd() *FriendRpcCmd {
|
|||||||
var relationConfig relation.Config
|
var relationConfig relation.Config
|
||||||
ret := &FriendRpcCmd{relationConfig: &relationConfig}
|
ret := &FriendRpcCmd{relationConfig: &relationConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMRPCFriendCfgFileName: &relationConfig.RpcConfig,
|
OpenIMRPCFriendCfgFileName: &relationConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &relationConfig.RedisConfig,
|
RedisConfigFileName: &relationConfig.RedisConfig,
|
||||||
config.MongodbConfigFileName: &relationConfig.MongodbConfig,
|
MongodbConfigFileName: &relationConfig.MongodbConfig,
|
||||||
config.ShareFileName: &relationConfig.Share,
|
ShareFileName: &relationConfig.Share,
|
||||||
config.NotificationFileName: &relationConfig.NotificationConfig,
|
NotificationFileName: &relationConfig.NotificationConfig,
|
||||||
config.WebhooksConfigFileName: &relationConfig.WebhooksConfig,
|
WebhooksConfigFileName: &relationConfig.WebhooksConfig,
|
||||||
config.LocalCacheConfigFileName: &relationConfig.LocalCacheConfig,
|
LocalCacheConfigFileName: &relationConfig.LocalCacheConfig,
|
||||||
config.DiscoveryConfigFilename: &relationConfig.Discovery,
|
DiscoveryConfigFilename: &relationConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -60,16 +59,7 @@ func (a *FriendRpcCmd) Exec() error {
|
|||||||
func (a *FriendRpcCmd) runE() error {
|
func (a *FriendRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.relationConfig.Discovery, &a.relationConfig.RpcConfig.Prometheus, a.relationConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.relationConfig.Discovery, &a.relationConfig.RpcConfig.Prometheus, a.relationConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.relationConfig.RpcConfig.RPC.RegisterIP, a.relationConfig.RpcConfig.RPC.AutoSetPorts, a.relationConfig.RpcConfig.RPC.Ports,
|
a.relationConfig.RpcConfig.RPC.RegisterIP, a.relationConfig.RpcConfig.RPC.AutoSetPorts, a.relationConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.relationConfig.Discovery.RpcService.Friend, &a.relationConfig.NotificationConfig, a.relationConfig,
|
a.Index(), a.relationConfig.Share.RpcRegisterName.Friend, &a.relationConfig.Share, a.relationConfig,
|
||||||
[]string{
|
nil,
|
||||||
a.relationConfig.RpcConfig.GetConfigFileName(),
|
|
||||||
a.relationConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.relationConfig.MongodbConfig.GetConfigFileName(),
|
|
||||||
a.relationConfig.NotificationConfig.GetConfigFileName(),
|
|
||||||
a.relationConfig.Share.GetConfigFileName(),
|
|
||||||
a.relationConfig.WebhooksConfig.GetConfigFileName(),
|
|
||||||
a.relationConfig.LocalCacheConfig.GetConfigFileName(),
|
|
||||||
a.relationConfig.Discovery.GetConfigFileName(),
|
|
||||||
}, nil,
|
|
||||||
relation.Start)
|
relation.Start)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-20
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/group"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/group"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
@@ -37,14 +36,14 @@ func NewGroupRpcCmd() *GroupRpcCmd {
|
|||||||
var groupConfig group.Config
|
var groupConfig group.Config
|
||||||
ret := &GroupRpcCmd{groupConfig: &groupConfig}
|
ret := &GroupRpcCmd{groupConfig: &groupConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMRPCGroupCfgFileName: &groupConfig.RpcConfig,
|
OpenIMRPCGroupCfgFileName: &groupConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &groupConfig.RedisConfig,
|
RedisConfigFileName: &groupConfig.RedisConfig,
|
||||||
config.MongodbConfigFileName: &groupConfig.MongodbConfig,
|
MongodbConfigFileName: &groupConfig.MongodbConfig,
|
||||||
config.ShareFileName: &groupConfig.Share,
|
ShareFileName: &groupConfig.Share,
|
||||||
config.NotificationFileName: &groupConfig.NotificationConfig,
|
NotificationFileName: &groupConfig.NotificationConfig,
|
||||||
config.WebhooksConfigFileName: &groupConfig.WebhooksConfig,
|
WebhooksConfigFileName: &groupConfig.WebhooksConfig,
|
||||||
config.LocalCacheConfigFileName: &groupConfig.LocalCacheConfig,
|
LocalCacheConfigFileName: &groupConfig.LocalCacheConfig,
|
||||||
config.DiscoveryConfigFilename: &groupConfig.Discovery,
|
DiscoveryConfigFilename: &groupConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -61,16 +60,7 @@ func (a *GroupRpcCmd) Exec() error {
|
|||||||
func (a *GroupRpcCmd) runE() error {
|
func (a *GroupRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.groupConfig.Discovery, &a.groupConfig.RpcConfig.Prometheus, a.groupConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.groupConfig.Discovery, &a.groupConfig.RpcConfig.Prometheus, a.groupConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.groupConfig.RpcConfig.RPC.RegisterIP, a.groupConfig.RpcConfig.RPC.AutoSetPorts, a.groupConfig.RpcConfig.RPC.Ports,
|
a.groupConfig.RpcConfig.RPC.RegisterIP, a.groupConfig.RpcConfig.RPC.AutoSetPorts, a.groupConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.groupConfig.Discovery.RpcService.Group, &a.groupConfig.NotificationConfig, a.groupConfig,
|
a.Index(), a.groupConfig.Share.RpcRegisterName.Group, &a.groupConfig.Share, a.groupConfig,
|
||||||
[]string{
|
nil,
|
||||||
a.groupConfig.RpcConfig.GetConfigFileName(),
|
|
||||||
a.groupConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.groupConfig.MongodbConfig.GetConfigFileName(),
|
|
||||||
a.groupConfig.NotificationConfig.GetConfigFileName(),
|
|
||||||
a.groupConfig.Share.GetConfigFileName(),
|
|
||||||
a.groupConfig.WebhooksConfig.GetConfigFileName(),
|
|
||||||
a.groupConfig.LocalCacheConfig.GetConfigFileName(),
|
|
||||||
a.groupConfig.Discovery.GetConfigFileName(),
|
|
||||||
}, nil,
|
|
||||||
group.Start, versionctx.EnableVersionCtx())
|
group.Start, versionctx.EnableVersionCtx())
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-22
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/msg"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/msg"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,15 +35,15 @@ func NewMsgRpcCmd() *MsgRpcCmd {
|
|||||||
var msgConfig msg.Config
|
var msgConfig msg.Config
|
||||||
ret := &MsgRpcCmd{msgConfig: &msgConfig}
|
ret := &MsgRpcCmd{msgConfig: &msgConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMRPCMsgCfgFileName: &msgConfig.RpcConfig,
|
OpenIMRPCMsgCfgFileName: &msgConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &msgConfig.RedisConfig,
|
RedisConfigFileName: &msgConfig.RedisConfig,
|
||||||
config.MongodbConfigFileName: &msgConfig.MongodbConfig,
|
MongodbConfigFileName: &msgConfig.MongodbConfig,
|
||||||
config.KafkaConfigFileName: &msgConfig.KafkaConfig,
|
KafkaConfigFileName: &msgConfig.KafkaConfig,
|
||||||
config.ShareFileName: &msgConfig.Share,
|
ShareFileName: &msgConfig.Share,
|
||||||
config.NotificationFileName: &msgConfig.NotificationConfig,
|
NotificationFileName: &msgConfig.NotificationConfig,
|
||||||
config.WebhooksConfigFileName: &msgConfig.WebhooksConfig,
|
WebhooksConfigFileName: &msgConfig.WebhooksConfig,
|
||||||
config.LocalCacheConfigFileName: &msgConfig.LocalCacheConfig,
|
LocalCacheConfigFileName: &msgConfig.LocalCacheConfig,
|
||||||
config.DiscoveryConfigFilename: &msgConfig.Discovery,
|
DiscoveryConfigFilename: &msgConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -61,17 +60,7 @@ func (a *MsgRpcCmd) Exec() error {
|
|||||||
func (a *MsgRpcCmd) runE() error {
|
func (a *MsgRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.msgConfig.Discovery, &a.msgConfig.RpcConfig.Prometheus, a.msgConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.msgConfig.Discovery, &a.msgConfig.RpcConfig.Prometheus, a.msgConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.msgConfig.RpcConfig.RPC.RegisterIP, a.msgConfig.RpcConfig.RPC.AutoSetPorts, a.msgConfig.RpcConfig.RPC.Ports,
|
a.msgConfig.RpcConfig.RPC.RegisterIP, a.msgConfig.RpcConfig.RPC.AutoSetPorts, a.msgConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.msgConfig.Discovery.RpcService.Msg, &a.msgConfig.NotificationConfig, a.msgConfig,
|
a.Index(), a.msgConfig.Share.RpcRegisterName.Msg, &a.msgConfig.Share, a.msgConfig,
|
||||||
[]string{
|
nil,
|
||||||
a.msgConfig.RpcConfig.GetConfigFileName(),
|
|
||||||
a.msgConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.msgConfig.MongodbConfig.GetConfigFileName(),
|
|
||||||
a.msgConfig.KafkaConfig.GetConfigFileName(),
|
|
||||||
a.msgConfig.NotificationConfig.GetConfigFileName(),
|
|
||||||
a.msgConfig.Share.GetConfigFileName(),
|
|
||||||
a.msgConfig.WebhooksConfig.GetConfigFileName(),
|
|
||||||
a.msgConfig.LocalCacheConfig.GetConfigFileName(),
|
|
||||||
a.msgConfig.Discovery.GetConfigFileName(),
|
|
||||||
}, nil,
|
|
||||||
msg.Start)
|
msg.Start)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/msggateway"
|
"github.com/openimsdk/open-im-server/v3/internal/msggateway"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
|
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,11 +35,11 @@ func NewMsgGatewayCmd() *MsgGatewayCmd {
|
|||||||
var msgGatewayConfig msggateway.Config
|
var msgGatewayConfig msggateway.Config
|
||||||
ret := &MsgGatewayCmd{msgGatewayConfig: &msgGatewayConfig}
|
ret := &MsgGatewayCmd{msgGatewayConfig: &msgGatewayConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMMsgGatewayCfgFileName: &msgGatewayConfig.MsgGateway,
|
OpenIMMsgGatewayCfgFileName: &msgGatewayConfig.MsgGateway,
|
||||||
config.ShareFileName: &msgGatewayConfig.Share,
|
ShareFileName: &msgGatewayConfig.Share,
|
||||||
config.RedisConfigFileName: &msgGatewayConfig.RedisConfig,
|
RedisConfigFileName: &msgGatewayConfig.RedisConfig,
|
||||||
config.WebhooksConfigFileName: &msgGatewayConfig.WebhooksConfig,
|
WebhooksConfigFileName: &msgGatewayConfig.WebhooksConfig,
|
||||||
config.DiscoveryConfigFilename: &msgGatewayConfig.Discovery,
|
DiscoveryConfigFilename: &msgGatewayConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/msgtransfer"
|
"github.com/openimsdk/open-im-server/v3/internal/msgtransfer"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -35,13 +34,13 @@ func NewMsgTransferCmd() *MsgTransferCmd {
|
|||||||
var msgTransferConfig msgtransfer.Config
|
var msgTransferConfig msgtransfer.Config
|
||||||
ret := &MsgTransferCmd{msgTransferConfig: &msgTransferConfig}
|
ret := &MsgTransferCmd{msgTransferConfig: &msgTransferConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMMsgTransferCfgFileName: &msgTransferConfig.MsgTransfer,
|
OpenIMMsgTransferCfgFileName: &msgTransferConfig.MsgTransfer,
|
||||||
config.RedisConfigFileName: &msgTransferConfig.RedisConfig,
|
RedisConfigFileName: &msgTransferConfig.RedisConfig,
|
||||||
config.MongodbConfigFileName: &msgTransferConfig.MongodbConfig,
|
MongodbConfigFileName: &msgTransferConfig.MongodbConfig,
|
||||||
config.KafkaConfigFileName: &msgTransferConfig.KafkaConfig,
|
KafkaConfigFileName: &msgTransferConfig.KafkaConfig,
|
||||||
config.ShareFileName: &msgTransferConfig.Share,
|
ShareFileName: &msgTransferConfig.Share,
|
||||||
config.WebhooksConfigFileName: &msgTransferConfig.WebhooksConfig,
|
WebhooksConfigFileName: &msgTransferConfig.WebhooksConfig,
|
||||||
config.DiscoveryConfigFilename: &msgTransferConfig.Discovery,
|
DiscoveryConfigFilename: &msgTransferConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,11 +26,11 @@ func (m *MsgUtilsCmd) AddUserIDFlag() {
|
|||||||
m.Command.PersistentFlags().StringP("userID", "u", "", "openIM userID")
|
m.Command.PersistentFlags().StringP("userID", "u", "", "openIM userID")
|
||||||
}
|
}
|
||||||
func (m *MsgUtilsCmd) AddIndexFlag() {
|
func (m *MsgUtilsCmd) AddIndexFlag() {
|
||||||
m.Command.PersistentFlags().IntP(config.FlagTransferIndex, "i", 0, "process startup sequence number")
|
m.Command.PersistentFlags().IntP(FlagTransferIndex, "i", 0, "process startup sequence number")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MsgUtilsCmd) AddConfigDirFlag() {
|
func (m *MsgUtilsCmd) AddConfigDirFlag() {
|
||||||
m.Command.PersistentFlags().StringP(config.FlagConf, "c", "", "path of config directory")
|
m.Command.PersistentFlags().StringP(FlagConf, "c", "", "path of config directory")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-21
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/push"
|
"github.com/openimsdk/open-im-server/v3/internal/push"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,14 +35,14 @@ func NewPushRpcCmd() *PushRpcCmd {
|
|||||||
var pushConfig push.Config
|
var pushConfig push.Config
|
||||||
ret := &PushRpcCmd{pushConfig: &pushConfig}
|
ret := &PushRpcCmd{pushConfig: &pushConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMPushCfgFileName: &pushConfig.RpcConfig,
|
OpenIMPushCfgFileName: &pushConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &pushConfig.RedisConfig,
|
RedisConfigFileName: &pushConfig.RedisConfig,
|
||||||
config.KafkaConfigFileName: &pushConfig.KafkaConfig,
|
KafkaConfigFileName: &pushConfig.KafkaConfig,
|
||||||
config.ShareFileName: &pushConfig.Share,
|
ShareFileName: &pushConfig.Share,
|
||||||
config.NotificationFileName: &pushConfig.NotificationConfig,
|
NotificationFileName: &pushConfig.NotificationConfig,
|
||||||
config.WebhooksConfigFileName: &pushConfig.WebhooksConfig,
|
WebhooksConfigFileName: &pushConfig.WebhooksConfig,
|
||||||
config.LocalCacheConfigFileName: &pushConfig.LocalCacheConfig,
|
LocalCacheConfigFileName: &pushConfig.LocalCacheConfig,
|
||||||
config.DiscoveryConfigFilename: &pushConfig.Discovery,
|
DiscoveryConfigFilename: &pushConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -61,19 +60,9 @@ func (a *PushRpcCmd) Exec() error {
|
|||||||
func (a *PushRpcCmd) runE() error {
|
func (a *PushRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.pushConfig.Discovery, &a.pushConfig.RpcConfig.Prometheus, a.pushConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.pushConfig.Discovery, &a.pushConfig.RpcConfig.Prometheus, a.pushConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.pushConfig.RpcConfig.RPC.RegisterIP, a.pushConfig.RpcConfig.RPC.AutoSetPorts, a.pushConfig.RpcConfig.RPC.Ports,
|
a.pushConfig.RpcConfig.RPC.RegisterIP, a.pushConfig.RpcConfig.RPC.AutoSetPorts, a.pushConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.pushConfig.Discovery.RpcService.Push, &a.pushConfig.NotificationConfig, a.pushConfig,
|
a.Index(), a.pushConfig.Share.RpcRegisterName.Push, &a.pushConfig.Share, a.pushConfig,
|
||||||
[]string{
|
[]string{
|
||||||
a.pushConfig.RpcConfig.GetConfigFileName(),
|
a.pushConfig.Share.RpcRegisterName.MessageGateway,
|
||||||
a.pushConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.pushConfig.KafkaConfig.GetConfigFileName(),
|
|
||||||
a.pushConfig.NotificationConfig.GetConfigFileName(),
|
|
||||||
a.pushConfig.Share.GetConfigFileName(),
|
|
||||||
a.pushConfig.WebhooksConfig.GetConfigFileName(),
|
|
||||||
a.pushConfig.LocalCacheConfig.GetConfigFileName(),
|
|
||||||
a.pushConfig.Discovery.GetConfigFileName(),
|
|
||||||
},
|
|
||||||
[]string{
|
|
||||||
a.pushConfig.Discovery.RpcService.MessageGateway,
|
|
||||||
},
|
},
|
||||||
push.Start)
|
push.Start)
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-103
@@ -1,20 +1,28 @@
|
|||||||
|
// 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 cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discovery"
|
|
||||||
disetcd "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/discovery/etcd"
|
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/utils/runtimeenv"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
clientv3 "go.etcd.io/etcd/client/v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RootCmd struct {
|
type RootCmd struct {
|
||||||
@@ -25,7 +33,6 @@ type RootCmd struct {
|
|||||||
log config.Log
|
log config.Log
|
||||||
index int
|
index int
|
||||||
configPath string
|
configPath string
|
||||||
etcdClient *clientv3.Client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RootCmd) ConfigPath() string {
|
func (r *RootCmd) ConfigPath() string {
|
||||||
@@ -73,49 +80,23 @@ func NewRootCmd(processName string, opts ...func(*CmdOpts)) *RootCmd {
|
|||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
SilenceErrors: false,
|
SilenceErrors: false,
|
||||||
}
|
}
|
||||||
cmd.Flags().StringP(config.FlagConf, "c", "", "path of config directory")
|
cmd.Flags().StringP(FlagConf, "c", "", "path of config directory")
|
||||||
cmd.Flags().IntP(config.FlagTransferIndex, "i", 0, "process startup sequence number")
|
cmd.Flags().IntP(FlagTransferIndex, "i", 0, "process startup sequence number")
|
||||||
|
|
||||||
rootCmd.Command = cmd
|
rootCmd.Command = cmd
|
||||||
return rootCmd
|
return rootCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RootCmd) initEtcd() error {
|
|
||||||
configDirectory, _, err := r.getFlag(&r.Command)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
disConfig := config.Discovery{}
|
|
||||||
env := runtimeenv.PrintRuntimeEnvironment()
|
|
||||||
err = config.Load(configDirectory, config.DiscoveryConfigFilename, config.EnvPrefixMap[config.DiscoveryConfigFilename],
|
|
||||||
env, &disConfig)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if disConfig.Enable == config.ETCD {
|
|
||||||
discov, _ := kdisc.NewDiscoveryRegister(&disConfig, env, nil)
|
|
||||||
r.etcdClient = discov.(*etcd.SvcDiscoveryRegistryImpl).GetClient()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RootCmd) persistentPreRun(cmd *cobra.Command, opts ...func(*CmdOpts)) error {
|
func (r *RootCmd) persistentPreRun(cmd *cobra.Command, opts ...func(*CmdOpts)) error {
|
||||||
if err := r.initEtcd(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cmdOpts := r.applyOptions(opts...)
|
cmdOpts := r.applyOptions(opts...)
|
||||||
if err := r.initializeConfiguration(cmd, cmdOpts); err != nil {
|
if err := r.initializeConfiguration(cmd, cmdOpts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.updateConfigFromEtcd(cmdOpts); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := r.initializeLogger(cmdOpts); err != nil {
|
if err := r.initializeLogger(cmdOpts); err != nil {
|
||||||
return errs.WrapMsg(err, "failed to initialize logger")
|
return errs.WrapMsg(err, "failed to initialize logger")
|
||||||
}
|
}
|
||||||
if err := r.etcdClient.Close(); err != nil {
|
|
||||||
return errs.WrapMsg(err, "failed to close etcd client")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,77 +105,18 @@ func (r *RootCmd) initializeConfiguration(cmd *cobra.Command, opts *CmdOpts) err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeEnv := runtimeenv.PrintRuntimeEnvironment()
|
|
||||||
|
|
||||||
// Load common configuration file
|
// Load common configuration file
|
||||||
//opts.configMap[ShareFileName] = StructEnvPrefix{EnvPrefix: shareEnvPrefix, ConfigStruct: &r.share}
|
//opts.configMap[ShareFileName] = StructEnvPrefix{EnvPrefix: shareEnvPrefix, ConfigStruct: &r.share}
|
||||||
for configFileName, configStruct := range opts.configMap {
|
for configFileName, configStruct := range opts.configMap {
|
||||||
err := config.Load(configDirectory, configFileName, config.EnvPrefixMap[configFileName], runtimeEnv, configStruct)
|
err := config.LoadConfig(filepath.Join(configDirectory, configFileName),
|
||||||
|
ConfigEnvPrefixMap[configFileName], configStruct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Load common log configuration file
|
// Load common log configuration file
|
||||||
return config.Load(configDirectory, config.LogConfigFileName, config.EnvPrefixMap[config.LogConfigFileName], runtimeEnv, &r.log)
|
return config.LoadConfig(filepath.Join(configDirectory, LogConfigFileName),
|
||||||
}
|
ConfigEnvPrefixMap[LogConfigFileName], &r.log)
|
||||||
|
|
||||||
func (r *RootCmd) updateConfigFromEtcd(opts *CmdOpts) error {
|
|
||||||
if r.etcdClient == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
res, err := r.etcdClient.Get(ctx, disetcd.BuildKey(disetcd.EnableConfigCenterKey))
|
|
||||||
if err != nil {
|
|
||||||
log.ZWarn(ctx, "root cmd updateConfigFromEtcd, etcd Get EnableConfigCenterKey err: %v", errs.Wrap(err))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if res.Count == 0 {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
if string(res.Kvs[0].Value) == disetcd.Disable {
|
|
||||||
return nil
|
|
||||||
} else if string(res.Kvs[0].Value) != disetcd.Enable {
|
|
||||||
return errs.New("unknown EnableConfigCenter value").Wrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update := func(configFileName string, configStruct any) error {
|
|
||||||
key := disetcd.BuildKey(configFileName)
|
|
||||||
etcdRes, err := r.etcdClient.Get(ctx, key)
|
|
||||||
if err != nil {
|
|
||||||
log.ZWarn(ctx, "root cmd updateConfigFromEtcd, etcd Get err: %v", errs.Wrap(err))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if etcdRes.Count == 0 {
|
|
||||||
data, err := json.Marshal(configStruct)
|
|
||||||
if err != nil {
|
|
||||||
return errs.ErrArgs.WithDetail(err.Error()).Wrap()
|
|
||||||
}
|
|
||||||
_, err = r.etcdClient.Put(ctx, disetcd.BuildKey(configFileName), string(data))
|
|
||||||
if err != nil {
|
|
||||||
log.ZWarn(ctx, "root cmd updateConfigFromEtcd, etcd Put err: %v", errs.Wrap(err))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(etcdRes.Kvs[0].Value, configStruct)
|
|
||||||
if err != nil {
|
|
||||||
return errs.WrapMsg(err, "failed to unmarshal config from etcd")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for configFileName, configStruct := range opts.configMap {
|
|
||||||
if err := update(configFileName, configStruct); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := update(config.LogConfigFileName, &r.log); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Load common log configuration file
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RootCmd) applyOptions(opts ...func(*CmdOpts)) *CmdOpts {
|
func (r *RootCmd) applyOptions(opts ...func(*CmdOpts)) *CmdOpts {
|
||||||
@@ -235,12 +157,12 @@ func defaultCmdOpts() *CmdOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *RootCmd) getFlag(cmd *cobra.Command) (string, int, error) {
|
func (r *RootCmd) getFlag(cmd *cobra.Command) (string, int, error) {
|
||||||
configDirectory, err := cmd.Flags().GetString(config.FlagConf)
|
configDirectory, err := cmd.Flags().GetString(FlagConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, errs.Wrap(err)
|
return "", 0, errs.Wrap(err)
|
||||||
}
|
}
|
||||||
r.configPath = configDirectory
|
r.configPath = configDirectory
|
||||||
index, err := cmd.Flags().GetInt(config.FlagTransferIndex)
|
index, err := cmd.Flags().GetInt(FlagTransferIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, errs.Wrap(err)
|
return "", 0, errs.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-20
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/third"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/third"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,14 +35,14 @@ func NewThirdRpcCmd() *ThirdRpcCmd {
|
|||||||
var thirdConfig third.Config
|
var thirdConfig third.Config
|
||||||
ret := &ThirdRpcCmd{thirdConfig: &thirdConfig}
|
ret := &ThirdRpcCmd{thirdConfig: &thirdConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMRPCThirdCfgFileName: &thirdConfig.RpcConfig,
|
OpenIMRPCThirdCfgFileName: &thirdConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &thirdConfig.RedisConfig,
|
RedisConfigFileName: &thirdConfig.RedisConfig,
|
||||||
config.MongodbConfigFileName: &thirdConfig.MongodbConfig,
|
MongodbConfigFileName: &thirdConfig.MongodbConfig,
|
||||||
config.ShareFileName: &thirdConfig.Share,
|
ShareFileName: &thirdConfig.Share,
|
||||||
config.NotificationFileName: &thirdConfig.NotificationConfig,
|
NotificationFileName: &thirdConfig.NotificationConfig,
|
||||||
config.MinioConfigFileName: &thirdConfig.MinioConfig,
|
MinioConfigFileName: &thirdConfig.MinioConfig,
|
||||||
config.LocalCacheConfigFileName: &thirdConfig.LocalCacheConfig,
|
LocalCacheConfigFileName: &thirdConfig.LocalCacheConfig,
|
||||||
config.DiscoveryConfigFilename: &thirdConfig.Discovery,
|
DiscoveryConfigFilename: &thirdConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -60,16 +59,7 @@ func (a *ThirdRpcCmd) Exec() error {
|
|||||||
func (a *ThirdRpcCmd) runE() error {
|
func (a *ThirdRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.thirdConfig.Discovery, &a.thirdConfig.RpcConfig.Prometheus, a.thirdConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.thirdConfig.Discovery, &a.thirdConfig.RpcConfig.Prometheus, a.thirdConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.thirdConfig.RpcConfig.RPC.RegisterIP, a.thirdConfig.RpcConfig.RPC.AutoSetPorts, a.thirdConfig.RpcConfig.RPC.Ports,
|
a.thirdConfig.RpcConfig.RPC.RegisterIP, a.thirdConfig.RpcConfig.RPC.AutoSetPorts, a.thirdConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.thirdConfig.Discovery.RpcService.Third, &a.thirdConfig.NotificationConfig, a.thirdConfig,
|
a.Index(), a.thirdConfig.Share.RpcRegisterName.Third, &a.thirdConfig.Share, a.thirdConfig,
|
||||||
[]string{
|
nil,
|
||||||
a.thirdConfig.RpcConfig.GetConfigFileName(),
|
|
||||||
a.thirdConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.thirdConfig.MongodbConfig.GetConfigFileName(),
|
|
||||||
a.thirdConfig.NotificationConfig.GetConfigFileName(),
|
|
||||||
a.thirdConfig.Share.GetConfigFileName(),
|
|
||||||
a.thirdConfig.MinioConfig.GetConfigFileName(),
|
|
||||||
a.thirdConfig.LocalCacheConfig.GetConfigFileName(),
|
|
||||||
a.thirdConfig.Discovery.GetConfigFileName(),
|
|
||||||
}, nil,
|
|
||||||
third.Start)
|
third.Start)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-22
@@ -18,7 +18,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/internal/rpc/user"
|
"github.com/openimsdk/open-im-server/v3/internal/rpc/user"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||||
"github.com/openimsdk/open-im-server/v3/version"
|
"github.com/openimsdk/open-im-server/v3/version"
|
||||||
"github.com/openimsdk/tools/system/program"
|
"github.com/openimsdk/tools/system/program"
|
||||||
@@ -36,15 +35,15 @@ func NewUserRpcCmd() *UserRpcCmd {
|
|||||||
var userConfig user.Config
|
var userConfig user.Config
|
||||||
ret := &UserRpcCmd{userConfig: &userConfig}
|
ret := &UserRpcCmd{userConfig: &userConfig}
|
||||||
ret.configMap = map[string]any{
|
ret.configMap = map[string]any{
|
||||||
config.OpenIMRPCUserCfgFileName: &userConfig.RpcConfig,
|
OpenIMRPCUserCfgFileName: &userConfig.RpcConfig,
|
||||||
config.RedisConfigFileName: &userConfig.RedisConfig,
|
RedisConfigFileName: &userConfig.RedisConfig,
|
||||||
config.MongodbConfigFileName: &userConfig.MongodbConfig,
|
MongodbConfigFileName: &userConfig.MongodbConfig,
|
||||||
config.KafkaConfigFileName: &userConfig.KafkaConfig,
|
KafkaConfigFileName: &userConfig.KafkaConfig,
|
||||||
config.ShareFileName: &userConfig.Share,
|
ShareFileName: &userConfig.Share,
|
||||||
config.NotificationFileName: &userConfig.NotificationConfig,
|
NotificationFileName: &userConfig.NotificationConfig,
|
||||||
config.WebhooksConfigFileName: &userConfig.WebhooksConfig,
|
WebhooksConfigFileName: &userConfig.WebhooksConfig,
|
||||||
config.LocalCacheConfigFileName: &userConfig.LocalCacheConfig,
|
LocalCacheConfigFileName: &userConfig.LocalCacheConfig,
|
||||||
config.DiscoveryConfigFilename: &userConfig.Discovery,
|
DiscoveryConfigFilename: &userConfig.Discovery,
|
||||||
}
|
}
|
||||||
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
|
||||||
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
ret.ctx = context.WithValue(context.Background(), "version", version.Version)
|
||||||
@@ -61,17 +60,7 @@ func (a *UserRpcCmd) Exec() error {
|
|||||||
func (a *UserRpcCmd) runE() error {
|
func (a *UserRpcCmd) runE() error {
|
||||||
return startrpc.Start(a.ctx, &a.userConfig.Discovery, &a.userConfig.RpcConfig.Prometheus, a.userConfig.RpcConfig.RPC.ListenIP,
|
return startrpc.Start(a.ctx, &a.userConfig.Discovery, &a.userConfig.RpcConfig.Prometheus, a.userConfig.RpcConfig.RPC.ListenIP,
|
||||||
a.userConfig.RpcConfig.RPC.RegisterIP, a.userConfig.RpcConfig.RPC.AutoSetPorts, a.userConfig.RpcConfig.RPC.Ports,
|
a.userConfig.RpcConfig.RPC.RegisterIP, a.userConfig.RpcConfig.RPC.AutoSetPorts, a.userConfig.RpcConfig.RPC.Ports,
|
||||||
a.Index(), a.userConfig.Discovery.RpcService.User, &a.userConfig.NotificationConfig, a.userConfig,
|
a.Index(), a.userConfig.Share.RpcRegisterName.User, &a.userConfig.Share, a.userConfig,
|
||||||
[]string{
|
nil,
|
||||||
a.userConfig.RpcConfig.GetConfigFileName(),
|
|
||||||
a.userConfig.RedisConfig.GetConfigFileName(),
|
|
||||||
a.userConfig.MongodbConfig.GetConfigFileName(),
|
|
||||||
a.userConfig.KafkaConfig.GetConfigFileName(),
|
|
||||||
a.userConfig.NotificationConfig.GetConfigFileName(),
|
|
||||||
a.userConfig.Share.GetConfigFileName(),
|
|
||||||
a.userConfig.WebhooksConfig.GetConfigFileName(),
|
|
||||||
a.userConfig.LocalCacheConfig.GetConfigFileName(),
|
|
||||||
a.userConfig.Discovery.GetConfigFileName(),
|
|
||||||
}, nil,
|
|
||||||
user.Start)
|
user.Start)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-212
@@ -18,9 +18,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||||
"github.com/openimsdk/tools/db/mongoutil"
|
"github.com/openimsdk/tools/db/mongoutil"
|
||||||
"github.com/openimsdk/tools/db/redisutil"
|
"github.com/openimsdk/tools/db/redisutil"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
"github.com/openimsdk/tools/s3/aws"
|
"github.com/openimsdk/tools/s3/aws"
|
||||||
"github.com/openimsdk/tools/s3/cos"
|
"github.com/openimsdk/tools/s3/cos"
|
||||||
"github.com/openimsdk/tools/s3/kodo"
|
"github.com/openimsdk/tools/s3/kodo"
|
||||||
@@ -358,7 +358,7 @@ type Redis struct {
|
|||||||
Username string `mapstructure:"username"`
|
Username string `mapstructure:"username"`
|
||||||
Password string `mapstructure:"password"`
|
Password string `mapstructure:"password"`
|
||||||
ClusterMode bool `mapstructure:"clusterMode"`
|
ClusterMode bool `mapstructure:"clusterMode"`
|
||||||
DB int `mapstructure:"storage"`
|
DB int `mapstructure:"db"`
|
||||||
MaxRetry int `mapstructure:"maxRetry"`
|
MaxRetry int `mapstructure:"maxRetry"`
|
||||||
PoolSize int `mapstructure:"poolSize"`
|
PoolSize int `mapstructure:"poolSize"`
|
||||||
}
|
}
|
||||||
@@ -380,9 +380,16 @@ type AfterConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Share struct {
|
type Share struct {
|
||||||
Secret string `mapstructure:"secret"`
|
Secret string `mapstructure:"secret"`
|
||||||
IMAdminUserID []string `mapstructure:"imAdminUserID"`
|
RpcRegisterName RpcRegisterName `mapstructure:"rpcRegisterName"`
|
||||||
MultiLogin MultiLogin `mapstructure:"multiLogin"`
|
IMAdminUserID []string `mapstructure:"imAdminUserID"`
|
||||||
|
MultiLogin MultiLogin `mapstructure:"multiLogin"`
|
||||||
|
RPCMaxBodySize MaxRequestBody `mapstructure:"rpcMaxBodySize"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MaxRequestBody struct {
|
||||||
|
RequestMaxBodySize int `mapstructure:"requestMaxBodySize"`
|
||||||
|
ResponseMaxBodySize int `mapstructure:"responseMaxBodySize"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiLogin struct {
|
type MultiLogin struct {
|
||||||
@@ -477,41 +484,11 @@ type ZooKeeper struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Discovery struct {
|
type Discovery struct {
|
||||||
Enable string `mapstructure:"enable"`
|
Enable string `mapstructure:"enable"`
|
||||||
Etcd Etcd `mapstructure:"etcd"`
|
Etcd Etcd `mapstructure:"etcd"`
|
||||||
Kubernetes Kubernetes `mapstructure:"kubernetes"`
|
ZooKeeper ZooKeeper `mapstructure:"zooKeeper"`
|
||||||
RpcService RpcService `mapstructure:"rpcService"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type RpcService struct {
|
|
||||||
User string `mapstructure:"user"`
|
|
||||||
Friend string `mapstructure:"friend"`
|
|
||||||
Msg string `mapstructure:"msg"`
|
|
||||||
Push string `mapstructure:"push"`
|
|
||||||
MessageGateway string `mapstructure:"messageGateway"`
|
|
||||||
Group string `mapstructure:"group"`
|
|
||||||
Auth string `mapstructure:"auth"`
|
|
||||||
Conversation string `mapstructure:"conversation"`
|
|
||||||
Third string `mapstructure:"third"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RpcService) GetServiceNames() []string {
|
|
||||||
return []string{
|
|
||||||
r.User,
|
|
||||||
r.Friend,
|
|
||||||
r.Msg,
|
|
||||||
r.Push,
|
|
||||||
r.MessageGateway,
|
|
||||||
r.Group,
|
|
||||||
r.Auth,
|
|
||||||
r.Conversation,
|
|
||||||
r.Third,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Kubernetes struct {
|
|
||||||
Namespace string `yaml:"namespace"`
|
|
||||||
}
|
|
||||||
type Etcd struct {
|
type Etcd struct {
|
||||||
RootDirectory string `mapstructure:"rootDirectory"`
|
RootDirectory string `mapstructure:"rootDirectory"`
|
||||||
Address []string `mapstructure:"address"`
|
Address []string `mapstructure:"address"`
|
||||||
@@ -635,7 +612,7 @@ func (l *CacheConfig) Enable() bool {
|
|||||||
return l.Topic != "" && l.SlotNum > 0 && l.SlotSize > 0
|
return l.Topic != "" && l.SlotNum > 0 && l.SlotSize > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
var (
|
||||||
DiscoveryConfigFilename = "discovery.yml"
|
DiscoveryConfigFilename = "discovery.yml"
|
||||||
KafkaConfigFileName = "kafka.yml"
|
KafkaConfigFileName = "kafka.yml"
|
||||||
LocalCacheConfigFileName = "local-cache.yml"
|
LocalCacheConfigFileName = "local-cache.yml"
|
||||||
@@ -657,7 +634,6 @@ const (
|
|||||||
RedisConfigFileName = "redis.yml"
|
RedisConfigFileName = "redis.yml"
|
||||||
ShareFileName = "share.yml"
|
ShareFileName = "share.yml"
|
||||||
WebhooksConfigFileName = "webhooks.yml"
|
WebhooksConfigFileName = "webhooks.yml"
|
||||||
NotificationFileName = "notification.yml"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Discovery) GetConfigFileName() string {
|
func (d *Discovery) GetConfigFileName() string {
|
||||||
@@ -747,175 +723,3 @@ func (s *Share) GetConfigFileName() string {
|
|||||||
func (w *Webhooks) GetConfigFileName() string {
|
func (w *Webhooks) GetConfigFileName() string {
|
||||||
return WebhooksConfigFileName
|
return WebhooksConfigFileName
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitNotification(notification *Notification) {
|
|
||||||
notification.GroupCreated.UnreadCount = false
|
|
||||||
notification.GroupCreated.ReliabilityLevel = 1
|
|
||||||
notification.GroupInfoSet.UnreadCount = false
|
|
||||||
notification.GroupInfoSet.ReliabilityLevel = 1
|
|
||||||
notification.JoinGroupApplication.UnreadCount = false
|
|
||||||
notification.JoinGroupApplication.ReliabilityLevel = 1
|
|
||||||
notification.MemberQuit.UnreadCount = false
|
|
||||||
notification.MemberQuit.ReliabilityLevel = 1
|
|
||||||
notification.GroupApplicationAccepted.UnreadCount = false
|
|
||||||
notification.GroupApplicationAccepted.ReliabilityLevel = 1
|
|
||||||
notification.GroupApplicationRejected.UnreadCount = false
|
|
||||||
notification.GroupApplicationRejected.ReliabilityLevel = 1
|
|
||||||
notification.GroupOwnerTransferred.UnreadCount = false
|
|
||||||
notification.GroupOwnerTransferred.ReliabilityLevel = 1
|
|
||||||
notification.MemberKicked.UnreadCount = false
|
|
||||||
notification.MemberKicked.ReliabilityLevel = 1
|
|
||||||
notification.MemberInvited.UnreadCount = false
|
|
||||||
notification.MemberInvited.ReliabilityLevel = 1
|
|
||||||
notification.MemberEnter.UnreadCount = false
|
|
||||||
notification.MemberEnter.ReliabilityLevel = 1
|
|
||||||
notification.GroupDismissed.UnreadCount = false
|
|
||||||
notification.GroupDismissed.ReliabilityLevel = 1
|
|
||||||
notification.GroupMuted.UnreadCount = false
|
|
||||||
notification.GroupMuted.ReliabilityLevel = 1
|
|
||||||
notification.GroupCancelMuted.UnreadCount = false
|
|
||||||
notification.GroupCancelMuted.ReliabilityLevel = 1
|
|
||||||
notification.GroupMemberMuted.UnreadCount = false
|
|
||||||
notification.GroupMemberMuted.ReliabilityLevel = 1
|
|
||||||
notification.GroupMemberCancelMuted.UnreadCount = false
|
|
||||||
notification.GroupMemberCancelMuted.ReliabilityLevel = 1
|
|
||||||
notification.GroupMemberInfoSet.UnreadCount = false
|
|
||||||
notification.GroupMemberInfoSet.ReliabilityLevel = 1
|
|
||||||
notification.GroupMemberSetToAdmin.UnreadCount = false
|
|
||||||
notification.GroupMemberSetToAdmin.ReliabilityLevel = 1
|
|
||||||
notification.GroupMemberSetToOrdinary.UnreadCount = false
|
|
||||||
notification.GroupMemberSetToOrdinary.ReliabilityLevel = 1
|
|
||||||
notification.GroupInfoSetAnnouncement.UnreadCount = false
|
|
||||||
notification.GroupInfoSetAnnouncement.ReliabilityLevel = 1
|
|
||||||
notification.GroupInfoSetName.UnreadCount = false
|
|
||||||
notification.GroupInfoSetName.ReliabilityLevel = 1
|
|
||||||
notification.FriendApplicationAdded.UnreadCount = false
|
|
||||||
notification.FriendApplicationAdded.ReliabilityLevel = 1
|
|
||||||
notification.FriendApplicationApproved.UnreadCount = false
|
|
||||||
notification.FriendApplicationApproved.ReliabilityLevel = 1
|
|
||||||
notification.FriendApplicationRejected.UnreadCount = false
|
|
||||||
notification.FriendApplicationRejected.ReliabilityLevel = 1
|
|
||||||
notification.FriendAdded.UnreadCount = false
|
|
||||||
notification.FriendAdded.ReliabilityLevel = 1
|
|
||||||
notification.FriendDeleted.UnreadCount = false
|
|
||||||
notification.FriendDeleted.ReliabilityLevel = 1
|
|
||||||
notification.FriendRemarkSet.UnreadCount = false
|
|
||||||
notification.FriendRemarkSet.ReliabilityLevel = 1
|
|
||||||
notification.BlackAdded.UnreadCount = false
|
|
||||||
notification.BlackAdded.ReliabilityLevel = 1
|
|
||||||
notification.BlackDeleted.UnreadCount = false
|
|
||||||
notification.BlackDeleted.ReliabilityLevel = 1
|
|
||||||
notification.FriendInfoUpdated.UnreadCount = false
|
|
||||||
notification.FriendInfoUpdated.ReliabilityLevel = 1
|
|
||||||
notification.UserInfoUpdated.UnreadCount = false
|
|
||||||
notification.UserInfoUpdated.ReliabilityLevel = 1
|
|
||||||
notification.UserStatusChanged.UnreadCount = false
|
|
||||||
notification.UserStatusChanged.ReliabilityLevel = 1
|
|
||||||
notification.ConversationChanged.UnreadCount = false
|
|
||||||
notification.ConversationChanged.ReliabilityLevel = 1
|
|
||||||
notification.ConversationSetPrivate.UnreadCount = false
|
|
||||||
notification.ConversationSetPrivate.ReliabilityLevel = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
type AllConfig struct {
|
|
||||||
Discovery Discovery
|
|
||||||
Kafka Kafka
|
|
||||||
LocalCache LocalCache
|
|
||||||
Log Log
|
|
||||||
Minio Minio
|
|
||||||
Mongo Mongo
|
|
||||||
Notification Notification
|
|
||||||
API API
|
|
||||||
CronTask CronTask
|
|
||||||
MsgGateway MsgGateway
|
|
||||||
MsgTransfer MsgTransfer
|
|
||||||
Push Push
|
|
||||||
Auth Auth
|
|
||||||
Conversation Conversation
|
|
||||||
Friend Friend
|
|
||||||
Group Group
|
|
||||||
Msg Msg
|
|
||||||
Third Third
|
|
||||||
User User
|
|
||||||
Redis Redis
|
|
||||||
Share Share
|
|
||||||
Webhooks Webhooks
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AllConfig) Name2Config(name string) any {
|
|
||||||
switch name {
|
|
||||||
case a.Discovery.GetConfigFileName():
|
|
||||||
return a.Discovery
|
|
||||||
case a.Kafka.GetConfigFileName():
|
|
||||||
return a.Kafka
|
|
||||||
case a.LocalCache.GetConfigFileName():
|
|
||||||
return a.LocalCache
|
|
||||||
case a.Log.GetConfigFileName():
|
|
||||||
return a.Log
|
|
||||||
case a.Minio.GetConfigFileName():
|
|
||||||
return a.Minio
|
|
||||||
case a.Mongo.GetConfigFileName():
|
|
||||||
return a.Mongo
|
|
||||||
case a.Notification.GetConfigFileName():
|
|
||||||
return a.Notification
|
|
||||||
case a.API.GetConfigFileName():
|
|
||||||
return a.API
|
|
||||||
case a.CronTask.GetConfigFileName():
|
|
||||||
return a.CronTask
|
|
||||||
case a.MsgGateway.GetConfigFileName():
|
|
||||||
return a.MsgGateway
|
|
||||||
case a.MsgTransfer.GetConfigFileName():
|
|
||||||
return a.MsgTransfer
|
|
||||||
case a.Push.GetConfigFileName():
|
|
||||||
return a.Push
|
|
||||||
case a.Auth.GetConfigFileName():
|
|
||||||
return a.Auth
|
|
||||||
case a.Conversation.GetConfigFileName():
|
|
||||||
return a.Conversation
|
|
||||||
case a.Friend.GetConfigFileName():
|
|
||||||
return a.Friend
|
|
||||||
case a.Group.GetConfigFileName():
|
|
||||||
return a.Group
|
|
||||||
case a.Msg.GetConfigFileName():
|
|
||||||
return a.Msg
|
|
||||||
case a.Third.GetConfigFileName():
|
|
||||||
return a.Third
|
|
||||||
case a.User.GetConfigFileName():
|
|
||||||
return a.User
|
|
||||||
case a.Redis.GetConfigFileName():
|
|
||||||
return a.Redis
|
|
||||||
case a.Share.GetConfigFileName():
|
|
||||||
return a.Share
|
|
||||||
case a.Webhooks.GetConfigFileName():
|
|
||||||
return a.Webhooks
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AllConfig) GetConfigNames() []string {
|
|
||||||
return []string{
|
|
||||||
a.Discovery.GetConfigFileName(),
|
|
||||||
a.Kafka.GetConfigFileName(),
|
|
||||||
a.LocalCache.GetConfigFileName(),
|
|
||||||
a.Log.GetConfigFileName(),
|
|
||||||
a.Minio.GetConfigFileName(),
|
|
||||||
a.Mongo.GetConfigFileName(),
|
|
||||||
a.Notification.GetConfigFileName(),
|
|
||||||
a.API.GetConfigFileName(),
|
|
||||||
a.CronTask.GetConfigFileName(),
|
|
||||||
a.MsgGateway.GetConfigFileName(),
|
|
||||||
a.MsgTransfer.GetConfigFileName(),
|
|
||||||
a.Push.GetConfigFileName(),
|
|
||||||
a.Auth.GetConfigFileName(),
|
|
||||||
a.Conversation.GetConfigFileName(),
|
|
||||||
a.Friend.GetConfigFileName(),
|
|
||||||
a.Group.GetConfigFileName(),
|
|
||||||
a.Msg.GetConfigFileName(),
|
|
||||||
a.Third.GetConfigFileName(),
|
|
||||||
a.User.GetConfigFileName(),
|
|
||||||
a.Redis.GetConfigFileName(),
|
|
||||||
a.Share.GetConfigFileName(),
|
|
||||||
a.Webhooks.GetConfigFileName(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
package config
|
package config
|
||||||
|
|
||||||
const ConfKey = "conf"
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MountConfigFilePath = "CONFIG_PATH"
|
MountConfigFilePath = "CONFIG_PATH"
|
||||||
DeploymentType = "DEPLOYMENT_TYPE"
|
DeploymentType = "DEPLOYMENT_TYPE"
|
||||||
|
|||||||
@@ -1,29 +1,13 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Load(configDirectory string, configFileName string, envPrefix string, runtimeEnv string, config any) error {
|
func LoadConfig(path string, envPrefix string, config any) error {
|
||||||
if runtimeEnv == KUBERNETES {
|
|
||||||
mountPath := os.Getenv(MountConfigFilePath)
|
|
||||||
if mountPath == "" {
|
|
||||||
return errs.ErrArgs.WrapMsg(MountConfigFilePath + " env is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return loadConfig(filepath.Join(mountPath, configFileName), envPrefix, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
return loadConfig(filepath.Join(configDirectory, configFileName), envPrefix, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadConfig(path string, envPrefix string, config any) error {
|
|
||||||
v := viper.New()
|
v := viper.New()
|
||||||
v.SetConfigFile(path)
|
v.SetConfigFile(path)
|
||||||
v.SetEnvPrefix(envPrefix)
|
v.SetEnvPrefix(envPrefix)
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FileName = "config.yaml"
|
FileName = "config.yaml"
|
||||||
|
NotificationFileName = "notification.yaml"
|
||||||
|
DefaultFolderPath = "../config/"
|
||||||
)
|
)
|
||||||
|
|
||||||
// return absolude path join ../config/, this is k8s container config path.
|
// return absolude path join ../config/, this is k8s container config path.
|
||||||
@@ -56,10 +58,13 @@ func GetProjectRoot() (string, error) {
|
|||||||
return projectRoot, nil
|
return projectRoot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOptionsByNotification(cfg NotificationConfig) msgprocessor.Options {
|
func GetOptionsByNotification(cfg NotificationConfig, sendMessage *bool) msgprocessor.Options {
|
||||||
opts := msgprocessor.NewOptions()
|
opts := msgprocessor.NewOptions()
|
||||||
|
|
||||||
if cfg.UnreadCount {
|
if sendMessage != nil {
|
||||||
|
cfg.IsSendMsg = *sendMessage
|
||||||
|
}
|
||||||
|
if cfg.IsSendMsg {
|
||||||
opts = msgprocessor.WithOptions(opts, msgprocessor.WithUnreadCount(true))
|
opts = msgprocessor.WithOptions(opts, msgprocessor.WithUnreadCount(true))
|
||||||
}
|
}
|
||||||
if cfg.OfflinePush.Enable {
|
if cfg.OfflinePush.Enable {
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ package convert
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"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/protocol/relation"
|
"github.com/openimsdk/protocol/relation"
|
||||||
|
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
@@ -98,7 +100,7 @@ func FriendOnlyDB2PbOnly(friendsDB []*model.Friend) []*relation.FriendInfoOnly {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.FriendRequest, getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) ([]*sdkws.FriendRequest, error) {
|
func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.FriendRequest, getUsers func(ctx context.Context, userIDs []string) (map[string]common_user.CommonUser, error)) ([]*sdkws.FriendRequest, error) {
|
||||||
if len(friendRequests) == 0 {
|
if len(friendRequests) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -117,11 +119,11 @@ func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.FriendReque
|
|||||||
fromUser := users[friendRequest.FromUserID]
|
fromUser := users[friendRequest.FromUserID]
|
||||||
res = append(res, &sdkws.FriendRequest{
|
res = append(res, &sdkws.FriendRequest{
|
||||||
FromUserID: friendRequest.FromUserID,
|
FromUserID: friendRequest.FromUserID,
|
||||||
FromNickname: fromUser.Nickname,
|
FromNickname: fromUser.GetNickname(),
|
||||||
FromFaceURL: fromUser.FaceURL,
|
FromFaceURL: fromUser.GetFaceURL(),
|
||||||
ToUserID: friendRequest.ToUserID,
|
ToUserID: friendRequest.ToUserID,
|
||||||
ToNickname: toUser.Nickname,
|
ToNickname: toUser.GetNickname(),
|
||||||
ToFaceURL: toUser.FaceURL,
|
ToFaceURL: toUser.GetFaceURL(),
|
||||||
HandleResult: friendRequest.HandleResult,
|
HandleResult: friendRequest.HandleResult,
|
||||||
ReqMsg: friendRequest.ReqMsg,
|
ReqMsg: friendRequest.ReqMsg,
|
||||||
CreateTime: friendRequest.CreateTime.UnixMilli(),
|
CreateTime: friendRequest.CreateTime.UnixMilli(),
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
package etcd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/openimsdk/tools/errs"
|
|
||||||
"github.com/openimsdk/tools/log"
|
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
|
||||||
clientv3 "go.etcd.io/etcd/client/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ShutDowns []func() error
|
|
||||||
)
|
|
||||||
|
|
||||||
func RegisterShutDown(shutDown ...func() error) {
|
|
||||||
ShutDowns = append(ShutDowns, shutDown...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigManager struct {
|
|
||||||
client *clientv3.Client
|
|
||||||
watchConfigNames []string
|
|
||||||
lock sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildKey(s string) string {
|
|
||||||
return ConfigKeyPrefix + s
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfigManager(client *clientv3.Client, configNames []string) *ConfigManager {
|
|
||||||
return &ConfigManager{
|
|
||||||
client: client,
|
|
||||||
watchConfigNames: datautil.Batch(func(s string) string { return BuildKey(s) }, append(configNames, RestartKey))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfigManager) Watch(ctx context.Context) {
|
|
||||||
chans := make([]clientv3.WatchChan, 0, len(c.watchConfigNames))
|
|
||||||
for _, name := range c.watchConfigNames {
|
|
||||||
chans = append(chans, c.client.Watch(ctx, name, clientv3.WithPrefix()))
|
|
||||||
}
|
|
||||||
|
|
||||||
doWatch := func(watchChan clientv3.WatchChan) {
|
|
||||||
for watchResp := range watchChan {
|
|
||||||
if watchResp.Err() != nil {
|
|
||||||
log.ZError(ctx, "watch err", errs.Wrap(watchResp.Err()))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, event := range watchResp.Events {
|
|
||||||
if event.IsModify() {
|
|
||||||
if datautil.Contain(string(event.Kv.Key), c.watchConfigNames...) {
|
|
||||||
c.lock.Lock()
|
|
||||||
err := restartServer(ctx)
|
|
||||||
if err != nil {
|
|
||||||
log.ZError(ctx, "restart server err", err)
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, ch := range chans {
|
|
||||||
go doWatch(ch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func restartServer(ctx context.Context) error {
|
|
||||||
exePath, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return errs.New("get executable path fail").Wrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
args := os.Args
|
|
||||||
env := os.Environ()
|
|
||||||
|
|
||||||
cmd := exec.Command(exePath, args[1:]...)
|
|
||||||
cmd.Env = env
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
|
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
|
||||||
}
|
|
||||||
log.ZInfo(ctx, "shutdown server")
|
|
||||||
for _, f := range ShutDowns {
|
|
||||||
if err = f(); err != nil {
|
|
||||||
log.ZError(ctx, "shutdown fail", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.ZInfo(ctx, "restart server")
|
|
||||||
err = cmd.Start()
|
|
||||||
if err != nil {
|
|
||||||
return errs.New("restart server fail").Wrap()
|
|
||||||
}
|
|
||||||
log.ZInfo(ctx, "cmd start over")
|
|
||||||
|
|
||||||
os.Exit(0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package etcd
|
|
||||||
|
|
||||||
const (
|
|
||||||
ConfigKeyPrefix = "/open-im/config/"
|
|
||||||
RestartKey = "restart"
|
|
||||||
EnableConfigCenterKey = "enable-config-center"
|
|
||||||
Enable = "enable"
|
|
||||||
Disable = "disable"
|
|
||||||
)
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
package kubernetes
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/informers"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
"k8s.io/client-go/rest"
|
|
||||||
"k8s.io/client-go/tools/cache"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KubernetesConnManager struct {
|
|
||||||
clientset *kubernetes.Clientset
|
|
||||||
namespace string
|
|
||||||
dialOptions []grpc.DialOption
|
|
||||||
|
|
||||||
rpcTargets map[string]string
|
|
||||||
selfTarget string
|
|
||||||
|
|
||||||
mu sync.RWMutex
|
|
||||||
connMap map[string][]*grpc.ClientConn
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewKubernetesConnManager creates a new connection manager that uses Kubernetes services for service discovery.
|
|
||||||
func NewKubernetesConnManager(namespace string, options ...grpc.DialOption) (*KubernetesConnManager, error) {
|
|
||||||
config, err := rest.InClusterConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create in-cluster config: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
clientset, err := kubernetes.NewForConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create clientset: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
k := &KubernetesConnManager{
|
|
||||||
clientset: clientset,
|
|
||||||
namespace: namespace,
|
|
||||||
dialOptions: options,
|
|
||||||
connMap: make(map[string][]*grpc.ClientConn),
|
|
||||||
}
|
|
||||||
|
|
||||||
go k.watchEndpoints()
|
|
||||||
|
|
||||||
return k, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesConnManager) initializeConns(serviceName string) error {
|
|
||||||
port, err := k.getServicePort(serviceName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints, err := k.clientset.CoreV1().Endpoints(k.namespace).Get(context.Background(), serviceName, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get endpoints for service %s: %v", serviceName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmt.Println("Endpoints:", endpoints, "endpoints.Subsets:", endpoints.Subsets)
|
|
||||||
|
|
||||||
var conns []*grpc.ClientConn
|
|
||||||
for _, subset := range endpoints.Subsets {
|
|
||||||
for _, address := range subset.Addresses {
|
|
||||||
target := fmt.Sprintf("%s:%d", address.IP, port)
|
|
||||||
// fmt.Println("IP target:", target)
|
|
||||||
conn, err := grpc.Dial(target, append(k.dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))...)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to dial endpoint %s: %v", target, err)
|
|
||||||
}
|
|
||||||
conns = append(conns, conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
k.mu.Lock()
|
|
||||||
k.connMap[serviceName] = conns
|
|
||||||
k.mu.Unlock()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConns returns gRPC client connections for a given Kubernetes service name.
|
|
||||||
func (k *KubernetesConnManager) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
|
|
||||||
k.mu.RLock()
|
|
||||||
|
|
||||||
conns, exists := k.connMap[serviceName]
|
|
||||||
k.mu.RUnlock()
|
|
||||||
if exists {
|
|
||||||
return conns, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
k.mu.Lock()
|
|
||||||
// Check if another goroutine has already initialized the connections when we released the read lock
|
|
||||||
conns, exists = k.connMap[serviceName]
|
|
||||||
if exists {
|
|
||||||
return conns, nil
|
|
||||||
}
|
|
||||||
k.mu.Unlock()
|
|
||||||
|
|
||||||
if err := k.initializeConns(serviceName); err != nil {
|
|
||||||
fmt.Println("Failed to initialize connections:", err)
|
|
||||||
return nil, fmt.Errorf("failed to initialize connections for service %s: %v", serviceName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return k.connMap[serviceName], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConn returns a single gRPC client connection for a given Kubernetes service name.
|
|
||||||
func (k *KubernetesConnManager) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
|
|
||||||
var target string
|
|
||||||
|
|
||||||
if k.rpcTargets[serviceName] == "" {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
svcPort, err := k.getServicePort(serviceName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
target = fmt.Sprintf("%s.%s.svc.cluster.local:%d", serviceName, k.namespace, svcPort)
|
|
||||||
|
|
||||||
// fmt.Println("SVC target:", target)
|
|
||||||
} else {
|
|
||||||
target = k.rpcTargets[serviceName]
|
|
||||||
}
|
|
||||||
|
|
||||||
return grpc.DialContext(
|
|
||||||
ctx,
|
|
||||||
target,
|
|
||||||
append([]grpc.DialOption{
|
|
||||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
|
||||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(1024*1024*10), grpc.MaxCallSendMsgSize(1024*1024*20)),
|
|
||||||
}, k.dialOptions...)...,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSelfConnTarget returns the connection target for the current service.
|
|
||||||
func (k *KubernetesConnManager) GetSelfConnTarget() string {
|
|
||||||
if k.selfTarget == "" {
|
|
||||||
hostName := os.Getenv("HOSTNAME")
|
|
||||||
|
|
||||||
pod, err := k.clientset.CoreV1().Pods(k.namespace).Get(context.Background(), hostName, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("failed to get pod %s: %v \n", hostName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for pod.Status.PodIP == "" {
|
|
||||||
pod, err = k.clientset.CoreV1().Pods(k.namespace).Get(context.TODO(), hostName, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error getting pod: %v \n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
var selfPort int32
|
|
||||||
|
|
||||||
for _, port := range pod.Spec.Containers[0].Ports {
|
|
||||||
if port.ContainerPort != 10001 {
|
|
||||||
selfPort = port.ContainerPort
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
k.selfTarget = fmt.Sprintf("%s:%d", pod.Status.PodIP, selfPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
return k.selfTarget
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddOption appends gRPC dial options to the existing options.
|
|
||||||
func (k *KubernetesConnManager) AddOption(opts ...grpc.DialOption) {
|
|
||||||
k.mu.Lock()
|
|
||||||
defer k.mu.Unlock()
|
|
||||||
k.dialOptions = append(k.dialOptions, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseConn closes a given gRPC client connection.
|
|
||||||
func (k *KubernetesConnManager) CloseConn(conn *grpc.ClientConn) {
|
|
||||||
conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes all gRPC connections managed by KubernetesConnManager.
|
|
||||||
func (k *KubernetesConnManager) Close() {
|
|
||||||
k.mu.Lock()
|
|
||||||
defer k.mu.Unlock()
|
|
||||||
for _, conns := range k.connMap {
|
|
||||||
for _, conn := range conns {
|
|
||||||
_ = conn.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
k.connMap = make(map[string][]*grpc.ClientConn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesConnManager) Register(serviceName, host string, port int, opts ...grpc.DialOption) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesConnManager) UnRegister() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesConnManager) GetUserIdHashGatewayHost(ctx context.Context, userId string) (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesConnManager) getServicePort(serviceName string) (int32, error) {
|
|
||||||
var svcPort int32
|
|
||||||
|
|
||||||
svc, err := k.clientset.CoreV1().Services(k.namespace).Get(context.Background(), serviceName, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Print("namespace:", k.namespace)
|
|
||||||
return 0, fmt.Errorf("failed to get service %s: %v", serviceName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(svc.Spec.Ports) == 0 {
|
|
||||||
return 0, fmt.Errorf("service %s has no ports defined", serviceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, port := range svc.Spec.Ports {
|
|
||||||
// fmt.Println(serviceName, " Now Get Port:", port.Port)
|
|
||||||
if port.Port != 10001 {
|
|
||||||
svcPort = port.Port
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return svcPort, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchEndpoints listens for changes in Pod resources.
|
|
||||||
func (k *KubernetesConnManager) watchEndpoints() {
|
|
||||||
informerFactory := informers.NewSharedInformerFactory(k.clientset, time.Minute*10)
|
|
||||||
informer := informerFactory.Core().V1().Pods().Informer()
|
|
||||||
|
|
||||||
// Watch for Pod changes (add, update, delete)
|
|
||||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
|
||||||
AddFunc: func(obj interface{}) {
|
|
||||||
k.handleEndpointChange(obj)
|
|
||||||
},
|
|
||||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
|
||||||
k.handleEndpointChange(newObj)
|
|
||||||
},
|
|
||||||
DeleteFunc: func(obj interface{}) {
|
|
||||||
k.handleEndpointChange(obj)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
informerFactory.Start(context.Background().Done())
|
|
||||||
<-context.Background().Done() // Block forever
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesConnManager) handleEndpointChange(obj interface{}) {
|
|
||||||
endpoint, ok := obj.(*v1.Endpoints)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
serviceName := endpoint.Name
|
|
||||||
if err := k.initializeConns(serviceName); err != nil {
|
|
||||||
fmt.Printf("Error initializing connections for %s: %v\n", serviceName, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,4 +12,4 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package direct // import "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/direct"
|
package direct // import "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/direct"
|
||||||
+8
-12
@@ -12,33 +12,29 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package discovery
|
package discoveryregister
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
"google.golang.org/grpc"
|
|
||||||
|
|
||||||
"github.com/openimsdk/tools/discovery/kubernetes"
|
|
||||||
|
|
||||||
"github.com/openimsdk/tools/discovery/etcd"
|
"github.com/openimsdk/tools/discovery/etcd"
|
||||||
|
"github.com/openimsdk/tools/discovery/kubernetes"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDiscoveryRegister creates a new service discovery and registry client based on the provided environment type.
|
// NewDiscoveryRegister creates a new service discovery and registry client based on the provided environment type.
|
||||||
func NewDiscoveryRegister(discovery *config.Discovery, runtimeEnv string, watchNames []string) (discovery.SvcDiscoveryRegistry, error) {
|
func NewDiscoveryRegister(discovery *config.Discovery, share *config.Share, watchNames []string) (discovery.SvcDiscoveryRegistry, error) {
|
||||||
if runtimeEnv == config.KUBERNETES {
|
switch discovery.Enable {
|
||||||
return kubernetes.NewKubernetesConnManager(discovery.Kubernetes.Namespace,
|
case "k8s":
|
||||||
|
return kubernetes.NewKubernetesConnManager("default",
|
||||||
grpc.WithDefaultCallOptions(
|
grpc.WithDefaultCallOptions(
|
||||||
grpc.MaxCallSendMsgSize(1024*1024*20),
|
grpc.MaxCallSendMsgSize(1024*1024*20),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
case "etcd":
|
||||||
|
|
||||||
switch discovery.Enable {
|
|
||||||
case config.ETCD:
|
|
||||||
return etcd.NewSvcDiscoveryRegistry(
|
return etcd.NewSvcDiscoveryRegistry(
|
||||||
discovery.Etcd.RootDirectory,
|
discovery.Etcd.RootDirectory,
|
||||||
discovery.Etcd.Address,
|
discovery.Etcd.Address,
|
||||||
+1
-1
@@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package discovery
|
package discoveryregister
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
@@ -12,4 +12,4 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package discovery // import "github.com/openimsdk/open-im-server/v3/pkg/common/discovery"
|
package discoveryregister // import "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||||
@@ -12,4 +12,4 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package kubernetes // import "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/kubernetes"
|
package kubernetes // import "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/etcd"
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright © 2024 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 zookeeper // import "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister/zookeeper"
|
||||||
@@ -43,25 +43,25 @@ func GetGrpcServerMetrics() *gp.ServerMetrics {
|
|||||||
return grpcMetrics
|
return grpcMetrics
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetGrpcCusMetrics(registerName string, discovery *config.Discovery) []prometheus.Collector {
|
func GetGrpcCusMetrics(registerName string, share *config.Share) []prometheus.Collector {
|
||||||
switch registerName {
|
switch registerName {
|
||||||
case discovery.RpcService.MessageGateway:
|
case share.RpcRegisterName.MessageGateway:
|
||||||
return []prometheus.Collector{OnlineUserGauge}
|
return []prometheus.Collector{OnlineUserGauge}
|
||||||
case discovery.RpcService.Msg:
|
case share.RpcRegisterName.Msg:
|
||||||
return []prometheus.Collector{
|
return []prometheus.Collector{
|
||||||
SingleChatMsgProcessSuccessCounter,
|
SingleChatMsgProcessSuccessCounter,
|
||||||
SingleChatMsgProcessFailedCounter,
|
SingleChatMsgProcessFailedCounter,
|
||||||
GroupChatMsgProcessSuccessCounter,
|
GroupChatMsgProcessSuccessCounter,
|
||||||
GroupChatMsgProcessFailedCounter,
|
GroupChatMsgProcessFailedCounter,
|
||||||
}
|
}
|
||||||
case discovery.RpcService.Push:
|
case share.RpcRegisterName.Push:
|
||||||
return []prometheus.Collector{
|
return []prometheus.Collector{
|
||||||
MsgOfflinePushFailedCounter,
|
MsgOfflinePushFailedCounter,
|
||||||
MsgLoneTimePushCounter,
|
MsgLoneTimePushCounter,
|
||||||
}
|
}
|
||||||
case discovery.RpcService.Auth:
|
case share.RpcRegisterName.Auth:
|
||||||
return []prometheus.Collector{UserLoginCounter}
|
return []prometheus.Collector{UserLoginCounter}
|
||||||
case discovery.RpcService.User:
|
case share.RpcRegisterName.User:
|
||||||
return []prometheus.Collector{UserRegisterCounter}
|
return []prometheus.Collector{UserRegisterCounter}
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -22,20 +22,18 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
conf "github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
disetcd "github.com/openimsdk/open-im-server/v3/pkg/common/discovery/etcd"
|
|
||||||
"github.com/openimsdk/tools/discovery/etcd"
|
"github.com/openimsdk/tools/discovery/etcd"
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
"github.com/openimsdk/tools/utils/jsonutil"
|
"github.com/openimsdk/tools/utils/jsonutil"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
"github.com/openimsdk/tools/utils/runtimeenv"
|
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||||
|
|
||||||
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discovery"
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||||
"github.com/openimsdk/tools/discovery"
|
"github.com/openimsdk/tools/discovery"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
@@ -46,14 +44,56 @@ import (
|
|||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getConfigRpcMaxRequestBody(value reflect.Value) *conf.MaxRequestBody {
|
||||||
|
for value.Kind() == reflect.Pointer {
|
||||||
|
value = value.Elem()
|
||||||
|
}
|
||||||
|
if value.Kind() == reflect.Struct {
|
||||||
|
num := value.NumField()
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
field := value.Field(i)
|
||||||
|
if !field.CanInterface() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for field.Kind() == reflect.Pointer {
|
||||||
|
field = field.Elem()
|
||||||
|
}
|
||||||
|
switch elem := field.Interface().(type) {
|
||||||
|
case conf.Share:
|
||||||
|
return &elem.RPCMaxBodySize
|
||||||
|
case conf.MaxRequestBody:
|
||||||
|
return &elem
|
||||||
|
}
|
||||||
|
if field.Kind() == reflect.Struct {
|
||||||
|
if elem := getConfigRpcMaxRequestBody(field); elem != nil {
|
||||||
|
return elem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Start rpc server.
|
// Start rpc server.
|
||||||
func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConfig *conf.Prometheus, listenIP,
|
func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConfig *conf.Prometheus, listenIP,
|
||||||
registerIP string, autoSetPorts bool, rpcPorts []int, index int, rpcRegisterName string, notification *conf.Notification, config T,
|
registerIP string, autoSetPorts bool, rpcPorts []int, index int, rpcRegisterName string, share *conf.Share, config T,
|
||||||
watchConfigNames []string, watchServiceNames []string,
|
watchServiceNames []string,
|
||||||
rpcFn func(ctx context.Context, config T, client discovery.SvcDiscoveryRegistry, server *grpc.Server) error,
|
rpcFn func(ctx context.Context, config T, client discovery.SvcDiscoveryRegistry, server *grpc.Server) error,
|
||||||
options ...grpc.ServerOption) error {
|
options ...grpc.ServerOption) error {
|
||||||
|
|
||||||
watchConfigNames = append(watchConfigNames, conf.LogConfigFileName)
|
maxRequestBody := &share.RPCMaxBodySize
|
||||||
|
var clientOptions []grpc.DialOption
|
||||||
|
if maxRequestBody != nil {
|
||||||
|
if maxRequestBody.RequestMaxBodySize > 0 {
|
||||||
|
options = append(options, grpc.MaxRecvMsgSize(maxRequestBody.RequestMaxBodySize))
|
||||||
|
clientOptions = append(clientOptions, grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(maxRequestBody.RequestMaxBodySize)))
|
||||||
|
}
|
||||||
|
if maxRequestBody.ResponseMaxBodySize > 0 {
|
||||||
|
options = append(options, grpc.MaxSendMsgSize(maxRequestBody.ResponseMaxBodySize))
|
||||||
|
clientOptions = append(clientOptions, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxRequestBody.ResponseMaxBodySize)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rpcTcpAddr string
|
rpcTcpAddr string
|
||||||
netDone = make(chan struct{}, 2)
|
netDone = make(chan struct{}, 2)
|
||||||
@@ -61,17 +101,11 @@ func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConf
|
|||||||
prometheusPort int
|
prometheusPort int
|
||||||
)
|
)
|
||||||
|
|
||||||
if notification != nil {
|
|
||||||
conf.InitNotification(notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
registerIP, err := network.GetRpcRegisterIP(registerIP)
|
registerIP, err := network.GetRpcRegisterIP(registerIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runTimeEnv := runtimeenv.PrintRuntimeEnvironment()
|
|
||||||
|
|
||||||
if !autoSetPorts {
|
if !autoSetPorts {
|
||||||
rpcPort, err := datautil.GetElemByIndex(rpcPorts, index)
|
rpcPort, err := datautil.GetElemByIndex(rpcPorts, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -95,7 +129,7 @@ func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConf
|
|||||||
if autoSetPorts && discovery.Enable != conf.ETCD {
|
if autoSetPorts && discovery.Enable != conf.ETCD {
|
||||||
return errs.New("only etcd support autoSetPorts", "rpcRegisterName", rpcRegisterName).Wrap()
|
return errs.New("only etcd support autoSetPorts", "rpcRegisterName", rpcRegisterName).Wrap()
|
||||||
}
|
}
|
||||||
client, err := kdisc.NewDiscoveryRegister(discovery, runTimeEnv, watchServiceNames)
|
client, err := kdisc.NewDiscoveryRegister(discovery, share, watchServiceNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -103,6 +137,10 @@ func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConf
|
|||||||
defer client.Close()
|
defer client.Close()
|
||||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||||
|
|
||||||
|
if len(clientOptions) > 0 {
|
||||||
|
client.AddOption(clientOptions...)
|
||||||
|
}
|
||||||
|
|
||||||
// var reg *prometheus.Registry
|
// var reg *prometheus.Registry
|
||||||
// var metric *grpcprometheus.ServerMetrics
|
// var metric *grpcprometheus.ServerMetrics
|
||||||
if prometheusConfig.Enable {
|
if prometheusConfig.Enable {
|
||||||
@@ -142,7 +180,7 @@ func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConf
|
|||||||
return errs.WrapMsg(err, "listen err", "rpcTcpAddr", rpcTcpAddr)
|
return errs.WrapMsg(err, "listen err", "rpcTcpAddr", rpcTcpAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cs := prommetrics.GetGrpcCusMetrics(rpcRegisterName, discovery)
|
cs := prommetrics.GetGrpcCusMetrics(rpcRegisterName, share)
|
||||||
go func() {
|
go func() {
|
||||||
if err := prommetrics.RpcInit(cs, listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
if err := prommetrics.RpcInit(cs, listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
netErr = errs.WrapMsg(err, fmt.Sprintf("rpc %s prometheus start err: %d", rpcRegisterName, prometheusPort))
|
netErr = errs.WrapMsg(err, fmt.Sprintf("rpc %s prometheus start err: %d", rpcRegisterName, prometheusPort))
|
||||||
@@ -177,6 +215,7 @@ func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConf
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = client.Register(
|
err = client.Register(
|
||||||
|
ctx,
|
||||||
rpcRegisterName,
|
rpcRegisterName,
|
||||||
registerIP,
|
registerIP,
|
||||||
port,
|
port,
|
||||||
@@ -194,11 +233,6 @@ func Start[T any](ctx context.Context, discovery *conf.Discovery, prometheusConf
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if discovery.Enable == conf.ETCD {
|
|
||||||
cm := disetcd.NewConfigManager(client.(*etcd.SvcDiscoveryRegistryImpl).GetClient(), watchConfigNames)
|
|
||||||
cm.Watch(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGTERM)
|
signal.Notify(sigs, syscall.SIGTERM)
|
||||||
select {
|
select {
|
||||||
|
|||||||
@@ -17,10 +17,11 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
||||||
"github.com/openimsdk/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
@@ -61,10 +62,10 @@ type FriendDatabase interface {
|
|||||||
PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error)
|
PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error)
|
||||||
|
|
||||||
// PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination
|
// PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination
|
||||||
PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error)
|
PageFriendRequestFromMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error)
|
||||||
|
|
||||||
// PageFriendRequestToMe retrieves the friend requests received by the user with pagination
|
// PageFriendRequestToMe retrieves the friend requests received by the user with pagination
|
||||||
PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error)
|
PageFriendRequestToMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error)
|
||||||
|
|
||||||
// FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist
|
// FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist
|
||||||
FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*model.Friend, err error)
|
FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*model.Friend, err error)
|
||||||
@@ -87,6 +88,8 @@ type FriendDatabase interface {
|
|||||||
FindFriendUserID(ctx context.Context, friendUserID string) ([]string, error)
|
FindFriendUserID(ctx context.Context, friendUserID string) ([]string, error)
|
||||||
|
|
||||||
OwnerIncrVersion(ctx context.Context, ownerUserID string, friendUserIDs []string, state int32) error
|
OwnerIncrVersion(ctx context.Context, ownerUserID string, friendUserIDs []string, state int32) error
|
||||||
|
|
||||||
|
GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type friendDatabase struct {
|
type friendDatabase struct {
|
||||||
@@ -334,13 +337,13 @@ func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PageFriendRequestFromMe retrieves friend requests sent by me. It does not return an error if the result is empty.
|
// PageFriendRequestFromMe retrieves friend requests sent by me. It does not return an error if the result is empty.
|
||||||
func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) {
|
func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) {
|
||||||
return f.friendRequest.FindFromUserID(ctx, userID, pagination)
|
return f.friendRequest.FindFromUserID(ctx, userID, handleResults, pagination)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PageFriendRequestToMe retrieves friend requests received by me. It does not return an error if the result is empty.
|
// PageFriendRequestToMe retrieves friend requests received by me. It does not return an error if the result is empty.
|
||||||
func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) {
|
func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) {
|
||||||
return f.friendRequest.FindToUserID(ctx, userID, pagination)
|
return f.friendRequest.FindToUserID(ctx, userID, handleResults, pagination)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindFriendsWithError retrieves specified friends' information for ownerUserID. Returns an error if any friend does not exist.
|
// FindFriendsWithError retrieves specified friends' information for ownerUserID. Returns an error if any friend does not exist.
|
||||||
@@ -397,3 +400,7 @@ func (f *friendDatabase) OwnerIncrVersion(ctx context.Context, ownerUserID strin
|
|||||||
}
|
}
|
||||||
return f.cache.DelMaxFriendVersion(ownerUserID).ChainExecDel(ctx)
|
return f.cache.DelMaxFriendVersion(ownerUserID).ChainExecDel(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *friendDatabase) GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error) {
|
||||||
|
return f.friendRequest.GetUnhandledCount(ctx, userID, ts)
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ type GroupDatabase interface {
|
|||||||
// FindUserManagedGroupID retrieves group IDs managed by a user.
|
// FindUserManagedGroupID retrieves group IDs managed by a user.
|
||||||
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
|
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
|
||||||
// PageGroupRequest paginates through group requests for specified groups.
|
// PageGroupRequest paginates through group requests for specified groups.
|
||||||
PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
|
PageGroupRequest(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
|
||||||
// GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level.
|
// GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level.
|
||||||
GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
|
GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ type GroupDatabase interface {
|
|||||||
// FindGroupRequests retrieves multiple group join requests.
|
// FindGroupRequests retrieves multiple group join requests.
|
||||||
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
|
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
|
||||||
// PageGroupRequestUser paginates through group join requests made by a user.
|
// PageGroupRequestUser paginates through group join requests made by a user.
|
||||||
PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
|
PageGroupRequestUser(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
|
||||||
|
|
||||||
// CountTotal counts the total number of groups as of a certain date.
|
// CountTotal counts the total number of groups as of a certain date.
|
||||||
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
|
CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
|
||||||
@@ -124,6 +124,8 @@ type GroupDatabase interface {
|
|||||||
SearchJoinGroup(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*model.Group, error)
|
SearchJoinGroup(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*model.Group, error)
|
||||||
|
|
||||||
FindJoinGroupID(ctx context.Context, userID string) ([]string, error)
|
FindJoinGroupID(ctx context.Context, userID string) ([]string, error)
|
||||||
|
|
||||||
|
GetGroupApplicationUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGroupDatabase(
|
func NewGroupDatabase(
|
||||||
@@ -304,8 +306,8 @@ func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID strin
|
|||||||
return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
|
return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
|
func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
|
||||||
return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination)
|
return g.groupRequestDB.PageGroup(ctx, groupIDs, handleResults, pagination)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error) {
|
func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error) {
|
||||||
@@ -463,16 +465,12 @@ func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*mode
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *groupDatabase) TakeGroupRequest(
|
func (g *groupDatabase) TakeGroupRequest(ctx context.Context, groupID string, userID string) (*model.GroupRequest, error) {
|
||||||
ctx context.Context,
|
|
||||||
groupID string,
|
|
||||||
userID string,
|
|
||||||
) (*model.GroupRequest, error) {
|
|
||||||
return g.groupRequestDB.Take(ctx, groupID, userID)
|
return g.groupRequestDB.Take(ctx, groupID, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
|
func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
|
||||||
return g.groupRequestDB.Page(ctx, userID, pagination)
|
return g.groupRequestDB.Page(ctx, userID, groupIDs, handleResults, pagination)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
|
func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
|
||||||
@@ -565,3 +563,7 @@ func (g *groupDatabase) MemberGroupIncrVersion(ctx context.Context, groupID stri
|
|||||||
}
|
}
|
||||||
return g.cache.DelMaxGroupMemberVersion(groupID).ChainExecDel(ctx)
|
return g.cache.DelMaxGroupMemberVersion(groupID).ChainExecDel(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *groupDatabase) GetGroupApplicationUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) {
|
||||||
|
return g.groupRequestDB.GetUnhandledCount(ctx, groupIDs, ts)
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||||
"github.com/openimsdk/tools/utils/jsonutil"
|
"github.com/openimsdk/tools/utils/jsonutil"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||||
@@ -38,7 +39,6 @@ import (
|
|||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -310,7 +310,7 @@ func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][
|
|||||||
log.ZError(ctx, "json.Unmarshal", err)
|
log.ZError(ctx, "json.Unmarshal", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if quoteMsg.QuoteMessage == nil || quoteMsg.QuoteMessage.Content == "" {
|
if quoteMsg.QuoteMessage == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if quoteMsg.QuoteMessage.Content == "e30=" {
|
if quoteMsg.QuoteMessage.Content == "e30=" {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||||
"github.com/openimsdk/protocol/constant"
|
"github.com/openimsdk/protocol/constant"
|
||||||
"github.com/openimsdk/tools/utils/datautil"
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
|
|
||||||
@@ -14,7 +16,6 @@ import (
|
|||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ import (
|
|||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
||||||
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/kafka"
|
||||||
"github.com/openimsdk/protocol/push"
|
"github.com/openimsdk/protocol/push"
|
||||||
"github.com/openimsdk/protocol/sdkws"
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
"github.com/openimsdk/tools/log"
|
"github.com/openimsdk/tools/log"
|
||||||
"github.com/openimsdk/tools/mq/kafka"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PushDatabase interface {
|
type PushDatabase interface {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type S3Database interface {
|
type S3Database interface {
|
||||||
PartLimit() *s3.PartLimit
|
PartLimit() (*s3.PartLimit, error)
|
||||||
PartSize(ctx context.Context, size int64) (int64, error)
|
PartSize(ctx context.Context, size int64) (int64, error)
|
||||||
AuthSign(ctx context.Context, uploadID string, partNumbers []int) (*s3.AuthSignResult, error)
|
AuthSign(ctx context.Context, uploadID string, partNumbers []int) (*s3.AuthSignResult, error)
|
||||||
InitiateMultipartUpload(ctx context.Context, hash string, size int64, expire time.Duration, maxParts int) (*cont.InitiateUploadResult, error)
|
InitiateMultipartUpload(ctx context.Context, hash string, size int64, expire time.Duration, maxParts int) (*cont.InitiateUploadResult, error)
|
||||||
@@ -65,7 +65,7 @@ func (s *s3Database) PartSize(ctx context.Context, size int64) (int64, error) {
|
|||||||
return s.s3.PartSize(ctx, size)
|
return s.s3.PartSize(ctx, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *s3Database) PartLimit() *s3.PartLimit {
|
func (s *s3Database) PartLimit() (*s3.PartLimit, error) {
|
||||||
return s.s3.PartLimit()
|
return s.s3.PartLimit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||||
"github.com/openimsdk/tools/db/pagination"
|
"github.com/openimsdk/tools/db/pagination"
|
||||||
)
|
)
|
||||||
@@ -33,8 +34,9 @@ type FriendRequest interface {
|
|||||||
Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error)
|
Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error)
|
||||||
Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error)
|
Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error)
|
||||||
// Get list of friend requests received by toUserID
|
// Get list of friend requests received by toUserID
|
||||||
FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error)
|
FindToUserID(ctx context.Context, toUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error)
|
||||||
// Get list of friend requests sent by fromUserID
|
// Get list of friend requests sent by fromUserID
|
||||||
FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error)
|
FindFromUserID(ctx context.Context, fromUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error)
|
||||||
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error)
|
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error)
|
||||||
|
GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||||
"github.com/openimsdk/tools/db/pagination"
|
"github.com/openimsdk/tools/db/pagination"
|
||||||
)
|
)
|
||||||
@@ -26,6 +27,7 @@ type GroupRequest interface {
|
|||||||
UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
|
UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
|
||||||
Take(ctx context.Context, groupID string, userID string) (groupRequest *model.GroupRequest, err error)
|
Take(ctx context.Context, groupID string, userID string) (groupRequest *model.GroupRequest, err error)
|
||||||
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
|
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
|
||||||
Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
|
Page(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
|
||||||
PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
|
PageGroup(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
|
||||||
|
GetUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,24 +16,35 @@ package mgo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||||
|
|
||||||
"github.com/openimsdk/tools/db/mongoutil"
|
|
||||||
"github.com/openimsdk/tools/db/pagination"
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
|
||||||
|
"github.com/openimsdk/tools/db/mongoutil"
|
||||||
|
"github.com/openimsdk/tools/db/pagination"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewFriendRequestMongo(db *mongo.Database) (database.FriendRequest, error) {
|
func NewFriendRequestMongo(db *mongo.Database) (database.FriendRequest, error) {
|
||||||
coll := db.Collection(database.FriendRequestName)
|
coll := db.Collection(database.FriendRequestName)
|
||||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||||
Keys: bson.D{
|
{
|
||||||
{Key: "from_user_id", Value: 1},
|
Keys: bson.D{
|
||||||
{Key: "to_user_id", Value: 1},
|
{Key: "from_user_id", Value: 1},
|
||||||
|
{Key: "to_user_id", Value: 1},
|
||||||
|
},
|
||||||
|
Options: options.Index().SetUnique(true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Keys: bson.D{
|
||||||
|
{Key: "create_time", Value: -1},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Options: options.Index().SetUnique(true),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -45,12 +56,24 @@ type FriendRequestMgo struct {
|
|||||||
coll *mongo.Collection
|
coll *mongo.Collection
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FriendRequestMgo) FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) {
|
func (f *FriendRequestMgo) sort() any {
|
||||||
return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, bson.M{"to_user_id": toUserID}, pagination)
|
return bson.D{{Key: "create_time", Value: -1}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FriendRequestMgo) FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) {
|
func (f *FriendRequestMgo) FindToUserID(ctx context.Context, toUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) {
|
||||||
return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, bson.M{"from_user_id": fromUserID}, pagination)
|
filter := bson.M{"to_user_id": toUserID}
|
||||||
|
if len(handleResults) > 0 {
|
||||||
|
filter["handle_result"] = bson.M{"$in": handleResults}
|
||||||
|
}
|
||||||
|
return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, filter, pagination, options.Find().SetSort(f.sort()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FriendRequestMgo) FindFromUserID(ctx context.Context, fromUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) {
|
||||||
|
filter := bson.M{"from_user_id": fromUserID}
|
||||||
|
if len(handleResults) > 0 {
|
||||||
|
filter["handle_result"] = bson.M{"$in": handleResults}
|
||||||
|
}
|
||||||
|
return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, filter, pagination, options.Find().SetSort(f.sort()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FriendRequestMgo) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error) {
|
func (f *FriendRequestMgo) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error) {
|
||||||
@@ -110,3 +133,11 @@ func (f *FriendRequestMgo) Find(ctx context.Context, fromUserID, toUserID string
|
|||||||
func (f *FriendRequestMgo) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error) {
|
func (f *FriendRequestMgo) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error) {
|
||||||
return f.Find(ctx, fromUserID, toUserID)
|
return f.Find(ctx, fromUserID, toUserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FriendRequestMgo) GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error) {
|
||||||
|
filter := bson.M{"to_user_id": userID, "handle_result": 0}
|
||||||
|
if ts != 0 {
|
||||||
|
filter["create_time"] = bson.M{"$gt": time.Unix(ts, 0)}
|
||||||
|
}
|
||||||
|
return mongoutil.Count(ctx, f.coll, filter)
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,25 +16,36 @@ package mgo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||||
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
|
||||||
"github.com/openimsdk/tools/db/mongoutil"
|
"github.com/openimsdk/tools/db/mongoutil"
|
||||||
"github.com/openimsdk/tools/db/pagination"
|
"github.com/openimsdk/tools/db/pagination"
|
||||||
"github.com/openimsdk/tools/errs"
|
"github.com/openimsdk/tools/errs"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewGroupRequestMgo(db *mongo.Database) (database.GroupRequest, error) {
|
func NewGroupRequestMgo(db *mongo.Database) (database.GroupRequest, error) {
|
||||||
coll := db.Collection(database.GroupRequestName)
|
coll := db.Collection(database.GroupRequestName)
|
||||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||||
Keys: bson.D{
|
{
|
||||||
{Key: "group_id", Value: 1},
|
Keys: bson.D{
|
||||||
{Key: "user_id", Value: 1},
|
{Key: "group_id", Value: 1},
|
||||||
|
{Key: "user_id", Value: 1},
|
||||||
|
},
|
||||||
|
Options: options.Index().SetUnique(true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Keys: bson.D{
|
||||||
|
{Key: "req_time", Value: -1},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Options: options.Index().SetUnique(true),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errs.Wrap(err)
|
return nil, errs.Wrap(err)
|
||||||
@@ -66,10 +77,39 @@ func (g *GroupRequestMgo) FindGroupRequests(ctx context.Context, groupID string,
|
|||||||
return mongoutil.Find[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
|
return mongoutil.Find[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GroupRequestMgo) Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) {
|
func (g *GroupRequestMgo) sort() any {
|
||||||
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, bson.M{"user_id": userID}, pagination)
|
return bson.D{{Key: "req_time", Value: -1}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) {
|
func (g *GroupRequestMgo) Page(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) {
|
||||||
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}}, pagination)
|
filter := bson.M{"user_id": userID}
|
||||||
|
if len(groupIDs) > 0 {
|
||||||
|
filter["group_id"] = bson.M{"$in": datautil.Distinct(groupIDs)}
|
||||||
|
}
|
||||||
|
if len(handleResults) > 0 {
|
||||||
|
filter["handle_result"] = bson.M{"$in": handleResults}
|
||||||
|
}
|
||||||
|
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, filter, pagination, options.Find().SetSort(g.sort()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) {
|
||||||
|
if len(groupIDs) == 0 {
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
|
filter := bson.M{"group_id": bson.M{"$in": groupIDs}}
|
||||||
|
if len(handleResults) > 0 {
|
||||||
|
filter["handle_result"] = bson.M{"$in": handleResults}
|
||||||
|
}
|
||||||
|
return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, filter, pagination, options.Find().SetSort(g.sort()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GroupRequestMgo) GetUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) {
|
||||||
|
if len(groupIDs) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
filter := bson.M{"group_id": bson.M{"$in": groupIDs}, "handle_result": 0}
|
||||||
|
if ts != 0 {
|
||||||
|
filter["req_time"] = bson.M{"$gt": time.Unix(ts, 0)}
|
||||||
|
}
|
||||||
|
return mongoutil.Count(ctx, g.coll, filter)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright © 2024 OpenIM open source community. 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 kafka
|
||||||
|
|
||||||
|
type TLSConfig struct {
|
||||||
|
EnableTLS bool `yaml:"enableTLS"`
|
||||||
|
CACrt string `yaml:"caCrt"`
|
||||||
|
ClientCrt string `yaml:"clientCrt"`
|
||||||
|
ClientKey string `yaml:"clientKey"`
|
||||||
|
ClientKeyPwd string `yaml:"clientKeyPwd"`
|
||||||
|
InsecureSkipVerify bool `yaml:"insecureSkipVerify"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Username string `yaml:"username"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
ProducerAck string `yaml:"producerAck"`
|
||||||
|
CompressType string `yaml:"compressType"`
|
||||||
|
Addr []string `yaml:"addr"`
|
||||||
|
TLS TLSConfig `yaml:"tls"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// 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 kafka
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/IBM/sarama"
|
||||||
|
"github.com/openimsdk/tools/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MConsumerGroup struct {
|
||||||
|
sarama.ConsumerGroup
|
||||||
|
groupID string
|
||||||
|
topics []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMConsumerGroup(conf *Config, groupID string, topics []string, autoCommitEnable bool) (*MConsumerGroup, error) {
|
||||||
|
config, err := BuildConsumerGroupConfig(conf, sarama.OffsetNewest, autoCommitEnable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
group, err := NewConsumerGroup(config, conf.Addr, groupID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &MConsumerGroup{
|
||||||
|
ConsumerGroup: group,
|
||||||
|
groupID: groupID,
|
||||||
|
topics: topics,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MConsumerGroup) GetContextFromMsg(cMsg *sarama.ConsumerMessage) context.Context {
|
||||||
|
return GetContextWithMQHeader(cMsg.Headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MConsumerGroup) RegisterHandleAndConsumer(ctx context.Context, handler sarama.ConsumerGroupHandler) {
|
||||||
|
for {
|
||||||
|
err := mc.ConsumerGroup.Consume(ctx, mc.topics, handler)
|
||||||
|
if errors.Is(err, sarama.ErrClosedConsumerGroup) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if errors.Is(err, context.Canceled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.ZWarn(ctx, "consume err", err, "topic", mc.topics, "groupID", mc.groupID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mc *MConsumerGroup) Close() error {
|
||||||
|
return mc.ConsumerGroup.Close()
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// 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 kafka
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/IBM/sarama"
|
||||||
|
"github.com/openimsdk/tools/errs"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Producer represents a Kafka producer.
|
||||||
|
type Producer struct {
|
||||||
|
addr []string
|
||||||
|
topic string
|
||||||
|
config *sarama.Config
|
||||||
|
producer sarama.SyncProducer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKafkaProducer(config *sarama.Config, addr []string, topic string) (*Producer, error) {
|
||||||
|
producer, err := NewProducer(config, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Producer{
|
||||||
|
addr: addr,
|
||||||
|
topic: topic,
|
||||||
|
config: config,
|
||||||
|
producer: producer,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendMessage sends a message to the Kafka topic configured in the Producer.
|
||||||
|
func (p *Producer) SendMessage(ctx context.Context, key string, msg proto.Message) (int32, int64, error) {
|
||||||
|
// Marshal the protobuf message
|
||||||
|
bMsg, err := proto.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, errs.WrapMsg(err, "kafka proto Marshal err")
|
||||||
|
}
|
||||||
|
if len(bMsg) == 0 {
|
||||||
|
return 0, 0, errs.WrapMsg(errEmptyMsg, "kafka proto Marshal err")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare Kafka message
|
||||||
|
kMsg := &sarama.ProducerMessage{
|
||||||
|
Topic: p.topic,
|
||||||
|
Key: sarama.StringEncoder(key),
|
||||||
|
Value: sarama.ByteEncoder(bMsg),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate message key and value
|
||||||
|
if kMsg.Key.Length() == 0 || kMsg.Value.Length() == 0 {
|
||||||
|
return 0, 0, errs.Wrap(errEmptyMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach context metadata as headers
|
||||||
|
header, err := GetMQHeaderWithContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
kMsg.Headers = header
|
||||||
|
|
||||||
|
// Send the message
|
||||||
|
partition, offset, err := p.producer.SendMessage(kMsg)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, errs.WrapMsg(err, "p.producer.SendMessage error")
|
||||||
|
}
|
||||||
|
|
||||||
|
return partition, offset, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package kafka
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IBM/sarama"
|
||||||
|
"github.com/openimsdk/tools/errs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BuildConsumerGroupConfig(conf *Config, initial int64, autoCommitEnable bool) (*sarama.Config, error) {
|
||||||
|
kfk := sarama.NewConfig()
|
||||||
|
kfk.Version = sarama.V2_0_0_0
|
||||||
|
kfk.Consumer.Offsets.Initial = initial
|
||||||
|
kfk.Consumer.Offsets.AutoCommit.Enable = autoCommitEnable
|
||||||
|
kfk.Consumer.Return.Errors = false
|
||||||
|
if conf.Username != "" || conf.Password != "" {
|
||||||
|
kfk.Net.SASL.Enable = true
|
||||||
|
kfk.Net.SASL.User = conf.Username
|
||||||
|
kfk.Net.SASL.Password = conf.Password
|
||||||
|
}
|
||||||
|
if conf.TLS.EnableTLS {
|
||||||
|
tls, err := newTLSConfig(conf.TLS.ClientCrt, conf.TLS.ClientKey, conf.TLS.CACrt, []byte(conf.TLS.ClientKeyPwd), conf.TLS.InsecureSkipVerify)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
kfk.Net.TLS.Config = tls
|
||||||
|
kfk.Net.TLS.Enable = true
|
||||||
|
}
|
||||||
|
return kfk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConsumerGroup(conf *sarama.Config, addr []string, groupID string) (sarama.ConsumerGroup, error) {
|
||||||
|
cg, err := sarama.NewConsumerGroup(addr, groupID, conf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "NewConsumerGroup failed", "addr", addr, "groupID", groupID, "conf", *conf)
|
||||||
|
}
|
||||||
|
return cg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildProducerConfig(conf Config) (*sarama.Config, error) {
|
||||||
|
kfk := sarama.NewConfig()
|
||||||
|
kfk.Producer.Return.Successes = true
|
||||||
|
kfk.Producer.Return.Errors = true
|
||||||
|
kfk.Producer.Partitioner = sarama.NewHashPartitioner
|
||||||
|
if conf.Username != "" || conf.Password != "" {
|
||||||
|
kfk.Net.SASL.Enable = true
|
||||||
|
kfk.Net.SASL.User = conf.Username
|
||||||
|
kfk.Net.SASL.Password = conf.Password
|
||||||
|
}
|
||||||
|
switch strings.ToLower(conf.ProducerAck) {
|
||||||
|
case "no_response":
|
||||||
|
kfk.Producer.RequiredAcks = sarama.NoResponse
|
||||||
|
case "wait_for_local":
|
||||||
|
kfk.Producer.RequiredAcks = sarama.WaitForLocal
|
||||||
|
case "wait_for_all":
|
||||||
|
kfk.Producer.RequiredAcks = sarama.WaitForAll
|
||||||
|
default:
|
||||||
|
kfk.Producer.RequiredAcks = sarama.WaitForAll
|
||||||
|
}
|
||||||
|
if conf.CompressType == "" {
|
||||||
|
kfk.Producer.Compression = sarama.CompressionNone
|
||||||
|
} else {
|
||||||
|
if err := kfk.Producer.Compression.UnmarshalText(bytes.ToLower([]byte(conf.CompressType))); err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "UnmarshalText failed", "compressType", conf.CompressType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if conf.TLS.EnableTLS {
|
||||||
|
tls, err := newTLSConfig(conf.TLS.ClientCrt, conf.TLS.ClientKey, conf.TLS.CACrt, []byte(conf.TLS.ClientKeyPwd), conf.TLS.InsecureSkipVerify)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
kfk.Net.TLS.Config = tls
|
||||||
|
kfk.Net.TLS.Enable = true
|
||||||
|
}
|
||||||
|
return kfk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProducer(conf *sarama.Config, addr []string) (sarama.SyncProducer, error) {
|
||||||
|
producer, err := sarama.NewSyncProducer(addr, conf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "NewSyncProducer failed", "addr", addr, "conf", *conf)
|
||||||
|
}
|
||||||
|
return producer, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// Copyright © 2024 OpenIM open source community. 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 kafka
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/openimsdk/tools/errs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// decryptPEM decrypts a PEM block using a password.
|
||||||
|
func decryptPEM(data []byte, passphrase []byte) ([]byte, error) {
|
||||||
|
if len(passphrase) == 0 {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
b, _ := pem.Decode(data)
|
||||||
|
d, err := x509.DecryptPEMBlock(b, passphrase)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "DecryptPEMBlock failed")
|
||||||
|
}
|
||||||
|
return pem.EncodeToMemory(&pem.Block{
|
||||||
|
Type: b.Type,
|
||||||
|
Bytes: d,
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readEncryptablePEMBlock(path string, pwd []byte) ([]byte, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "ReadFile failed", "path", path)
|
||||||
|
}
|
||||||
|
return decryptPEM(data, pwd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTLSConfig setup the TLS config from general config file.
|
||||||
|
func newTLSConfig(clientCertFile, clientKeyFile, caCertFile string, keyPwd []byte, insecureSkipVerify bool) (*tls.Config, error) {
|
||||||
|
var tlsConfig tls.Config
|
||||||
|
if clientCertFile != "" && clientKeyFile != "" {
|
||||||
|
certPEMBlock, err := os.ReadFile(clientCertFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "ReadFile failed", "clientCertFile", clientCertFile)
|
||||||
|
}
|
||||||
|
keyPEMBlock, err := readEncryptablePEMBlock(clientKeyFile, keyPwd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "X509KeyPair failed")
|
||||||
|
}
|
||||||
|
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||||
|
}
|
||||||
|
|
||||||
|
if caCertFile != "" {
|
||||||
|
caCert, err := os.ReadFile(caCertFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errs.WrapMsg(err, "ReadFile failed", "caCertFile", caCertFile)
|
||||||
|
}
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
|
||||||
|
return nil, errs.New("AppendCertsFromPEM failed")
|
||||||
|
}
|
||||||
|
tlsConfig.RootCAs = caCertPool
|
||||||
|
}
|
||||||
|
tlsConfig.InsecureSkipVerify = insecureSkipVerify
|
||||||
|
return &tlsConfig, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package kafka
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/IBM/sarama"
|
||||||
|
"github.com/openimsdk/protocol/constant"
|
||||||
|
"github.com/openimsdk/tools/mcontext"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errEmptyMsg = errors.New("kafka binary msg is empty")
|
||||||
|
|
||||||
|
// GetMQHeaderWithContext extracts message queue headers from the context.
|
||||||
|
func GetMQHeaderWithContext(ctx context.Context) ([]sarama.RecordHeader, error) {
|
||||||
|
operationID, opUserID, platform, connID, err := mcontext.GetCtxInfos(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return []sarama.RecordHeader{
|
||||||
|
{Key: []byte(constant.OperationID), Value: []byte(operationID)},
|
||||||
|
{Key: []byte(constant.OpUserID), Value: []byte(opUserID)},
|
||||||
|
{Key: []byte(constant.OpUserPlatform), Value: []byte(platform)},
|
||||||
|
{Key: []byte(constant.ConnID), Value: []byte(connID)},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContextWithMQHeader creates a context from message queue headers.
|
||||||
|
func GetContextWithMQHeader(header []*sarama.RecordHeader) context.Context {
|
||||||
|
var values []string
|
||||||
|
for _, recordHeader := range header {
|
||||||
|
values = append(values, string(recordHeader.Value))
|
||||||
|
}
|
||||||
|
return mcontext.WithMustInfoCtx(values) // Attach extracted values to context
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user