mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-04-28 22:39:18 +08:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ee4736d6d0 | |||
| 181d304496 | |||
| 2b8b8b3204 | |||
| f0a60a71ae | |||
| 38cfa4a9c4 | |||
| cbade46ae0 | |||
| bfc4684a36 | |||
| 2c612ba6d0 | |||
| c2fd0061b0 | |||
| b17f4f15e8 | |||
| 334749c5a2 | |||
| bf88535800 | |||
| a37eb5ea0d | |||
| daba153d27 | |||
| 15648cd44d | |||
| 1df49ee718 | |||
| 8471a0ef3b | |||
| e0284724b5 | |||
| 12790e141d | |||
| 68698961f1 | |||
| ad8ae5f5f0 | |||
| 3ebd1bbaa4 | |||
| 8d308a4163 | |||
| 1516e9cb3a | |||
| 41d5688de6 | |||
| 269dd7180f | |||
| 61fc9bffec | |||
| ea477fd91f | |||
| b85e36e97c | |||
| 5af41e83ce | |||
| 07d30a645b | |||
| a4eae35118 | |||
| 53cf2c0540 | |||
| 4de3befd60 | |||
| 4a8abfa21d | |||
| 649250b7c6 | |||
| 312c8ba9d6 | |||
| b36b69506f | |||
| 4be508a640 | |||
| 0207f1dab1 | |||
| bbac036d6c | |||
| 9baf1ffe82 | |||
| b5ef71f5c2 | |||
| 43919bc5fe | |||
| 0d03b46ac8 | |||
| a84f7bd217 | |||
| 9e8a389698 | |||
| a2110e416a | |||
| 0b612c13c6 | |||
| e7c7bf3bd1 | |||
| 3167f9943f | |||
| 598750e8c7 | |||
| 87f79d3cee | |||
| 7f44319b9b |
@@ -8,10 +8,10 @@ ALERTMANAGER_IMAGE=prom/alertmanager:v0.27.0
|
||||
GRAFANA_IMAGE=grafana/grafana:11.0.1
|
||||
|
||||
OPENIM_WEB_FRONT_IMAGE=openim/openim-web-front:release-v3.8.1
|
||||
OPENIM_ADMIN_FRONT_IMAGE=openim/openim-admin-front:release-v1.8.3
|
||||
OPENIM_ADMIN_FRONT_IMAGE=openim/openim-admin-front:release-v1.8.2
|
||||
|
||||
#FRONT_IMAGE: use aliyun images
|
||||
#OPENIM_WEB_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-web-front:release-v3.8.1
|
||||
#OPENIM_ADMIN_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:release-v1.8.3
|
||||
#OPENIM_ADMIN_FRONT_IMAGE=registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-admin-front:release-v1.8.2
|
||||
|
||||
DATA_DIR=./
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
name: Build and release services Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release-*
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Tag version to be used for Docker image"
|
||||
required: true
|
||||
default: "v3.8.3"
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Log in to Aliyun Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALIREGISTRY_USERNAME }}
|
||||
password: ${{ secrets.ALIREGISTRY_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker (tags, labels)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern=v{{version}}
|
||||
# type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern=release-{{raw}}
|
||||
type=sha
|
||||
type=raw,value=${{ github.event.inputs.tag }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
run: |
|
||||
ROOT_DIR="build/images"
|
||||
for dir in "$ROOT_DIR"/*/; do
|
||||
# Find Dockerfile or *.dockerfile in a case-insensitive manner
|
||||
dockerfile=$(find "$dir" -maxdepth 1 -type f \( -iname 'dockerfile' -o -iname '*.dockerfile' \) | head -n 1)
|
||||
|
||||
if [ -n "$dockerfile" ] && [ -f "$dockerfile" ]; then
|
||||
IMAGE_NAME=$(basename "$dir")
|
||||
echo "Building Docker image for $IMAGE_NAME with tags:"
|
||||
|
||||
# Initialize tag arguments
|
||||
tag_args=()
|
||||
|
||||
# Read each tag and append --tag arguments
|
||||
while IFS= read -r tag; do
|
||||
tag_args+=(--tag "${{ secrets.DOCKER_USERNAME }}/$IMAGE_NAME:$tag")
|
||||
tag_args+=(--tag "ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME:$tag")
|
||||
tag_args+=(--tag "registry.cn-hangzhou.aliyuncs.com/openimsdk/$IMAGE_NAME:$tag")
|
||||
done <<< "${{ steps.meta.outputs.tags }}"
|
||||
|
||||
# Build and push the Docker image with all tags
|
||||
docker buildx build --platform linux/amd64,linux/arm64 \
|
||||
--file "$dockerfile" \
|
||||
"${tag_args[@]}" \
|
||||
--push "$dir"
|
||||
else
|
||||
echo "No valid Dockerfile found in $dir"
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,75 @@
|
||||
## [v3.8.2](https://github.com/openimsdk/open-im-server/releases/tag/v3.8.2) (2024-11-25)
|
||||
|
||||
### New Features
|
||||
* feat: improve publish docker image workflows [#2697](https://github.com/openimsdk/open-im-server/pull/2697)
|
||||
* feat: Msg filter [#2703](https://github.com/openimsdk/open-im-server/pull/2703)
|
||||
* feat: provide the interface required [#2712](https://github.com/openimsdk/open-im-server/pull/2712)
|
||||
* feat: add webhooks of online status and remove zookeeper configuration. [#2716](https://github.com/openimsdk/open-im-server/pull/2716)
|
||||
* feat: Add More Multi Login Policy [#2770](https://github.com/openimsdk/open-im-server/pull/2770)
|
||||
* feat: Push configuration can ignore case sensitivity [#2775](https://github.com/openimsdk/open-im-server/pull/2775)
|
||||
* feat: support app update service [#2794](https://github.com/openimsdk/open-im-server/pull/2794)
|
||||
* feat: implement merge milestone PR to target-branch. [#2796](https://github.com/openimsdk/open-im-server/pull/2796)
|
||||
* feat: support app update service [#2811](https://github.com/openimsdk/open-im-server/pull/2811)
|
||||
* feat: ApplicationVersion move chat [#2813](https://github.com/openimsdk/open-im-server/pull/2813)
|
||||
* feat: Update login policy [#2822](https://github.com/openimsdk/open-im-server/pull/2822)
|
||||
* feat: merge js sdk [#2856](https://github.com/openimsdk/open-im-server/pull/2856)
|
||||
* feat: Print Panic Log [#2850](https://github.com/openimsdk/open-im-server/pull/2850)
|
||||
|
||||
### Bug Fixes
|
||||
* fix: update load file logic. [#2700](https://github.com/openimsdk/open-im-server/pull/2700)
|
||||
* fix: the message I sent is not set to read seq in mongodb [#2718](https://github.com/openimsdk/open-im-server/pull/2718)
|
||||
* fix: cannot modify group member avatars [#2719](https://github.com/openimsdk/open-im-server/pull/2719)
|
||||
* fix: auth package import twice [#2724](https://github.com/openimsdk/open-im-server/pull/2724)
|
||||
* fix: join the group chat directly, notification type error [#2772](https://github.com/openimsdk/open-im-server/pull/2772)
|
||||
* fix: change update group member level logic [#2730](https://github.com/openimsdk/open-im-server/pull/2730)
|
||||
* fix: joinSource check args error. [#2773](https://github.com/openimsdk/open-im-server/pull/2773)
|
||||
* fix: Change group member roleLevel can`t send notification [#2777](https://github.com/openimsdk/open-im-server/pull/2777)
|
||||
* fix: client sends message status error to server [#2779](https://github.com/openimsdk/open-im-server/pull/2779)
|
||||
* fix: del UserB's conversation version cache when userA set conversati… [#2785](https://github.com/openimsdk/open-im-server/pull/2785)
|
||||
* fix: improve setConversationAtInfo logic. [#2782](https://github.com/openimsdk/open-im-server/pull/2782)
|
||||
* fix: improve transfer Owner logic when newOwner is mute. [#2790](https://github.com/openimsdk/open-im-server/pull/2790)
|
||||
* fix: improve getUserInfo logic. [#2792](https://github.com/openimsdk/open-im-server/pull/2792)
|
||||
* fix: improve time condition check mehtod. [#2804](https://github.com/openimsdk/open-im-server/pull/2804)
|
||||
* fix: webhook before online push [#2805](https://github.com/openimsdk/open-im-server/pull/2805)
|
||||
* fix: set own read seq in MongoDB when sender send a message. [#2808](https://github.com/openimsdk/open-im-server/pull/2808)
|
||||
* fix: solve err Notification when setGroupInfo. [#2806](https://github.com/openimsdk/open-im-server/pull/2806)
|
||||
* fix: improve condition check. [#2815](https://github.com/openimsdk/open-im-server/pull/2815)
|
||||
* fix: Write back message to Redis [#2836](https://github.com/openimsdk/open-im-server/pull/2836)
|
||||
* fix: get group return repeated result [#2842](https://github.com/openimsdk/open-im-server/pull/2842)
|
||||
* fix: SetConversations can update new conversation [#2838](https://github.com/openimsdk/open-im-server/pull/2838)
|
||||
* fix(push): push content with jpush [#2844](https://github.com/openimsdk/open-im-server/pull/2844)
|
||||
* fix #2860 migrate jpns to jpush [#2861](https://github.com/openimsdk/open-im-server/pull/2861)
|
||||
* fix: concurrent write to websocket connection [#2866](https://github.com/openimsdk/open-im-server/pull/2866)
|
||||
* fix: Remove admin token in redis [#2871](https://github.com/openimsdk/open-im-server/pull/2871)
|
||||
* Fix Push2User webhookBeforeOfflinePush [#2862](https://github.com/openimsdk/open-im-server/pull/2862)
|
||||
* fix: move workflow to correct path [#2837](https://github.com/openimsdk/open-im-server/pull/2837)
|
||||
* fix: del login Policy [#2825](https://github.com/openimsdk/open-im-server/pull/2825)
|
||||
* fix: Wrong Redis Error Check [#2876](https://github.com/openimsdk/open-im-server/pull/2876)
|
||||
* fix: minor log typo [#2881](https://github.com/openimsdk/open-im-server/pull/2881)
|
||||
* fix: webhookAfterSingleMsgRead will be called correctly [#2884](https://github.com/openimsdk/open-im-server/pull/2884)
|
||||
* fix: webhookBeforeSendSingleMsg will call before black and friend check [#2885](https://github.com/openimsdk/open-im-server/pull/2885)
|
||||
|
||||
### Chores
|
||||
* chore: remove unused content [#2786](https://github.com/openimsdk/open-im-server/pull/2786)
|
||||
|
||||
### Builds
|
||||
* build: improve workflows logic. [#2801](https://github.com/openimsdk/open-im-server/pull/2801)
|
||||
* build: implement version file update when release. [#2826](https://github.com/openimsdk/open-im-server/pull/2826)
|
||||
* build: update mongo and kafka start logic. [#2858](https://github.com/openimsdk/open-im-server/pull/2858)
|
||||
* build: create changelog tool and workflows. [#2869](https://github.com/openimsdk/open-im-server/pull/2869)
|
||||
* build(deps): bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 [#2851](https://github.com/openimsdk/open-im-server/pull/2851)
|
||||
|
||||
### Others
|
||||
* Revert: Change group member roleLevel can`t send notification [#2789](https://github.com/openimsdk/open-im-server/pull/2789)
|
||||
* Introducing OpenIM Guru on Gurubase.io [#2788](https://github.com/openimsdk/open-im-server/pull/2788)
|
||||
* revert: write msg to redis [#2883](https://github.com/openimsdk/open-im-server/pull/2883)
|
||||
* @lkzz made their first contribution in https://github.com/openimsdk/open-im-server/pull/2724
|
||||
[#2724](https://github.com/openimsdk/open-im-server/pull/2724)
|
||||
* @alilestera made their first contribution in https://github.com/openimsdk/open-im-server/pull/2773
|
||||
[#2773](https://github.com/openimsdk/open-im-server/pull/2773)
|
||||
* @kursataktas made their first contribution in https://github.com/openimsdk/open-im-server/pull/2788
|
||||
[#2788](https://github.com/openimsdk/open-im-server/pull/2788)
|
||||
* @yoyo930021 made their first contribution in https://github.com/openimsdk/open-im-server/pull/2844
|
||||
[#2844](https://github.com/openimsdk/open-im-server/pull/2844)
|
||||
* @wikylyu made their first contribution in https://github.com/openimsdk/open-im-server/pull/2861
|
||||
[#2861](https://github.com/openimsdk/open-im-server/pull/2861)
|
||||
@@ -0,0 +1,4 @@
|
||||
# CHANGELOGs
|
||||
|
||||
- [CHANGELOG-3.8.md](./CHANGELOG-3.8.md)
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ ENV SERVER_DIR=/openim-server
|
||||
WORKDIR $SERVER_DIR
|
||||
|
||||
# Set the Go proxy to improve dependency resolution speed
|
||||
# ENV GOPROXY=https://goproxy.io,direct
|
||||
ENV GOPROXY=https://goproxy.io,direct
|
||||
|
||||
# Copy all files from the current directory into the container
|
||||
COPY . .
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
[](https://www.bestpractices.dev/projects/8045)
|
||||
[](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
|
||||
[](https://golang.org/)
|
||||
[](https://gurubase.io/g/openim)
|
||||
|
||||
|
||||
<p align="center">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
cronExecuteTime: 0 2 * * *
|
||||
retainChatRecords: 365
|
||||
fileExpireTime: 180
|
||||
deleteObjectType: ["msg-picture","msg-file", "msg-voice","msg-video","msg-video-snapshot","sdklog"]
|
||||
fileExpireTime: 90
|
||||
|
||||
@@ -13,8 +13,8 @@ prometheus:
|
||||
ports: [ 12170, 12171, 12172, 12173, 12174, 12175, 12176, 12177, 12178, 12179, 12180, 12182, 12183, 12184, 12185, 12186 ]
|
||||
|
||||
maxConcurrentWorkers: 3
|
||||
#Use geTui for offline push notifications, or choose fcm or jpush; corresponding configuration settings must be specified.
|
||||
enable: geTui
|
||||
#Use geTui for offline push notifications, or choose fcm or jpns; corresponding configuration settings must be specified.
|
||||
enable:
|
||||
geTui:
|
||||
pushUrl: https://restapi.getui.com/v2/$appId
|
||||
masterSecret:
|
||||
|
||||
+138
-151
@@ -1,188 +1,175 @@
|
||||
# Kubernetes Deployment
|
||||
# OpenIM Application Containerization Deployment Guide
|
||||
|
||||
## Resource Requests
|
||||
OpenIM supports a variety of cluster deployment methods, including but not limited to `helm`, `sealos`, `kustomize`
|
||||
|
||||
- CPU: 2 cores
|
||||
- Memory: 4 GiB
|
||||
- Disk usage: 20 GiB (on Node)
|
||||
Various contributors, as well as previous official releases, have provided some referenceable solutions:
|
||||
|
||||
## Preconditions
|
||||
+ [k8s-jenkins Repository](https://github.com/OpenIMSDK/k8s-jenkins)
|
||||
+ [open-im-server-k8s-deploy Repository](https://github.com/openimsdk/open-im-server-k8s-deploy)
|
||||
+ [openim-charts Repository](https://github.com/OpenIMSDK/openim-charts)
|
||||
+ [deploy-openim Repository](https://github.com/showurl/deploy-openim)
|
||||
|
||||
ensure that you have already deployed the following components:
|
||||
### Dependency Check
|
||||
|
||||
- Redis
|
||||
- MongoDB
|
||||
- Kafka
|
||||
- MinIO
|
||||
```bash
|
||||
Kubernetes: >= 1.16.0-0
|
||||
Helm: >= 3.0
|
||||
```
|
||||
|
||||
## Origin Deploy
|
||||
### Minimum Configuration
|
||||
|
||||
### Enter the target dir
|
||||
|
||||
`cd ./deployments/deploy/`
|
||||
|
||||
### Deploy configs and dependencies
|
||||
|
||||
Upate your configMap `openim-config.yml`. **You can check the official docs for more details.**
|
||||
|
||||
In `openim-config.yml`, you need modify the following configurations:
|
||||
|
||||
**discovery.yml**
|
||||
|
||||
- `kubernetes.namespace`: default is `default`, you can change it to your namespace.
|
||||
|
||||
**mongodb.yml**
|
||||
|
||||
- `address`: set to your already mongodb address or mongo Service name and port in your deployed.
|
||||
- `database`: set to your mongodb database name.(Need have a created database.)
|
||||
- `authSource`: set to your mongodb authSource. (authSource is specify the database name associated with the user's credentials, user need create in this database.)
|
||||
|
||||
**kafka.yml**
|
||||
|
||||
- `address`: set to your already kafka address or kafka Service name and port in your deployed.
|
||||
|
||||
**redis.yml**
|
||||
|
||||
- `address`: set to your already redis address or redis Service name and port in your deployed.
|
||||
|
||||
**minio.yml**
|
||||
|
||||
- `internalAddress`: set to your minio Service name and port in your deployed.
|
||||
- `externalAddress`: set to your already expose minio external address.
|
||||
|
||||
### Set the secret
|
||||
|
||||
A Secret is an object that contains a small amount of sensitive data. Such as password and secret. Secret is similar to ConfigMaps.
|
||||
|
||||
#### Redis:
|
||||
|
||||
Update the `redis-password` value in `redis-secret.yml` to your Redis password encoded in base64.
|
||||
The recommended minimum configuration for a production environment is as follows:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-redis-secret
|
||||
type: Opaque
|
||||
data:
|
||||
redis-password: b3BlbklNMTIz # update to your redis password encoded in base64, if need empty, you can set to ""
|
||||
CPU: 4
|
||||
Memory: 8G
|
||||
Disk: 100G
|
||||
```
|
||||
|
||||
#### Mongo:
|
||||
## Configuration File Generation
|
||||
|
||||
Update the `mongo_openim_username`, `mongo_openim_password` value in `mongo-secret.yml` to your Mongo username and password encoded in base64.
|
||||
We have automated all the files, making the generation of configuration files optional for OpenIM. However, if you desire custom configurations, you can follow the steps below:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-mongo-secret
|
||||
type: Opaque
|
||||
data:
|
||||
mongo_openim_username: b3BlbklN # update to your mongo username encoded in base64, if need empty, you can set to "" (this user credentials need in authSource database).
|
||||
mongo_openim_password: b3BlbklNMTIz # update to your mongo password encoded in base64, if need empty, you can set to ""
|
||||
```bash
|
||||
$ make init
|
||||
# Alternatively, use script:
|
||||
# ./scripts/init-config.sh
|
||||
```
|
||||
|
||||
#### Minio:
|
||||
At this point, configuration files will be generated under `deployments/openim/config`, which you can modify as per your requirements.
|
||||
|
||||
Update the `minio-root-user` and `minio-root-password` value in `minio-secret.yml` to your MinIO accessKeyID and secretAccessKey encoded in base64.
|
||||
## Cluster Setup
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-minio-secret
|
||||
type: Opaque
|
||||
data:
|
||||
minio-root-user: cm9vdA== # update to your minio accessKeyID encoded in base64, if need empty, you can set to ""
|
||||
minio-root-password: b3BlbklNMTIz # update to your minio secretAccessKey encoded in base64, if need empty, you can set to ""
|
||||
If you already have a `kubernetes` cluster, or if you wish to build a `kubernetes` cluster from scratch, you can skip this step.
|
||||
|
||||
For a quick start, I used [sealos](https://github.com/labring/sealos) to rapidly set up the cluster, with sealos also being a wrapper for kubeadm at its core:
|
||||
|
||||
```bash
|
||||
$ SEALOS_VERSION=`curl -s https://api.github.com/repos/labring/sealos/releases/latest | grep -oE '"tag_name": "[^"]+"' | head -n1 | cut -d'"' -f4` && \
|
||||
curl -sfL https://raw.githubusercontent.com/labring/sealos/${SEALOS_VERSION}/scripts/install.sh |
|
||||
sh -s ${SEALOS_VERSION} labring/sealos
|
||||
```
|
||||
|
||||
#### Kafka:
|
||||
**Supported Versions:**
|
||||
|
||||
Update the `kafka-password` value in `kafka-secret.yml` to your Kafka password encoded in base64.
|
||||
+ docker: `labring/kubernetes-docker`:(v1.24.0~v1.27.0)
|
||||
+ containerd: `labring/kubernetes`:(v1.24.0~v1.27.0)
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-kafka-secret
|
||||
type: Opaque
|
||||
data:
|
||||
kafka-password: b3BlbklNMTIz # update to your kafka password encoded in base64, if need empty, you can set to ""
|
||||
#### Cluster Installation:
|
||||
|
||||
Cluster details are as follows:
|
||||
|
||||
| Hostname | IP Address | System Info |
|
||||
| -------- | ---------- | ------------------------------------------------------------ |
|
||||
| master01 | 10.0.0.9 | `Linux VM-0-9-ubuntu 5.15.0-76-generic #83-Ubuntu SMP Thu Jun 15 19:16:32 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux` |
|
||||
| node01 | 10.0.0.4 | Similar to master01 |
|
||||
| node02 | 10.0.0.10 | Similar to master01 |
|
||||
|
||||
```bash
|
||||
$ export CLUSTER_USERNAME=ubuntu
|
||||
$ export CLUSTER_PASSWORD=123456
|
||||
$ sudo sealos run labring/kubernetes:v1.25.0 labring/helm:v3.8.2 labring/calico:v3.24.1 \
|
||||
--masters 10.0.0.9 \
|
||||
--nodes 10.0.0.4,10.0.0.10 \
|
||||
-u "$CLUSTER_USERNAME" \
|
||||
-p "$CLUSTER_PASSWORD"
|
||||
```
|
||||
|
||||
### Apply the secret.
|
||||
|
||||
```shell
|
||||
kubectl apply -f redis-secret.yml -f minio-secret.yml -f mongo-secret.yml -f kafka-secret.yml
|
||||
```
|
||||
|
||||
### Apply all config
|
||||
|
||||
`kubectl apply -f ./openim-config.yml`
|
||||
|
||||
> Attation: If you use `default` namespace, you can excute `clusterRile.yml` to create a cluster role binding for default service account.
|
||||
> **Node** Uninstallation method: using `kubeadm` for uninstallation does not remove `etcd` and `cni` related configurations. Manual clearance or using `sealos` for uninstallation is needed.
|
||||
>
|
||||
> Namespace is modify to `discovery.yml` in `openim-config.yml`, you can change `kubernetes.namespace` to your namespace.
|
||||
> ```bash
|
||||
> $ sealos reset
|
||||
> ```
|
||||
|
||||
**Excute `clusterRole.yml`**
|
||||
|
||||
`kubectl apply -f ./clusterRole.yml`
|
||||
|
||||
### run all deployments and services
|
||||
|
||||
> Note: Ensure that infrastructure services like MinIO, Redis, and Kafka are running before deploying the main applications.
|
||||
If you are local, you can also use Kind and Minikube to test, for example, using Kind:
|
||||
|
||||
```bash
|
||||
kubectl apply \
|
||||
-f openim-api-deployment.yml \
|
||||
-f openim-api-service.yml \
|
||||
-f openim-crontask-deployment.yml \
|
||||
-f openim-rpc-user-deployment.yml \
|
||||
-f openim-rpc-user-service.yml \
|
||||
-f openim-msggateway-deployment.yml \
|
||||
-f openim-msggateway-service.yml \
|
||||
-f openim-push-deployment.yml \
|
||||
-f openim-push-service.yml \
|
||||
-f openim-msgtransfer-service.yml \
|
||||
-f openim-msgtransfer-deployment.yml \
|
||||
-f openim-rpc-conversation-deployment.yml \
|
||||
-f openim-rpc-conversation-service.yml \
|
||||
-f openim-rpc-auth-deployment.yml \
|
||||
-f openim-rpc-auth-service.yml \
|
||||
-f openim-rpc-group-deployment.yml \
|
||||
-f openim-rpc-group-service.yml \
|
||||
-f openim-rpc-friend-deployment.yml \
|
||||
-f openim-rpc-friend-service.yml \
|
||||
-f openim-rpc-msg-deployment.yml \
|
||||
-f openim-rpc-msg-service.yml \
|
||||
-f openim-rpc-third-deployment.yml \
|
||||
-f openim-rpc-third-service.yml
|
||||
$ GO111MODULE="on" go get sigs.k8s.io/kind@v0.11.1
|
||||
$ kind create cluster
|
||||
```
|
||||
|
||||
### Verification
|
||||
### Installing helm
|
||||
|
||||
After deploying the services, verify that everything is running smoothly:
|
||||
Helm simplifies the deployment and management of Kubernetes applications to a large extent by offering version control and release management through packaging.
|
||||
|
||||
**Using Script:**
|
||||
|
||||
```bash
|
||||
# Check the status of all pods
|
||||
kubectl get pods
|
||||
|
||||
# Check the status of services
|
||||
kubectl get svc
|
||||
|
||||
# Check the status of deployments
|
||||
kubectl get deployments
|
||||
|
||||
# View all resources
|
||||
kubectl get all
|
||||
$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||
```
|
||||
|
||||
### clean all
|
||||
**Adding Repository:**
|
||||
|
||||
`kubectl delete -f ./`
|
||||
```bash
|
||||
$ helm repo add brigade https://openimsdk.github.io/openim-charts
|
||||
```
|
||||
|
||||
### Notes:
|
||||
### OpenIM Image Strategy
|
||||
|
||||
- If you use a specific namespace for your deployment, be sure to append the -n <namespace> flag to your kubectl commands.
|
||||
Automated offerings include aliyun, ghcr, docker hub: [Image Documentation](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md)
|
||||
|
||||
**Local Test Build Method:**
|
||||
|
||||
```bash
|
||||
$ make image
|
||||
```
|
||||
|
||||
> This command assists in quickly building the required images locally. For a detailed build strategy, refer to the [Build Documentation](https://github.com/openimsdk/open-im-server/blob/main/build/README.md).
|
||||
|
||||
## Installation
|
||||
|
||||
Explore our Helm-Charts repository and read through: [Helm-Charts Repository](https://github.com/openimsdk/helm-charts)
|
||||
|
||||
|
||||
Using the helm charts repository, you can ignore the following configuration, but if you want to just use the server and scale on top of it, you can go ahead:
|
||||
|
||||
**Use the Helm template to generate the deployment yaml file: `openim-charts.yaml`**
|
||||
|
||||
**Gen Image:**
|
||||
|
||||
```bash
|
||||
../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/helm-image.yaml > ./charts/generated-configs/helm-image.yaml
|
||||
```
|
||||
|
||||
**Gen Charts:**
|
||||
|
||||
```bash
|
||||
for chart in ./charts/*/; do
|
||||
if [[ "$chart" == *"generated-configs"* || "$chart" == *"helmfile.yaml"* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -f "${chart}values.yaml" ]; then
|
||||
helm template "$chart" -f "./charts/generated-configs/helm-image.yaml" -f "./charts/generated-configs/config.yaml" -f "./charts/generated-configs/notification.yaml" >> openim-charts.yaml
|
||||
else
|
||||
helm template "$chart" >> openim-charts.yaml
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
**Use Helmfile:**
|
||||
|
||||
```bash
|
||||
GO111MODULE=on go get github.com/roboll/helmfile@latest
|
||||
```
|
||||
|
||||
```bash
|
||||
export MONGO_ADDRESS=im-mongo
|
||||
export MONGO_PORT=27017
|
||||
export REDIS_ADDRESS=im-redis-master
|
||||
export REDIS_PORT=6379
|
||||
export KAFKA_ADDRESS=im-kafka
|
||||
export KAFKA_PORT=9092
|
||||
export OBJECT_APIURL="https://openim.server.com/api"
|
||||
export MINIO_ENDPOINT="http://im-minio:9000"
|
||||
export MINIO_SIGN_ENDPOINT="https://openim.server.com/im-minio-api"
|
||||
|
||||
mkdir ./charts/generated-configs
|
||||
../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/config.yaml > ./charts/generated-configs/config.yaml
|
||||
cp ../config/notification.yaml ./charts/generated-configs/notification.yaml
|
||||
../scripts/genconfig.sh ../scripts/install/environment.sh ./templates/helm-image.yaml > ./charts/generated-configs/helm-image.yaml
|
||||
```
|
||||
|
||||
```bash
|
||||
helmfile apply
|
||||
```
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-kafka-secret
|
||||
type: Opaque
|
||||
data:
|
||||
kafka-password: ""
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-minio-secret
|
||||
type: Opaque
|
||||
data:
|
||||
minio-root-user: cm9vdA== # Base64 encoded "root"
|
||||
minio-root-password: b3BlbklNMTIz # Base64 encoded "openIM123"
|
||||
@@ -1,79 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: minio
|
||||
labels:
|
||||
app: minio
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: minio
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: minio
|
||||
spec:
|
||||
containers:
|
||||
- name: minio
|
||||
image: minio/minio:RELEASE.2024-01-11T07-46-16Z
|
||||
ports:
|
||||
- containerPort: 9000 # MinIO service port
|
||||
- containerPort: 9090 # MinIO console port
|
||||
volumeMounts:
|
||||
- name: minio-data
|
||||
mountPath: /data
|
||||
- name: minio-config
|
||||
mountPath: /root/.minio
|
||||
env:
|
||||
- name: TZ
|
||||
value: "Asia/Shanghai"
|
||||
- name: MINIO_ROOT_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-user
|
||||
- name: MINIO_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-password
|
||||
command:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- |
|
||||
mkdir -p /data && \
|
||||
minio server /data --console-address ":9090"
|
||||
volumes:
|
||||
- name: minio-data
|
||||
persistentVolumeClaim:
|
||||
claimName: minio-pvc
|
||||
- name: minio-config
|
||||
persistentVolumeClaim:
|
||||
claimName: minio-config-pvc
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: minio-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: minio-config-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-mongo-secret
|
||||
type: Opaque
|
||||
data:
|
||||
mongo_openim_username: b3BlbklN # base64 for "openIM", this user credentials need in authSource database.
|
||||
mongo_openim_password: b3BlbklNMTIz # base64 for "openIM123"
|
||||
@@ -1,108 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: mongo-statefulset
|
||||
spec:
|
||||
serviceName: "mongo"
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mongo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mongo
|
||||
spec:
|
||||
containers:
|
||||
- name: mongo
|
||||
image: mongo:7.0
|
||||
command: ["/bin/bash", "-c"]
|
||||
args:
|
||||
- >
|
||||
docker-entrypoint.sh mongod --wiredTigerCacheSizeGB ${wiredTigerCacheSizeGB} --auth &
|
||||
until mongosh -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --authenticationDatabase admin --eval "db.runCommand({ ping: 1 })" &>/dev/null; do
|
||||
echo "Waiting for MongoDB to start...";
|
||||
sleep 1;
|
||||
done &&
|
||||
mongosh -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD} --authenticationDatabase admin --eval "
|
||||
db = db.getSiblingDB(\"${MONGO_INITDB_DATABASE}\");
|
||||
if (!db.getUser(\"${MONGO_OPENIM_USERNAME}\")) {
|
||||
db.createUser({
|
||||
user: \"${MONGO_OPENIM_USERNAME}\",
|
||||
pwd: \"${MONGO_OPENIM_PASSWORD}\",
|
||||
roles: [{role: \"readWrite\", db: \"${MONGO_INITDB_DATABASE}\"}]
|
||||
});
|
||||
print(\"User created successfully: \");
|
||||
print(\"Username: ${MONGO_OPENIM_USERNAME}\");
|
||||
print(\"Password: ${MONGO_OPENIM_PASSWORD}\");
|
||||
print(\"Database: ${MONGO_INITDB_DATABASE}\");
|
||||
} else {
|
||||
print(\"User already exists in database: ${MONGO_INITDB_DATABASE}, Username: ${MONGO_OPENIM_USERNAME}\");
|
||||
}
|
||||
" &&
|
||||
tail -f /dev/null
|
||||
ports:
|
||||
- containerPort: 27017
|
||||
env:
|
||||
- name: MONGO_INITDB_ROOT_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_initdb_root_username
|
||||
- name: MONGO_INITDB_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_initdb_root_password
|
||||
- name: MONGO_INITDB_DATABASE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_initdb_database
|
||||
- name: MONGO_OPENIM_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_openim_username
|
||||
- name: MONGO_OPENIM_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-init-secret
|
||||
key: mongo_openim_password
|
||||
- name: TZ
|
||||
value: "Asia/Shanghai"
|
||||
- name: wiredTigerCacheSizeGB
|
||||
value: "1"
|
||||
volumeMounts:
|
||||
- name: mongo-storage
|
||||
mountPath: /data/db
|
||||
|
||||
volumes:
|
||||
- name: mongo-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: mongo-pvc
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: mongo-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-mongo-init-secret
|
||||
type: Opaque
|
||||
data:
|
||||
mongo_initdb_root_username: cm9vdA== # base64 for "root"
|
||||
mongo_initdb_root_password: b3BlbklNMTIz # base64 for "openIM123"
|
||||
mongo_initdb_database: b3BlbmltX3Yz # base64 for "openim_v3"
|
||||
mongo_openim_username: b3BlbklN # base64 for "openIM"
|
||||
mongo_openim_password: b3BlbklNMTIz # base64 for "openIM123"
|
||||
@@ -1,47 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: openim-api
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: openim-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: openim-api
|
||||
spec:
|
||||
containers:
|
||||
- name: openim-api-container
|
||||
image: openim/openim-api:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10002
|
||||
- containerPort: 12002
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messagegateway-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messagegateway-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messagegateway-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: openim-msggateway-container
|
||||
image: openim/openim-msggateway:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10140
|
||||
- containerPort: 12001
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,50 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: openim-msgtransfer-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: openim-msgtransfer-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: openim-msgtransfer-server
|
||||
spec:
|
||||
containers:
|
||||
- name: openim-msgtransfer-container
|
||||
image: openim/openim-msgtransfer:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 12020
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,41 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: push-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: push-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: push-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: push-rpc-server-container
|
||||
image: openim/openim-push:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10170
|
||||
- containerPort: 12170
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,37 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: auth-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: auth-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: auth-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: auth-rpc-server-container
|
||||
image: openim/openim-rpc-auth:v3.8.3
|
||||
imagePullPolicy: Never
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10200
|
||||
- containerPort: 12200
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,46 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: conversation-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: conversation-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: conversation-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: conversation-rpc-server-container
|
||||
image: openim/openim-rpc-conversation:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10220
|
||||
- containerPort: 12220
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,46 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: friend-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: friend-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: friend-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: friend-rpc-server-container
|
||||
image: openim/openim-rpc-friend:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10240
|
||||
- containerPort: 12240
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,46 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: group-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: group-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: group-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: group-rpc-server-container
|
||||
image: openim/openim-rpc-group:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10260
|
||||
- containerPort: 12260
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,51 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: msg-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: msg-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: msg-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: msg-rpc-server-container
|
||||
image: openim/openim-rpc-msg:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10280
|
||||
- containerPort: 12280
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,56 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: third-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: third-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: third-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: third-rpc-server-container
|
||||
image: openim/openim-rpc-third:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_MINIO_ACCESSKEYID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-user
|
||||
- name: IMENV_MINIO_SECRETACCESSKEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-minio-secret
|
||||
key: minio-root-password
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10300
|
||||
- containerPort: 12300
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,51 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: user-rpc-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: user-rpc-server
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: user-rpc-server
|
||||
spec:
|
||||
containers:
|
||||
- name: user-rpc-server-container
|
||||
image: openim/openim-rpc-user:v3.8.3
|
||||
env:
|
||||
- name: CONFIG_PATH
|
||||
value: "/config"
|
||||
- name: IMENV_REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-redis-secret
|
||||
key: redis-password
|
||||
- name: IMENV_MONGODB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_username
|
||||
- name: IMENV_MONGODB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-mongo-secret
|
||||
key: mongo_openim_password
|
||||
- name: IMENV_KAFKA_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: openim-kafka-secret
|
||||
key: kafka-password
|
||||
volumeMounts:
|
||||
- name: openim-config
|
||||
mountPath: "/config"
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 10320
|
||||
- containerPort: 12320
|
||||
volumes:
|
||||
- name: openim-config
|
||||
configMap:
|
||||
name: openim-config
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: openim-redis-secret
|
||||
type: Opaque
|
||||
data:
|
||||
redis-password: b3BlbklNMTIz # "openIM123" in base64
|
||||
@@ -1,55 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: redis-statefulset
|
||||
spec:
|
||||
serviceName: "redis"
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7.0.0
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
env:
|
||||
- name: TZ
|
||||
value: "Asia/Shanghai"
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: redis-secret
|
||||
key: redis-password
|
||||
volumeMounts:
|
||||
- name: redis-data
|
||||
mountPath: /data
|
||||
command:
|
||||
[
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
'redis-server --requirepass "$REDIS_PASSWORD" --appendonly yes',
|
||||
]
|
||||
volumes:
|
||||
- name: redis-config-volume
|
||||
configMap:
|
||||
name: openim-config
|
||||
- name: redis-data
|
||||
persistentVolumeClaim:
|
||||
claimName: redis-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: redis-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
@@ -1,6 +1,8 @@
|
||||
module github.com/openimsdk/open-im-server/v3
|
||||
|
||||
go 1.22.7
|
||||
go 1.22.0
|
||||
|
||||
toolchain go1.23.2
|
||||
|
||||
require (
|
||||
firebase.google.com/go/v4 v4.14.1
|
||||
@@ -12,15 +14,15 @@ require (
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.68
|
||||
github.com/openimsdk/tools v0.0.50-alpha.62
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.55
|
||||
github.com/openimsdk/tools v0.0.50-alpha.32
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.mongodb.org/mongo-driver v1.14.0
|
||||
google.golang.org/api v0.170.0
|
||||
google.golang.org/grpc v1.68.0
|
||||
google.golang.org/protobuf v1.35.1
|
||||
google.golang.org/grpc v1.66.2
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
@@ -42,36 +44,37 @@ require (
|
||||
github.com/spf13/viper v1.18.2
|
||||
github.com/stathat/consistent v1.0.0
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||
golang.org/x/sync v0.8.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.112.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.3.0 // indirect
|
||||
cloud.google.com/go/firestore v1.15.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.7 // indirect
|
||||
cloud.google.com/go/longrunning v0.5.5 // indirect
|
||||
cloud.google.com/go/storage v1.40.0 // indirect
|
||||
github.com/MicahParks/keyfunc v1.9.0 // indirect
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.23.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.25.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect
|
||||
github.com/aws/smithy-go v1.22.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 // indirect
|
||||
github.com/aws/smithy-go v1.17.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
@@ -172,16 +175,15 @@ require (
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/image v0.15.0 // indirect
|
||||
golang.org/x/net v0.29.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/oauth2 v0.21.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/appengine/v2 v2.0.2 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
gorm.io/gorm v1.25.8 // indirect
|
||||
stathat.com/c/consistent v1.0.0 // indirect
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM=
|
||||
cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4=
|
||||
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
|
||||
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8=
|
||||
cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk=
|
||||
cloud.google.com/go/iam v1.1.7 h1:z4VHOhwKLF/+UYXAJDFwGtNF0b6gjsW1Pk9Ml0U/IoM=
|
||||
@@ -21,42 +21,42 @@ github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x9
|
||||
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
|
||||
github.com/aws/aws-sdk-go-v2 v1.23.1 h1:qXaFsOOMA+HsZtX8WoCa+gJnbyW7qyFFBlPqvTSzbaI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.23.1/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 h1:ZY3108YtBNq96jNZTICHxN1gSBSbnvIdYwwqnvCV4Mc=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1/go.mod h1:t8PYl/6LzdAqsU4/9tz28V/kU+asFePvpOMkdul0gEQ=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.25.4 h1:r+X1x8QI6FEPdJDWCNBDZHyAcyFwSjHN8q8uuus+Axs=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.25.4/go.mod h1:8GTjImECskr7D88P/Nn9uM4M4rLY9i77hLJZgkZEWV8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.3 h1:8PeI2krzzjDJ5etmgaMiD1JswsrLrWvKKu/uBUtNy1g=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.3/go.mod h1:Kdh/okh+//vQ/AjEt81CjvkTo64+/zIE4OewP7RpfXk=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 h1:KehRNiVzIfAcj6gw98zotVbb/K67taJE0fkfgM6vzqU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5/go.mod h1:VhnExhw6uXy9QzetvpXDolo1/hjhx4u9qukBGkuUwjs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 h1:LAm3Ycm9HJfbSCd5I+wqC2S9Ej7FPrgr5CQoOljJZcE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4/go.mod h1:xEhvbJcyUf/31yfGSQBe01fukXwXJ0gxDp7rLfymWE0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 h1:4GV0kKZzUxiWxSVpn/9gwR0g21NF1Jsyduzo9rHgC/Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4/go.mod h1:dYvTNAggxDZy6y1AF7YDwXsPuHFy/VNEpEI/2dWK9IU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 h1:uR9lXYjdPX0xY+NhvaJ4dD8rpSRz5VY81ccIIoNG+lw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 h1:40Q4X5ebZruRtknEZH/bg91sT5pR853F7/1X9QRbI54=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4/go.mod h1:u77N7eEECzUv7F0xl2gcfK/vzc8wcjWobpy+DcrLJ5E=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 h1:rpkF4n0CyFcrJUG/rNNohoTmhtWlFTRI4BsZOh9PvLs=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1/go.mod h1:l9ymW25HOqymeU2m1gbUQ3rUIsTwKs8gYHXkqDQUhiI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 h1:6DRKQc+9cChgzL5gplRGusI5dBGeiEod4m/pmGbcX48=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4/go.mod h1:s8ORvrW4g4v7IvYKIAoBg17w3GQ+XuwXDXYrQ5SkzU0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 h1:rdovz3rEu0vZKbzoMYPTehp0E8veoE9AyfzqCr5Eeao=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4/go.mod h1:aYCGNjyUCUelhofxlZyj63srdxWUSsBSGg5l6MCuXuE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 h1:o3DcfCxGDIT20pTbVKVhp3vWXOj/VvgazNJvumWeYW0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4/go.mod h1:Uy0KVOxuTK2ne+/PKQ+VvEeWmjMMksE17k/2RK/r5oM=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 h1:1w11lfXOa8HoHoSlNtt4mqv/N3HmDOa+OnUH3Y9DHm8=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1/go.mod h1:dqJ5JBL0clzgHriH35Amx3LRFY6wNIPUX7QO/BerSBo=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg=
|
||||
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
|
||||
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 h1:CdsSOGlFF3Pn+koXOIpTtvX7st0IuGsZ8kJqcWMlX54=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.17.3/go.mod h1:oA6VjNsLll2eVuUoF2D+CMyORgNzPEW/3PyUdq6WQjI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 h1:cbRqFTVnJV+KRpwFl76GJdIZJKKCdTPnjUZ7uWh3pIU=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1/go.mod h1:hHL974p5auvXlZPIjJTblXJpbkfK4klBczlsEaMCGVY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 h1:yEvZ4neOQ/KpUqyR+X0ycUTW/kVRNR4nDZ38wStHGAA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.25.4/go.mod h1:feTnm2Tk/pJxdX+eooEsxvlvTWBvDm6CasRZ+JOs2IY=
|
||||
github.com/aws/smithy-go v1.17.0 h1:wWJD7LX6PBV6etBUwO0zElG0nWN9rUhp0WdYeHSHAaI=
|
||||
github.com/aws/smithy-go v1.17.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
@@ -319,10 +319,10 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
|
||||
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
||||
github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y=
|
||||
github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.68 h1:Ekn6S9Ftt12Xs/p9kJ39RDr2gSwIczz+MmSHQE4lAek=
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.68/go.mod h1:Iet+piS/jaS+kWWyj6EEr36mk4ISzIRYjoMSVA4dq2M=
|
||||
github.com/openimsdk/tools v0.0.50-alpha.62 h1:e/m1XL7+EXbkOoxr/En/612WcOPKOUHPBj0++gG6MuQ=
|
||||
github.com/openimsdk/tools v0.0.50-alpha.62/go.mod h1:JowL2jYr8tu4vcQe+5hJh4v3BtSx1T0CIS3pgU/Mw+U=
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.55 h1:9PPWPHvkFk3neBSbNr+IoOdKIFjxTvEqUfMK/TEq1+8=
|
||||
github.com/openimsdk/protocol v0.0.72-alpha.55/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8=
|
||||
github.com/openimsdk/tools v0.0.50-alpha.32 h1:JEsUFHFnaYg230TG+Ke3SUnaA2h44t4kABAzEdv5VZw=
|
||||
github.com/openimsdk/tools v0.0.50-alpha.32/go.mod h1:r5U6RbxcR4xhKb2fhTmKGC9Yt5LcErHBVt3lhXQIHSo=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
@@ -497,8 +497,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -565,8 +565,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
@@ -574,8 +574,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
|
||||
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -585,8 +585,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
|
||||
@@ -16,30 +16,29 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type AuthApi struct {
|
||||
Client auth.AuthClient
|
||||
}
|
||||
type AuthApi rpcclient.Auth
|
||||
|
||||
func NewAuthApi(client auth.AuthClient) AuthApi {
|
||||
return AuthApi{client}
|
||||
func NewAuthApi(client rpcclient.Auth) AuthApi {
|
||||
return AuthApi(client)
|
||||
}
|
||||
|
||||
func (o *AuthApi) GetAdminToken(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.GetAdminToken, o.Client)
|
||||
a2r.Call(auth.AuthClient.GetAdminToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *AuthApi) GetUserToken(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.GetUserToken, o.Client)
|
||||
a2r.Call(auth.AuthClient.GetUserToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *AuthApi) ParseToken(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.ParseToken, o.Client)
|
||||
a2r.Call(auth.AuthClient.ParseToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *AuthApi) ForceLogout(c *gin.Context) {
|
||||
a2r.Call(c, auth.AuthClient.ForceLogout, o.Client)
|
||||
a2r.Call(auth.AuthClient.ForceLogout, o.Client, c)
|
||||
}
|
||||
|
||||
@@ -16,58 +16,57 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type ConversationApi struct {
|
||||
Client conversation.ConversationClient
|
||||
}
|
||||
type ConversationApi rpcclient.Conversation
|
||||
|
||||
func NewConversationApi(client conversation.ConversationClient) ConversationApi {
|
||||
return ConversationApi{client}
|
||||
func NewConversationApi(client rpcclient.Conversation) ConversationApi {
|
||||
return ConversationApi(client)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetAllConversations(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetAllConversations, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetAllConversations, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetSortedConversationList(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetSortedConversationList, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetSortedConversationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetConversation(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetConversation, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetConversation, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetConversations(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetConversations, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetConversations, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) SetConversations(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.SetConversations, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.SetConversations, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetConversationOfflinePushUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetConversationOfflinePushUserIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetConversationOfflinePushUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetFullOwnerConversationIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetFullOwnerConversationIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetFullOwnerConversationIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetIncrementalConversation(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetIncrementalConversation, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetIncrementalConversation, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetOwnerConversation(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetOwnerConversation, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetOwnerConversation, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetNotNotifyConversationIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetNotNotifyConversationIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetNotNotifyConversationIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ConversationApi) GetPinnedConversationIDs(c *gin.Context) {
|
||||
a2r.Call(c, conversation.ConversationClient.GetPinnedConversationIDs, o.Client)
|
||||
a2r.Call(conversation.ConversationClient.GetPinnedConversationIDs, o.Client, c)
|
||||
}
|
||||
|
||||
+25
-26
@@ -17,100 +17,99 @@ package api
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type FriendApi struct {
|
||||
Client relation.FriendClient
|
||||
}
|
||||
type FriendApi rpcclient.Friend
|
||||
|
||||
func NewFriendApi(client relation.FriendClient) FriendApi {
|
||||
return FriendApi{client}
|
||||
func NewFriendApi(client rpcclient.Friend) FriendApi {
|
||||
return FriendApi(client)
|
||||
}
|
||||
|
||||
func (o *FriendApi) ApplyToAddFriend(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.ApplyToAddFriend, o.Client)
|
||||
a2r.Call(relation.FriendClient.ApplyToAddFriend, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) RespondFriendApply(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.RespondFriendApply, o.Client)
|
||||
a2r.Call(relation.FriendClient.RespondFriendApply, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) DeleteFriend(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.DeleteFriend, o.Client)
|
||||
a2r.Call(relation.FriendClient.DeleteFriend, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFriendApplyList(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationFriendsApplyTo, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationFriendsApplyTo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetDesignatedFriendsApply(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetDesignatedFriendsApply, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetDesignatedFriendsApply, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetSelfApplyList(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationFriendsApplyFrom, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationFriendsApplyFrom, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFriendList(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetDesignatedFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetDesignatedFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetDesignatedFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) SetFriendRemark(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.SetFriendRemark, o.Client)
|
||||
a2r.Call(relation.FriendClient.SetFriendRemark, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) AddBlack(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.AddBlack, o.Client)
|
||||
a2r.Call(relation.FriendClient.AddBlack, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetPaginationBlacks(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetPaginationBlacks, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetPaginationBlacks, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetSpecifiedBlacks(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetSpecifiedBlacks, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetSpecifiedBlacks, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) RemoveBlack(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.RemoveBlack, o.Client)
|
||||
a2r.Call(relation.FriendClient.RemoveBlack, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) ImportFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.ImportFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.ImportFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) IsFriend(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.IsFriend, o.Client)
|
||||
a2r.Call(relation.FriendClient.IsFriend, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFriendIDs(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetFriendIDs, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetFriendIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetSpecifiedFriendsInfo(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetSpecifiedFriendsInfo, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetSpecifiedFriendsInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) UpdateFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.UpdateFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.UpdateFriends, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetIncrementalFriends(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetIncrementalFriends, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetIncrementalFriends, o.Client, c)
|
||||
}
|
||||
|
||||
// GetIncrementalBlacks is temporarily unused.
|
||||
// Deprecated: This function is currently unused and may be removed in future versions.
|
||||
func (o *FriendApi) GetIncrementalBlacks(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetIncrementalBlacks, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetIncrementalBlacks, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *FriendApi) GetFullFriendUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, relation.FriendClient.GetFullFriendUserIDs, o.Client)
|
||||
a2r.Call(relation.FriendClient.GetFullFriendUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
+40
-41
@@ -16,152 +16,151 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type GroupApi struct {
|
||||
Client group.GroupClient
|
||||
}
|
||||
type GroupApi rpcclient.Group
|
||||
|
||||
func NewGroupApi(client group.GroupClient) GroupApi {
|
||||
return GroupApi{client}
|
||||
func NewGroupApi(client rpcclient.Group) GroupApi {
|
||||
return GroupApi(client)
|
||||
}
|
||||
|
||||
func (o *GroupApi) CreateGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.CreateGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.CreateGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) SetGroupInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.SetGroupInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.SetGroupInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) SetGroupInfoEx(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.SetGroupInfoEx, o.Client)
|
||||
a2r.Call(group.GroupClient.SetGroupInfoEx, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) JoinGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.JoinGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.JoinGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) QuitGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.QuitGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.QuitGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) ApplicationGroupResponse(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GroupApplicationResponse, o.Client)
|
||||
a2r.Call(group.GroupClient.GroupApplicationResponse, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) TransferGroupOwner(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.TransferGroupOwner, o.Client)
|
||||
a2r.Call(group.GroupClient.TransferGroupOwner, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetRecvGroupApplicationList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupApplicationList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupApplicationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetUserReqGroupApplicationList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetUserReqApplicationList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetUserReqApplicationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupUsersReqApplicationList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupUsersReqApplicationList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupUsersReqApplicationList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetSpecifiedUserGroupRequestInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetSpecifiedUserGroupRequestInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.GetSpecifiedUserGroupRequestInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupsInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupsInfo, o.Client)
|
||||
//a2r.Call(c, group.GroupClient.GetGroupsInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupsInfo))
|
||||
a2r.Call(group.GroupClient.GetGroupsInfo, o.Client, c)
|
||||
//a2r.Call(group.GroupClient.GetGroupsInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupsInfo))
|
||||
}
|
||||
|
||||
func (o *GroupApi) KickGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.KickGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.KickGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupMembersInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupMembersInfo, o.Client)
|
||||
//a2r.Call(c, group.GroupClient.GetGroupMembersInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupMembersInfo))
|
||||
a2r.Call(group.GroupClient.GetGroupMembersInfo, o.Client, c)
|
||||
//a2r.Call(group.GroupClient.GetGroupMembersInfo, o.Client, c, a2r.NewNilReplaceOption(group.GroupClient.GetGroupMembersInfo))
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupMemberList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupMemberList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupMemberList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) InviteUserToGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.InviteUserToGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.InviteUserToGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetJoinedGroupList(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetJoinedGroupList, o.Client)
|
||||
a2r.Call(group.GroupClient.GetJoinedGroupList, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) DismissGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.DismissGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.DismissGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) MuteGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.MuteGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.MuteGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) CancelMuteGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.CancelMuteGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.CancelMuteGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) MuteGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.MuteGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.MuteGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) CancelMuteGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.CancelMuteGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.CancelMuteGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) SetGroupMemberInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.SetGroupMemberInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.SetGroupMemberInfo, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupAbstractInfo(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupAbstractInfo, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupAbstractInfo, o.Client, c)
|
||||
}
|
||||
|
||||
// func (g *Group) SetGroupMemberNickname(c *gin.Context) {
|
||||
// a2r.Call(c, group.GroupClient.SetGroupMemberNickname, g.userClient)
|
||||
// a2r.Call(group.GroupClient.SetGroupMemberNickname, g.userClient, c)
|
||||
//}
|
||||
//
|
||||
// func (g *Group) GetGroupAllMemberList(c *gin.Context) {
|
||||
// a2r.Call(c, group.GroupClient.GetGroupAllMember, g.userClient)
|
||||
// a2r.Call(group.GroupClient.GetGroupAllMember, g.userClient, c)
|
||||
//}
|
||||
|
||||
func (o *GroupApi) GroupCreateCount(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GroupCreateCount, o.Client)
|
||||
a2r.Call(group.GroupClient.GroupCreateCount, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroups(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroups, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroups, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetGroupMemberUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetGroupMemberUserIDs, o.Client)
|
||||
a2r.Call(group.GroupClient.GetGroupMemberUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetIncrementalJoinGroup(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetIncrementalJoinGroup, o.Client)
|
||||
a2r.Call(group.GroupClient.GetIncrementalJoinGroup, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetIncrementalGroupMember(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetIncrementalGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.GetIncrementalGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetIncrementalGroupMemberBatch(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.BatchGetIncrementalGroupMember, o.Client)
|
||||
a2r.Call(group.GroupClient.BatchGetIncrementalGroupMember, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetFullGroupMemberUserIDs(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetFullGroupMemberUserIDs, o.Client)
|
||||
a2r.Call(group.GroupClient.GetFullGroupMemberUserIDs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *GroupApi) GetFullJoinGroupIDs(c *gin.Context) {
|
||||
a2r.Call(c, group.GroupClient.GetFullJoinGroupIDs, o.Client)
|
||||
a2r.Call(group.GroupClient.GetFullJoinGroupIDs, o.Client, c)
|
||||
}
|
||||
|
||||
@@ -62,10 +62,7 @@ func Start(ctx context.Context, index int, config *Config) error {
|
||||
prometheusPort int
|
||||
)
|
||||
|
||||
router, err := newGinRouter(ctx, client, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
router := newGinRouter(client, config)
|
||||
if config.API.Prometheus.Enable {
|
||||
go func() {
|
||||
prometheusPort, err = datautil.GetElemByIndex(config.API.Prometheus.Ports, index)
|
||||
|
||||
+49
-36
@@ -2,17 +2,17 @@ package jssdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"sort"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/protocol/jssdk"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -20,23 +20,22 @@ const (
|
||||
defaultGetActiveConversation = 100
|
||||
)
|
||||
|
||||
func NewJSSdkApi(userClient *rpcli.UserClient, relationClient *rpcli.RelationClient, groupClient *rpcli.GroupClient,
|
||||
conversationClient *rpcli.ConversationClient, msgClient *rpcli.MsgClient) *JSSdk {
|
||||
func NewJSSdkApi(user user.UserClient, friend relation.FriendClient, group group.GroupClient, msg msg.MsgClient, conv conversation.ConversationClient) *JSSdk {
|
||||
return &JSSdk{
|
||||
userClient: userClient,
|
||||
relationClient: relationClient,
|
||||
groupClient: groupClient,
|
||||
conversationClient: conversationClient,
|
||||
msgClient: msgClient,
|
||||
user: user,
|
||||
friend: friend,
|
||||
group: group,
|
||||
msg: msg,
|
||||
conv: conv,
|
||||
}
|
||||
}
|
||||
|
||||
type JSSdk struct {
|
||||
userClient *rpcli.UserClient
|
||||
relationClient *rpcli.RelationClient
|
||||
groupClient *rpcli.GroupClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
msgClient *rpcli.MsgClient
|
||||
user user.UserClient
|
||||
friend relation.FriendClient
|
||||
group group.GroupClient
|
||||
msg msg.MsgClient
|
||||
conv conversation.ConversationClient
|
||||
}
|
||||
|
||||
func (x *JSSdk) GetActiveConversations(c *gin.Context) {
|
||||
@@ -68,11 +67,11 @@ func (x *JSSdk) fillConversations(ctx context.Context, conversations []*jssdk.Co
|
||||
groupMap map[string]*sdkws.GroupInfo
|
||||
)
|
||||
if len(userIDs) > 0 {
|
||||
users, err := x.userClient.GetUsersInfo(ctx, userIDs)
|
||||
users, err := field(ctx, x.user.GetDesignateUsers, &user.GetDesignateUsersReq{UserIDs: userIDs}, (*user.GetDesignateUsersResp).GetUsersInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
friends, err := x.relationClient.GetFriendsInfo(ctx, conversations[0].Conversation.OwnerUserID, userIDs)
|
||||
friends, err := field(ctx, x.friend.GetFriendInfo, &relation.GetFriendInfoReq{OwnerUserID: conversations[0].Conversation.OwnerUserID, FriendUserIDs: userIDs}, (*relation.GetFriendInfoResp).GetFriendInfos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -80,11 +79,11 @@ func (x *JSSdk) fillConversations(ctx context.Context, conversations []*jssdk.Co
|
||||
friendMap = datautil.SliceToMap(friends, (*relation.FriendInfoOnly).GetFriendUserID)
|
||||
}
|
||||
if len(groupIDs) > 0 {
|
||||
groups, err := x.groupClient.GetGroupsInfo(ctx, groupIDs)
|
||||
resp, err := x.group.GetGroupsInfo(ctx, &group.GetGroupsInfoReq{GroupIDs: groupIDs})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupMap = datautil.SliceToMap(groups, (*sdkws.GroupInfo).GetGroupID)
|
||||
groupMap = datautil.SliceToMap(resp.GroupInfos, (*sdkws.GroupInfo).GetGroupID)
|
||||
}
|
||||
for _, c := range conversations {
|
||||
if c.Conversation.GroupID == "" {
|
||||
@@ -102,18 +101,21 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
req.Count = defaultGetActiveConversation
|
||||
}
|
||||
req.OwnerUserID = mcontext.GetOpUserID(ctx)
|
||||
conversationIDs, err := x.conversationClient.GetConversationIDs(ctx, req.OwnerUserID)
|
||||
conversationIDs, err := field(ctx, x.conv.GetConversationIDs,
|
||||
&conversation.GetConversationIDsReq{UserID: req.OwnerUserID}, (*conversation.GetConversationIDsResp).GetConversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(conversationIDs) == 0 {
|
||||
return &jssdk.GetActiveConversationsResp{}, nil
|
||||
}
|
||||
readSeq, err := x.msgClient.GetHasReadSeqs(ctx, conversationIDs, req.OwnerUserID)
|
||||
readSeq, err := field(ctx, x.msg.GetHasReadSeqs,
|
||||
&msg.GetHasReadSeqsReq{UserID: req.OwnerUserID, ConversationIDs: conversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
activeConversation, err := x.msgClient.GetActiveConversation(ctx, conversationIDs)
|
||||
activeConversation, err := field(ctx, x.msg.GetActiveConversation,
|
||||
&msg.GetActiveConversationReq{ConversationIDs: conversationIDs}, (*msg.GetActiveConversationResp).GetConversations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -124,7 +126,8 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
Conversation: activeConversation,
|
||||
}
|
||||
if len(activeConversation) > 1 {
|
||||
pinnedConversationIDs, err := x.conversationClient.GetPinnedConversationIDs(ctx, req.OwnerUserID)
|
||||
pinnedConversationIDs, err := field(ctx, x.conv.GetPinnedConversationIDs,
|
||||
&conversation.GetPinnedConversationIDsReq{UserID: req.OwnerUserID}, (*conversation.GetPinnedConversationIDsResp).GetConversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -132,18 +135,25 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
}
|
||||
sort.Sort(&sortConversations)
|
||||
sortList := sortConversations.Top(int(req.Count))
|
||||
conversations, err := x.conversationClient.GetConversations(ctx, datautil.Slice(sortList, func(c *msg.ActiveConversation) string {
|
||||
return c.ConversationID
|
||||
}), req.OwnerUserID)
|
||||
conversations, err := field(ctx, x.conv.GetConversations,
|
||||
&conversation.GetConversationsReq{
|
||||
OwnerUserID: req.OwnerUserID,
|
||||
ConversationIDs: datautil.Slice(sortList, func(c *msg.ActiveConversation) string {
|
||||
return c.ConversationID
|
||||
})}, (*conversation.GetConversationsResp).GetConversations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgs, err := x.msgClient.GetSeqMessage(ctx, req.OwnerUserID, datautil.Slice(sortList, func(c *msg.ActiveConversation) *msg.ConversationSeqs {
|
||||
return &msg.ConversationSeqs{
|
||||
ConversationID: c.ConversationID,
|
||||
Seqs: []int64{c.MaxSeq},
|
||||
}
|
||||
}))
|
||||
msgs, err := field(ctx, x.msg.GetSeqMessage,
|
||||
&msg.GetSeqMessageReq{
|
||||
UserID: req.OwnerUserID,
|
||||
Conversations: datautil.Slice(sortList, func(c *msg.ActiveConversation) *msg.ConversationSeqs {
|
||||
return &msg.ConversationSeqs{
|
||||
ConversationID: c.ConversationID,
|
||||
Seqs: []int64{c.MaxSeq},
|
||||
}
|
||||
}),
|
||||
}, (*msg.GetSeqMessageResp).GetMsgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -185,7 +195,7 @@ func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActive
|
||||
|
||||
func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversationsReq) (*jssdk.GetConversationsResp, error) {
|
||||
req.OwnerUserID = mcontext.GetOpUserID(ctx)
|
||||
conversations, err := x.conversationClient.GetConversations(ctx, req.ConversationIDs, req.OwnerUserID)
|
||||
conversations, err := field(ctx, x.conv.GetConversations, &conversation.GetConversationsReq{OwnerUserID: req.OwnerUserID, ConversationIDs: req.ConversationIDs}, (*conversation.GetConversationsResp).GetConversations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -195,11 +205,13 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
|
||||
req.ConversationIDs = datautil.Slice(conversations, func(c *conversation.Conversation) string {
|
||||
return c.ConversationID
|
||||
})
|
||||
maxSeqs, err := x.msgClient.GetMaxSeqs(ctx, req.ConversationIDs)
|
||||
maxSeqs, err := field(ctx, x.msg.GetMaxSeqs,
|
||||
&msg.GetMaxSeqsReq{ConversationIDs: req.ConversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
readSeqs, err := x.msgClient.GetHasReadSeqs(ctx, req.ConversationIDs, req.OwnerUserID)
|
||||
readSeqs, err := field(ctx, x.msg.GetHasReadSeqs,
|
||||
&msg.GetHasReadSeqsReq{UserID: req.OwnerUserID, ConversationIDs: req.ConversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -214,7 +226,8 @@ func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversation
|
||||
}
|
||||
var msgs map[string]*sdkws.PullMsgs
|
||||
if len(conversationSeqs) > 0 {
|
||||
msgs, err = x.msgClient.GetSeqMessage(ctx, req.OwnerUserID, conversationSeqs)
|
||||
msgs, err = field(ctx, x.msg.GetSeqMessage,
|
||||
&msg.GetSeqMessageReq{UserID: req.OwnerUserID, Conversations: conversationSeqs}, (*msg.GetSeqMessageResp).GetMsgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+34
-30
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/apistruct"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -37,14 +37,16 @@ import (
|
||||
)
|
||||
|
||||
type MessageApi struct {
|
||||
Client msg.MsgClient
|
||||
userClient *rpcli.UserClient
|
||||
imAdminUserID []string
|
||||
*rpcclient.Message
|
||||
validate *validator.Validate
|
||||
userRpcClient *rpcclient.UserRpcClient
|
||||
imAdminUserID []string
|
||||
}
|
||||
|
||||
func NewMessageApi(client msg.MsgClient, userClient *rpcli.UserClient, imAdminUserID []string) MessageApi {
|
||||
return MessageApi{Client: client, userClient: userClient, imAdminUserID: imAdminUserID, validate: validator.New()}
|
||||
func NewMessageApi(msgRpcClient *rpcclient.Message, userRpcClient *rpcclient.User,
|
||||
imAdminUserID []string) MessageApi {
|
||||
return MessageApi{Message: msgRpcClient, validate: validator.New(),
|
||||
userRpcClient: rpcclient.NewUserRpcClientByUser(userRpcClient), imAdminUserID: imAdminUserID}
|
||||
}
|
||||
|
||||
func (*MessageApi) SetOptions(options map[string]bool, value bool) {
|
||||
@@ -106,51 +108,51 @@ func (m *MessageApi) newUserSendMsgReq(_ *gin.Context, params *apistruct.SendMsg
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetSeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetMaxSeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetMaxSeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) PullMsgBySeqs(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.PullMessageBySeqs, m.Client)
|
||||
a2r.Call(msg.MsgClient.PullMessageBySeqs, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) RevokeMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.RevokeMsg, m.Client)
|
||||
a2r.Call(msg.MsgClient.RevokeMsg, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) MarkMsgsAsRead(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.MarkMsgsAsRead, m.Client)
|
||||
a2r.Call(msg.MsgClient.MarkMsgsAsRead, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) MarkConversationAsRead(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.MarkConversationAsRead, m.Client)
|
||||
a2r.Call(msg.MsgClient.MarkConversationAsRead, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetConversationsHasReadAndMaxSeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetConversationsHasReadAndMaxSeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetConversationsHasReadAndMaxSeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) SetConversationHasReadSeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.SetConversationHasReadSeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.SetConversationHasReadSeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) ClearConversationsMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.ClearConversationsMsg, m.Client)
|
||||
a2r.Call(msg.MsgClient.ClearConversationsMsg, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) UserClearAllMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.UserClearAllMsg, m.Client)
|
||||
a2r.Call(msg.MsgClient.UserClearAllMsg, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) DeleteMsgs(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.DeleteMsgs, m.Client)
|
||||
a2r.Call(msg.MsgClient.DeleteMsgs, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) DeleteMsgPhysicalBySeq(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.DeleteMsgPhysicalBySeq, m.Client)
|
||||
a2r.Call(msg.MsgClient.DeleteMsgPhysicalBySeq, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) DeleteMsgPhysical(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.DeleteMsgPhysical, m.Client)
|
||||
a2r.Call(msg.MsgClient.DeleteMsgPhysical, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendMsgReq *msg.SendMsgReq, err error) {
|
||||
@@ -171,10 +173,12 @@ func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendM
|
||||
data = apistruct.AtElem{}
|
||||
case constant.Custom:
|
||||
data = apistruct.CustomElem{}
|
||||
case constant.Stream:
|
||||
data = apistruct.StreamMsgElem{}
|
||||
case constant.OANotification:
|
||||
data = apistruct.OANotificationElem{}
|
||||
req.SessionType = constant.NotificationChatType
|
||||
if err = m.userClient.GetNotificationByID(c, req.SendID); err != nil {
|
||||
if err = m.userRpcClient.GetNotificationByID(c, req.SendID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
@@ -308,10 +312,10 @@ func (m *MessageApi) BatchSendMsg(c *gin.Context) {
|
||||
|
||||
var recvIDs []string
|
||||
if req.IsSendAll {
|
||||
var pageNumber int32 = 1
|
||||
const showNumber = 500
|
||||
pageNumber := 1
|
||||
showNumber := 500
|
||||
for {
|
||||
recvIDsPart, err := m.userClient.GetAllUserIDs(c, pageNumber, showNumber)
|
||||
recvIDsPart, err := m.userRpcClient.GetAllUserIDs(c, int32(pageNumber), int32(showNumber))
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
@@ -349,33 +353,33 @@ func (m *MessageApi) BatchSendMsg(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (m *MessageApi) CheckMsgIsSendSuccess(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetSendMsgStatus, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetSendMsgStatus, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetUsersOnlineStatus(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetSendMsgStatus, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetSendMsgStatus, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetActiveUser(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetActiveUser, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetActiveUser, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetActiveGroup(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetActiveGroup, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetActiveGroup, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) SearchMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.SearchMessage, m.Client)
|
||||
a2r.Call(msg.MsgClient.SearchMessage, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetServerTime(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetServerTime, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetServerTime, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) GetStreamMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetServerTime, m.Client)
|
||||
a2r.Call(msg.MsgClient.GetStreamMsg, m.Client, c)
|
||||
}
|
||||
|
||||
func (m *MessageApi) AppendStreamMsg(c *gin.Context) {
|
||||
a2r.Call(c, msg.MsgClient.GetServerTime, m.Client)
|
||||
a2r.Call(msg.MsgClient.AppendStreamMsg, m.Client, c)
|
||||
}
|
||||
|
||||
+40
-71
@@ -1,18 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
pbAuth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/internal/api/jssdk"
|
||||
|
||||
@@ -24,8 +13,12 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/tools/apiresp"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
@@ -55,42 +48,23 @@ func prommetricsGin() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, config *Config) (*gin.Engine, error) {
|
||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
func newGinRouter(disCov discovery.SvcDiscoveryRegistry, config *Config) *gin.Engine {
|
||||
disCov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||
authConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.New()
|
||||
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
||||
_ = v.RegisterValidation("required_if", RequiredIf)
|
||||
}
|
||||
// init rpc client here
|
||||
userRpc := rpcclient.NewUser(disCov, config.Share.RpcRegisterName.User, config.Share.RpcRegisterName.MessageGateway,
|
||||
config.Share.IMAdminUserID)
|
||||
groupRpc := rpcclient.NewGroup(disCov, config.Share.RpcRegisterName.Group)
|
||||
friendRpc := rpcclient.NewFriend(disCov, config.Share.RpcRegisterName.Friend)
|
||||
messageRpc := rpcclient.NewMessage(disCov, config.Share.RpcRegisterName.Msg)
|
||||
conversationRpc := rpcclient.NewConversation(disCov, config.Share.RpcRegisterName.Conversation)
|
||||
authRpc := rpcclient.NewAuth(disCov, config.Share.RpcRegisterName.Auth)
|
||||
thirdRpc := rpcclient.NewThird(disCov, config.Share.RpcRegisterName.Third, config.API.Prometheus.GrafanaURL)
|
||||
switch config.API.Api.CompressionLevel {
|
||||
case NoCompression:
|
||||
case DefaultCompression:
|
||||
@@ -100,12 +74,12 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
case BestSpeed:
|
||||
r.Use(gzip.Gzip(gzip.BestSpeed))
|
||||
}
|
||||
r.Use(prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(),
|
||||
mw.GinParseOperationID(), GinParseToken(rpcli.NewAuthClient(authConn)))
|
||||
|
||||
u := NewUserApi(user.NewUserClient(userConn), client, config.Share.RpcRegisterName)
|
||||
r.Use(prommetricsGin(), gin.RecoveryWithWriter(gin.DefaultErrorWriter, mw.GinPanicErr), mw.CorsHandler(), mw.GinParseOperationID(), GinParseToken(authRpc))
|
||||
u := NewUserApi(*userRpc)
|
||||
m := NewMessageApi(messageRpc, userRpc, config.Share.IMAdminUserID)
|
||||
j := jssdk.NewJSSdkApi(userRpc.Client, friendRpc.Client, groupRpc.Client, messageRpc.Client, conversationRpc.Client)
|
||||
userRouterGroup := r.Group("/user")
|
||||
{
|
||||
userRouterGroup := r.Group("/user")
|
||||
userRouterGroup.POST("/user_register", u.UserRegister)
|
||||
userRouterGroup.POST("/update_user_info", u.UpdateUserInfo)
|
||||
userRouterGroup.POST("/update_user_info_ex", u.UpdateUserInfoEx)
|
||||
@@ -131,9 +105,9 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
userRouterGroup.POST("/search_notification_account", u.SearchNotificationAccount)
|
||||
}
|
||||
// friend routing group
|
||||
friendRouterGroup := r.Group("/friend")
|
||||
{
|
||||
f := NewFriendApi(relation.NewFriendClient(friendConn))
|
||||
friendRouterGroup := r.Group("/friend")
|
||||
f := NewFriendApi(*friendRpc)
|
||||
friendRouterGroup.POST("/delete_friend", f.DeleteFriend)
|
||||
friendRouterGroup.POST("/get_friend_apply_list", f.GetFriendApplyList)
|
||||
friendRouterGroup.POST("/get_designated_friend_apply", f.GetDesignatedFriendsApply)
|
||||
@@ -156,10 +130,9 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
friendRouterGroup.POST("/get_incremental_friends", f.GetIncrementalFriends)
|
||||
friendRouterGroup.POST("/get_full_friend_user_ids", f.GetFullFriendUserIDs)
|
||||
}
|
||||
|
||||
g := NewGroupApi(group.NewGroupClient(groupConn))
|
||||
g := NewGroupApi(*groupRpc)
|
||||
groupRouterGroup := r.Group("/group")
|
||||
{
|
||||
groupRouterGroup := r.Group("/group")
|
||||
groupRouterGroup.POST("/create_group", g.CreateGroup)
|
||||
groupRouterGroup.POST("/set_group_info", g.SetGroupInfo)
|
||||
groupRouterGroup.POST("/set_group_info_ex", g.SetGroupInfoEx)
|
||||
@@ -193,19 +166,18 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
groupRouterGroup.POST("/get_full_join_group_ids", g.GetFullJoinGroupIDs)
|
||||
}
|
||||
// certificate
|
||||
authRouterGroup := r.Group("/auth")
|
||||
{
|
||||
a := NewAuthApi(pbAuth.NewAuthClient(authConn))
|
||||
authRouterGroup := r.Group("/auth")
|
||||
a := NewAuthApi(*authRpc)
|
||||
authRouterGroup.POST("/get_admin_token", a.GetAdminToken)
|
||||
authRouterGroup.POST("/get_user_token", a.GetUserToken)
|
||||
authRouterGroup.POST("/parse_token", a.ParseToken)
|
||||
authRouterGroup.POST("/force_logout", a.ForceLogout)
|
||||
|
||||
}
|
||||
// Third service
|
||||
thirdGroup := r.Group("/third")
|
||||
{
|
||||
t := NewThirdApi(third.NewThirdClient(thirdConn), config.API.Prometheus.GrafanaURL)
|
||||
thirdGroup := r.Group("/third")
|
||||
t := NewThirdApi(*thirdRpc)
|
||||
thirdGroup.GET("/prometheus", t.GetPrometheus)
|
||||
thirdGroup.POST("/fcm_update_token", t.FcmUpdateToken)
|
||||
thirdGroup.POST("/set_app_badge", t.SetAppBadge)
|
||||
@@ -228,9 +200,8 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
objectGroup.GET("/*name", t.ObjectRedirect)
|
||||
}
|
||||
// Message
|
||||
m := NewMessageApi(msg.NewMsgClient(msgConn), rpcli.NewUserClient(userConn), config.Share.IMAdminUserID)
|
||||
msgGroup := r.Group("/msg")
|
||||
{
|
||||
msgGroup := r.Group("/msg")
|
||||
msgGroup.POST("/newest_seq", m.GetSeq)
|
||||
msgGroup.POST("/search_msg", m.SearchMsg)
|
||||
msgGroup.POST("/send_msg", m.SendMessage)
|
||||
@@ -251,11 +222,13 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
msgGroup.POST("/batch_send_msg", m.BatchSendMsg)
|
||||
msgGroup.POST("/check_msg_is_send_success", m.CheckMsgIsSendSuccess)
|
||||
msgGroup.POST("/get_server_time", m.GetServerTime)
|
||||
msgGroup.POST("/get_stream_msg", m.GetStreamMsg)
|
||||
msgGroup.POST("/append_stream_msg", m.AppendStreamMsg)
|
||||
}
|
||||
// Conversation
|
||||
conversationGroup := r.Group("/conversation")
|
||||
{
|
||||
c := NewConversationApi(conversation.NewConversationClient(conversationConn))
|
||||
conversationGroup := r.Group("/conversation")
|
||||
c := NewConversationApi(*conversationRpc)
|
||||
conversationGroup.POST("/get_sorted_conversation_list", c.GetSortedConversationList)
|
||||
conversationGroup.POST("/get_all_conversations", c.GetAllConversations)
|
||||
conversationGroup.POST("/get_conversation", c.GetConversation)
|
||||
@@ -269,26 +242,22 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co
|
||||
conversationGroup.POST("/get_pinned_conversation_ids", c.GetPinnedConversationIDs)
|
||||
}
|
||||
|
||||
statisticsGroup := r.Group("/statistics")
|
||||
{
|
||||
statisticsGroup := r.Group("/statistics")
|
||||
statisticsGroup.POST("/user/register", u.UserRegisterCount)
|
||||
statisticsGroup.POST("/user/active", m.GetActiveUser)
|
||||
statisticsGroup.POST("/group/create", g.GroupCreateCount)
|
||||
statisticsGroup.POST("/group/active", m.GetActiveGroup)
|
||||
}
|
||||
|
||||
{
|
||||
j := jssdk.NewJSSdkApi(rpcli.NewUserClient(userConn), rpcli.NewRelationClient(friendConn),
|
||||
rpcli.NewGroupClient(groupConn), rpcli.NewConversationClient(conversationConn), rpcli.NewMsgClient(msgConn))
|
||||
jssdk := r.Group("/jssdk")
|
||||
jssdk.POST("/get_conversations", j.GetConversations)
|
||||
jssdk.POST("/get_active_conversations", j.GetActiveConversations)
|
||||
}
|
||||
jssdk := r.Group("/jssdk")
|
||||
jssdk.POST("/get_conversations", j.GetConversations)
|
||||
jssdk.POST("/get_active_conversations", j.GetActiveConversations)
|
||||
|
||||
return r, nil
|
||||
return r
|
||||
}
|
||||
|
||||
func GinParseToken(authClient *rpcli.AuthClient) gin.HandlerFunc {
|
||||
func GinParseToken(authRPC *rpcclient.Auth) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
switch c.Request.Method {
|
||||
case http.MethodPost:
|
||||
@@ -306,7 +275,7 @@ func GinParseToken(authClient *rpcli.AuthClient) gin.HandlerFunc {
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
resp, err := authClient.ParseToken(c, token)
|
||||
resp, err := authRPC.ParseToken(c, token)
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
c.Abort()
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright © 2023 OpenIM. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
)
|
||||
|
||||
type StatisticsApi rpcclient.User
|
||||
|
||||
func NewStatisticsApi(client rpcclient.User) StatisticsApi {
|
||||
return StatisticsApi(client)
|
||||
}
|
||||
|
||||
func (s *StatisticsApi) UserRegister(c *gin.Context) {
|
||||
a2r.Call(user.UserClient.UserRegisterCount, s.Client, c)
|
||||
}
|
||||
+17
-19
@@ -24,27 +24,25 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
)
|
||||
|
||||
type ThirdApi struct {
|
||||
GrafanaUrl string
|
||||
Client third.ThirdClient
|
||||
}
|
||||
type ThirdApi rpcclient.Third
|
||||
|
||||
func NewThirdApi(client third.ThirdClient, grafanaUrl string) ThirdApi {
|
||||
return ThirdApi{Client: client, GrafanaUrl: grafanaUrl}
|
||||
func NewThirdApi(client rpcclient.Third) ThirdApi {
|
||||
return ThirdApi(client)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) FcmUpdateToken(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.FcmUpdateToken, o.Client)
|
||||
a2r.Call(third.ThirdClient.FcmUpdateToken, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) SetAppBadge(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.SetAppBadge, o.Client)
|
||||
a2r.Call(third.ThirdClient.SetAppBadge, o.Client, c)
|
||||
}
|
||||
|
||||
// #################### s3 ####################
|
||||
@@ -79,44 +77,44 @@ func setURLPrefix(c *gin.Context, urlPrefix *string) error {
|
||||
}
|
||||
|
||||
func (o *ThirdApi) PartLimit(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.PartLimit, o.Client)
|
||||
a2r.Call(third.ThirdClient.PartLimit, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) PartSize(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.PartSize, o.Client)
|
||||
a2r.Call(third.ThirdClient.PartSize, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) InitiateMultipartUpload(c *gin.Context) {
|
||||
opt := setURLPrefixOption(third.ThirdClient.InitiateMultipartUpload, func(req *third.InitiateMultipartUploadReq) error {
|
||||
return setURLPrefix(c, &req.UrlPrefix)
|
||||
})
|
||||
a2r.Call(c, third.ThirdClient.InitiateMultipartUpload, o.Client, opt)
|
||||
a2r.Call(third.ThirdClient.InitiateMultipartUpload, o.Client, c, opt)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) AuthSign(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.AuthSign, o.Client)
|
||||
a2r.Call(third.ThirdClient.AuthSign, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) CompleteMultipartUpload(c *gin.Context) {
|
||||
opt := setURLPrefixOption(third.ThirdClient.CompleteMultipartUpload, func(req *third.CompleteMultipartUploadReq) error {
|
||||
return setURLPrefix(c, &req.UrlPrefix)
|
||||
})
|
||||
a2r.Call(c, third.ThirdClient.CompleteMultipartUpload, o.Client, opt)
|
||||
a2r.Call(third.ThirdClient.CompleteMultipartUpload, o.Client, c, opt)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) AccessURL(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.AccessURL, o.Client)
|
||||
a2r.Call(third.ThirdClient.AccessURL, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) InitiateFormData(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.InitiateFormData, o.Client)
|
||||
a2r.Call(third.ThirdClient.InitiateFormData, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) CompleteFormData(c *gin.Context) {
|
||||
opt := setURLPrefixOption(third.ThirdClient.CompleteFormData, func(req *third.CompleteFormDataReq) error {
|
||||
return setURLPrefix(c, &req.UrlPrefix)
|
||||
})
|
||||
a2r.Call(c, third.ThirdClient.CompleteFormData, o.Client, opt)
|
||||
a2r.Call(third.ThirdClient.CompleteFormData, o.Client, c, opt)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
|
||||
@@ -158,15 +156,15 @@ func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
|
||||
|
||||
// #################### logs ####################.
|
||||
func (o *ThirdApi) UploadLogs(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.UploadLogs, o.Client)
|
||||
a2r.Call(third.ThirdClient.UploadLogs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) DeleteLogs(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.DeleteLogs, o.Client)
|
||||
a2r.Call(third.ThirdClient.DeleteLogs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) SearchLogs(c *gin.Context) {
|
||||
a2r.Call(c, third.ThirdClient.SearchLogs, o.Client)
|
||||
a2r.Call(third.ThirdClient.SearchLogs, o.Client, c)
|
||||
}
|
||||
|
||||
func (o *ThirdApi) GetPrometheus(c *gin.Context) {
|
||||
|
||||
+26
-31
@@ -16,57 +16,52 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/a2r"
|
||||
"github.com/openimsdk/tools/apiresp"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
type UserApi struct {
|
||||
Client user.UserClient
|
||||
discov discovery.SvcDiscoveryRegistry
|
||||
config config.RpcRegisterName
|
||||
}
|
||||
type UserApi rpcclient.User
|
||||
|
||||
func NewUserApi(client user.UserClient, discov discovery.SvcDiscoveryRegistry, config config.RpcRegisterName) UserApi {
|
||||
return UserApi{Client: client, discov: discov, config: config}
|
||||
func NewUserApi(client rpcclient.User) UserApi {
|
||||
return UserApi(client)
|
||||
}
|
||||
|
||||
func (u *UserApi) UserRegister(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UserRegister, u.Client)
|
||||
a2r.Call(user.UserClient.UserRegister, u.Client, c)
|
||||
}
|
||||
|
||||
// UpdateUserInfo is deprecated. Use UpdateUserInfoEx
|
||||
func (u *UserApi) UpdateUserInfo(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UpdateUserInfo, u.Client)
|
||||
a2r.Call(user.UserClient.UpdateUserInfo, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) UpdateUserInfoEx(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UpdateUserInfoEx, u.Client)
|
||||
a2r.Call(user.UserClient.UpdateUserInfoEx, u.Client, c)
|
||||
}
|
||||
func (u *UserApi) SetGlobalRecvMessageOpt(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.SetGlobalRecvMessageOpt, u.Client)
|
||||
a2r.Call(user.UserClient.SetGlobalRecvMessageOpt, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) GetUsersPublicInfo(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetDesignateUsers, u.Client)
|
||||
a2r.Call(user.UserClient.GetDesignateUsers, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) GetAllUsersID(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetAllUserID, u.Client)
|
||||
a2r.Call(user.UserClient.GetAllUserID, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) AccountCheck(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.AccountCheck, u.Client)
|
||||
a2r.Call(user.UserClient.AccountCheck, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) GetUsers(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetPaginationUsers, u.Client)
|
||||
a2r.Call(user.UserClient.GetPaginationUsers, u.Client, c)
|
||||
}
|
||||
|
||||
// GetUsersOnlineStatus Get user online status.
|
||||
@@ -76,7 +71,7 @@ func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
}
|
||||
conns, err := u.discov.GetConns(c, u.config.MessageGateway)
|
||||
conns, err := u.Discov.GetConns(c, u.MessageGateWayRpcName)
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
@@ -127,7 +122,7 @@ func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (u *UserApi) UserRegisterCount(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UserRegisterCount, u.Client)
|
||||
a2r.Call(user.UserClient.UserRegisterCount, u.Client, c)
|
||||
}
|
||||
|
||||
// GetUsersOnlineTokenDetail Get user online token details.
|
||||
@@ -140,7 +135,7 @@ func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) {
|
||||
apiresp.GinError(c, errs.ErrArgs.WithDetail(err.Error()).Wrap())
|
||||
return
|
||||
}
|
||||
conns, err := u.discov.GetConns(c, u.config.MessageGateway)
|
||||
conns, err := u.Discov.GetConns(c, u.MessageGateWayRpcName)
|
||||
if err != nil {
|
||||
apiresp.GinError(c, err)
|
||||
return
|
||||
@@ -193,52 +188,52 @@ func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) {
|
||||
|
||||
// SubscriberStatus Presence status of subscribed users.
|
||||
func (u *UserApi) SubscriberStatus(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.SubscribeOrCancelUsersStatus, u.Client)
|
||||
a2r.Call(user.UserClient.SubscribeOrCancelUsersStatus, u.Client, c)
|
||||
}
|
||||
|
||||
// GetUserStatus Get the online status of the user.
|
||||
func (u *UserApi) GetUserStatus(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetUserStatus, u.Client)
|
||||
a2r.Call(user.UserClient.GetUserStatus, u.Client, c)
|
||||
}
|
||||
|
||||
// GetSubscribeUsersStatus Get the online status of subscribers.
|
||||
func (u *UserApi) GetSubscribeUsersStatus(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.GetSubscribeUsersStatus, u.Client)
|
||||
a2r.Call(user.UserClient.GetSubscribeUsersStatus, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandAdd user general function add.
|
||||
func (u *UserApi) ProcessUserCommandAdd(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandAdd, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandAdd, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandDelete user general function delete.
|
||||
func (u *UserApi) ProcessUserCommandDelete(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandDelete, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandDelete, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandUpdate user general function update.
|
||||
func (u *UserApi) ProcessUserCommandUpdate(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandUpdate, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandUpdate, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandGet user general function get.
|
||||
func (u *UserApi) ProcessUserCommandGet(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandGet, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c)
|
||||
}
|
||||
|
||||
// ProcessUserCommandGet user general function get all.
|
||||
func (u *UserApi) ProcessUserCommandGetAll(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.ProcessUserCommandGetAll, u.Client)
|
||||
a2r.Call(user.UserClient.ProcessUserCommandGetAll, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) AddNotificationAccount(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.AddNotificationAccount, u.Client)
|
||||
a2r.Call(user.UserClient.AddNotificationAccount, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) UpdateNotificationAccountInfo(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.UpdateNotificationAccountInfo, u.Client)
|
||||
a2r.Call(user.UserClient.UpdateNotificationAccountInfo, u.Client, c)
|
||||
}
|
||||
|
||||
func (u *UserApi) SearchNotificationAccount(c *gin.Context) {
|
||||
a2r.Call(c, user.UserClient.SearchNotificationAccount, u.Client)
|
||||
a2r.Call(user.UserClient.SearchNotificationAccount, u.Client, c)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/openimsdk/tools/mw"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -131,7 +133,7 @@ func (c *Client) readMessage() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
c.closedErr = ErrPanic
|
||||
log.ZPanic(c.ctx, "socket have panic err:", errs.ErrPanic(r))
|
||||
fmt.Println("socket have panic err:", r, string(debug.Stack()))
|
||||
}
|
||||
c.close()
|
||||
}()
|
||||
@@ -376,7 +378,7 @@ func (c *Client) activeHeartbeat(ctx context.Context) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.ZPanic(ctx, "activeHeartbeat Panic", errs.ErrPanic(r))
|
||||
mw.PanicStackToLog(ctx, r)
|
||||
}
|
||||
}()
|
||||
log.ZDebug(ctx, "server initiative send heartbeat start.")
|
||||
|
||||
@@ -16,12 +16,12 @@ package msggateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -35,15 +35,9 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) InitServer(ctx context.Context, config *Config, disCov discovery.SvcDiscoveryRegistry, server *grpc.Server) error {
|
||||
userConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.userClient = rpcli.NewUserClient(userConn)
|
||||
if err := s.LongConnServer.SetDiscoveryRegistry(ctx, disCov, config); err != nil {
|
||||
return err
|
||||
}
|
||||
s.LongConnServer.SetDiscoveryRegistry(disCov, config)
|
||||
msggateway.RegisterMsgGatewayServer(server, s)
|
||||
s.userRcp = rpcclient.NewUserRpcClient(disCov, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
if s.ready != nil {
|
||||
return s.ready(s)
|
||||
}
|
||||
@@ -62,22 +56,22 @@ func (s *Server) Start(ctx context.Context, index int, conf *Config) error {
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
msggateway.UnimplementedMsgGatewayServer
|
||||
rpcPort int
|
||||
LongConnServer LongConnServer
|
||||
config *Config
|
||||
pushTerminal map[int]struct{}
|
||||
ready func(srv *Server) error
|
||||
userRcp rpcclient.UserRpcClient
|
||||
queue *memamq.MemoryQueue
|
||||
userClient *rpcli.UserClient
|
||||
}
|
||||
|
||||
func (s *Server) SetLongConnServer(LongConnServer LongConnServer) {
|
||||
s.LongConnServer = LongConnServer
|
||||
}
|
||||
|
||||
func NewServer(longConnServer LongConnServer, conf *Config, ready func(srv *Server) error) *Server {
|
||||
func NewServer(rpcPort int, longConnServer LongConnServer, conf *Config, ready func(srv *Server) error) *Server {
|
||||
s := &Server{
|
||||
rpcPort: rpcPort,
|
||||
LongConnServer: longConnServer,
|
||||
pushTerminal: make(map[int]struct{}),
|
||||
config: conf,
|
||||
|
||||
@@ -41,6 +41,10 @@ func Start(ctx context.Context, index int, conf *Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rpcPort, err := datautil.GetElemByIndex(conf.MsgGateway.RPC.Ports, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rdb, err := redisutil.NewRedisClient(ctx, conf.RedisConfig.Build())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -53,10 +57,9 @@ func Start(ctx context.Context, index int, conf *Config) error {
|
||||
WithMessageMaxMsgLength(conf.MsgGateway.LongConnSvr.WebsocketMaxMsgLen),
|
||||
)
|
||||
|
||||
hubServer := NewServer(longServer, conf, func(srv *Server) error {
|
||||
var err error
|
||||
longServer.online, err = rpccache.NewOnlineCache(srv.userClient, nil, rdb, false, longServer.subscriberUserOnlineStatusChanges)
|
||||
return err
|
||||
hubServer := NewServer(rpcPort, longServer, conf, func(srv *Server) error {
|
||||
longServer.online, _ = rpccache.NewOnlineCache(srv.userRcp, nil, rdb, false, longServer.subscriberUserOnlineStatusChanges)
|
||||
return nil
|
||||
})
|
||||
|
||||
go longServer.ChangeOnlineStatus(4)
|
||||
|
||||
@@ -17,15 +17,17 @@ package msggateway
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"sync"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/push"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/utils/jsonutil"
|
||||
)
|
||||
@@ -100,33 +102,34 @@ func (r *Resp) String() string {
|
||||
}
|
||||
|
||||
type MessageHandler interface {
|
||||
GetSeq(ctx context.Context, data *Req) ([]byte, error)
|
||||
SendMessage(ctx context.Context, data *Req) ([]byte, error)
|
||||
SendSignalMessage(ctx context.Context, data *Req) ([]byte, error)
|
||||
PullMessageBySeqList(ctx context.Context, data *Req) ([]byte, error)
|
||||
GetConversationsHasReadAndMaxSeq(ctx context.Context, data *Req) ([]byte, error)
|
||||
GetSeqMessage(ctx context.Context, data *Req) ([]byte, error)
|
||||
UserLogout(ctx context.Context, data *Req) ([]byte, error)
|
||||
SetUserDeviceBackground(ctx context.Context, data *Req) ([]byte, bool, error)
|
||||
GetSeq(context context.Context, data *Req) ([]byte, error)
|
||||
SendMessage(context context.Context, data *Req) ([]byte, error)
|
||||
SendSignalMessage(context context.Context, data *Req) ([]byte, error)
|
||||
PullMessageBySeqList(context context.Context, data *Req) ([]byte, error)
|
||||
GetConversationsHasReadAndMaxSeq(context context.Context, data *Req) ([]byte, error)
|
||||
GetSeqMessage(context context.Context, data *Req) ([]byte, error)
|
||||
UserLogout(context context.Context, data *Req) ([]byte, error)
|
||||
SetUserDeviceBackground(context context.Context, data *Req) ([]byte, bool, error)
|
||||
}
|
||||
|
||||
var _ MessageHandler = (*GrpcHandler)(nil)
|
||||
|
||||
type GrpcHandler struct {
|
||||
validate *validator.Validate
|
||||
msgClient *rpcli.MsgClient
|
||||
pushClient *rpcli.PushMsgServiceClient
|
||||
msgRpcClient *rpcclient.MessageRpcClient
|
||||
pushClient *rpcclient.PushRpcClient
|
||||
validate *validator.Validate
|
||||
}
|
||||
|
||||
func NewGrpcHandler(validate *validator.Validate, msgClient *rpcli.MsgClient, pushClient *rpcli.PushMsgServiceClient) *GrpcHandler {
|
||||
func NewGrpcHandler(validate *validator.Validate, client discovery.SvcDiscoveryRegistry, rpcRegisterName *config.RpcRegisterName) *GrpcHandler {
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, rpcRegisterName.Msg)
|
||||
pushRpcClient := rpcclient.NewPushRpcClient(client, rpcRegisterName.Push)
|
||||
return &GrpcHandler{
|
||||
validate: validate,
|
||||
msgClient: msgClient,
|
||||
pushClient: pushClient,
|
||||
msgRpcClient: &msgRpcClient,
|
||||
pushClient: &pushRpcClient, validate: validate,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
req := sdkws.GetMaxSeqReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "GetSeq: error unmarshaling request", "action", "unmarshal", "dataType", "GetMaxSeqReq")
|
||||
@@ -134,7 +137,7 @@ func (g *GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
if err := g.validate.Struct(&req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "GetSeq: validation failed", "action", "validate", "dataType", "GetMaxSeqReq")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.GetMaxSeq(ctx, &req)
|
||||
resp, err := g.msgRpcClient.GetMaxSeq(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -147,7 +150,7 @@ func (g *GrpcHandler) GetSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
|
||||
// SendMessage handles the sending of messages through gRPC. It unmarshals the request data,
|
||||
// validates the message, and then sends it using the message RPC client.
|
||||
func (g *GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
var msgData sdkws.MsgData
|
||||
if err := proto.Unmarshal(data.Data, &msgData); err != nil {
|
||||
return nil, errs.WrapMsg(err, "SendMessage: error unmarshaling message data", "action", "unmarshal", "dataType", "MsgData")
|
||||
@@ -158,7 +161,7 @@ func (g *GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error
|
||||
}
|
||||
|
||||
req := msg.SendMsgReq{MsgData: &msgData}
|
||||
resp, err := g.msgClient.MsgClient.SendMsg(ctx, &req)
|
||||
resp, err := g.msgRpcClient.SendMsg(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -171,8 +174,8 @@ func (g *GrpcHandler) SendMessage(ctx context.Context, data *Req) ([]byte, error
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) SendSignalMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
resp, err := g.msgClient.MsgClient.SendMsg(ctx, nil)
|
||||
func (g GrpcHandler) SendSignalMessage(context context.Context, data *Req) ([]byte, error) {
|
||||
resp, err := g.msgRpcClient.SendMsg(context, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -183,7 +186,7 @@ func (g *GrpcHandler) SendSignalMessage(ctx context.Context, data *Req) ([]byte,
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) PullMessageBySeqList(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) PullMessageBySeqList(context context.Context, data *Req) ([]byte, error) {
|
||||
req := sdkws.PullMessageBySeqsReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "err proto unmarshal", "action", "unmarshal", "dataType", "PullMessageBySeqsReq")
|
||||
@@ -191,7 +194,7 @@ func (g *GrpcHandler) PullMessageBySeqList(ctx context.Context, data *Req) ([]by
|
||||
if err := g.validate.Struct(data); err != nil {
|
||||
return nil, errs.WrapMsg(err, "validation failed", "action", "validate", "dataType", "PullMessageBySeqsReq")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.PullMessageBySeqs(ctx, &req)
|
||||
resp, err := g.msgRpcClient.PullMessageBySeqList(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -202,7 +205,7 @@ func (g *GrpcHandler) PullMessageBySeqList(ctx context.Context, data *Req) ([]by
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) GetConversationsHasReadAndMaxSeq(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) GetConversationsHasReadAndMaxSeq(context context.Context, data *Req) ([]byte, error) {
|
||||
req := msg.GetConversationsHasReadAndMaxSeqReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "err proto unmarshal", "action", "unmarshal", "dataType", "GetConversationsHasReadAndMaxSeq")
|
||||
@@ -210,7 +213,7 @@ func (g *GrpcHandler) GetConversationsHasReadAndMaxSeq(ctx context.Context, data
|
||||
if err := g.validate.Struct(data); err != nil {
|
||||
return nil, errs.WrapMsg(err, "validation failed", "action", "validate", "dataType", "GetConversationsHasReadAndMaxSeq")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.GetConversationsHasReadAndMaxSeq(ctx, &req)
|
||||
resp, err := g.msgRpcClient.GetConversationsHasReadAndMaxSeq(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -221,7 +224,7 @@ func (g *GrpcHandler) GetConversationsHasReadAndMaxSeq(ctx context.Context, data
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) GetSeqMessage(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) GetSeqMessage(context context.Context, data *Req) ([]byte, error) {
|
||||
req := msg.GetSeqMessageReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "error unmarshaling request", "action", "unmarshal", "dataType", "GetSeqMessage")
|
||||
@@ -229,7 +232,7 @@ func (g *GrpcHandler) GetSeqMessage(ctx context.Context, data *Req) ([]byte, err
|
||||
if err := g.validate.Struct(data); err != nil {
|
||||
return nil, errs.WrapMsg(err, "validation failed", "action", "validate", "dataType", "GetSeqMessage")
|
||||
}
|
||||
resp, err := g.msgClient.MsgClient.GetSeqMessage(ctx, &req)
|
||||
resp, err := g.msgRpcClient.GetSeqMessage(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -240,12 +243,12 @@ func (g *GrpcHandler) GetSeqMessage(ctx context.Context, data *Req) ([]byte, err
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) UserLogout(ctx context.Context, data *Req) ([]byte, error) {
|
||||
func (g GrpcHandler) UserLogout(context context.Context, data *Req) ([]byte, error) {
|
||||
req := push.DelUserPushTokenReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, errs.WrapMsg(err, "error unmarshaling request", "action", "unmarshal", "dataType", "DelUserPushTokenReq")
|
||||
}
|
||||
resp, err := g.pushClient.PushMsgServiceClient.DelUserPushToken(ctx, &req)
|
||||
resp, err := g.pushClient.DelUserPushToken(context, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -256,7 +259,7 @@ func (g *GrpcHandler) UserLogout(ctx context.Context, data *Req) ([]byte, error)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (g *GrpcHandler) SetUserDeviceBackground(ctx context.Context, data *Req) ([]byte, bool, error) {
|
||||
func (g GrpcHandler) SetUserDeviceBackground(_ context.Context, data *Req) ([]byte, bool, error) {
|
||||
req := sdkws.SetAppBackgroundStatusReq{}
|
||||
if err := proto.Unmarshal(data.Data, &req); err != nil {
|
||||
return nil, false, errs.WrapMsg(err, "error unmarshaling request", "action", "unmarshal", "dataType", "SetAppBackgroundStatusReq")
|
||||
|
||||
@@ -87,7 +87,7 @@ func (ws *WsServer) ChangeOnlineStatus(concurrent int) {
|
||||
opIdCtx := mcontext.SetOperationID(context.Background(), operationIDPrefix+strconv.FormatInt(count.Add(1), 10))
|
||||
ctx, cancel := context.WithTimeout(opIdCtx, time.Second*5)
|
||||
defer cancel()
|
||||
if err := ws.userClient.SetUserOnlineStatus(ctx, req); err != nil {
|
||||
if _, err := ws.userClient.Client.SetUserOnlineStatus(ctx, req); err != nil {
|
||||
log.ZError(ctx, "update user online status", err)
|
||||
}
|
||||
for _, ss := range req.Status {
|
||||
|
||||
@@ -3,7 +3,10 @@ package msggateway
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
pbAuth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -12,15 +15,12 @@ import (
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
pbAuth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
@@ -31,7 +31,7 @@ type LongConnServer interface {
|
||||
GetUserAllCons(userID string) ([]*Client, bool)
|
||||
GetUserPlatformCons(userID string, platform int) ([]*Client, bool, bool)
|
||||
Validate(s any) error
|
||||
SetDiscoveryRegistry(ctx context.Context, client discovery.SvcDiscoveryRegistry, config *Config) error
|
||||
SetDiscoveryRegistry(client discovery.SvcDiscoveryRegistry, config *Config)
|
||||
KickUserConn(client *Client) error
|
||||
UnRegister(c *Client)
|
||||
SetKickHandlerInfo(i *kickHandler)
|
||||
@@ -56,13 +56,13 @@ type WsServer struct {
|
||||
handshakeTimeout time.Duration
|
||||
writeBufferSize int
|
||||
validate *validator.Validate
|
||||
userClient *rpcclient.UserRpcClient
|
||||
authClient *rpcclient.Auth
|
||||
disCov discovery.SvcDiscoveryRegistry
|
||||
Compressor
|
||||
//Encoder
|
||||
MessageHandler
|
||||
webhookClient *webhook.Client
|
||||
userClient *rpcli.UserClient
|
||||
authClient *rpcli.AuthClient
|
||||
}
|
||||
|
||||
type kickHandler struct {
|
||||
@@ -71,28 +71,12 @@ type kickHandler struct {
|
||||
newClient *Client
|
||||
}
|
||||
|
||||
func (ws *WsServer) SetDiscoveryRegistry(ctx context.Context, disCov discovery.SvcDiscoveryRegistry, config *Config) error {
|
||||
userConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pushConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Push)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := disCov.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.userClient = rpcli.NewUserClient(userConn)
|
||||
ws.authClient = rpcli.NewAuthClient(authConn)
|
||||
ws.MessageHandler = NewGrpcHandler(ws.validate, rpcli.NewMsgClient(msgConn), rpcli.NewPushMsgServiceClient(pushConn))
|
||||
func (ws *WsServer) SetDiscoveryRegistry(disCov discovery.SvcDiscoveryRegistry, config *Config) {
|
||||
ws.MessageHandler = NewGrpcHandler(ws.validate, disCov, &config.Share.RpcRegisterName)
|
||||
u := rpcclient.NewUserRpcClient(disCov, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
ws.authClient = rpcclient.NewAuth(disCov, config.Share.RpcRegisterName.Auth)
|
||||
ws.userClient = &u
|
||||
ws.disCov = disCov
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (ws *WsServer) SetUserOnlineStatus(ctx context.Context, client *Client, status int32) {
|
||||
@@ -327,7 +311,7 @@ func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClients []*Clien
|
||||
[]string{newClient.ctx.GetOperationID(), newClient.ctx.GetUserID(),
|
||||
constant.PlatformIDToName(newClient.PlatformID), newClient.ctx.GetConnID()},
|
||||
)
|
||||
if err := ws.authClient.KickTokens(ctx, kickTokens); err != nil {
|
||||
if _, err := ws.authClient.KickTokens(ctx, kickTokens); err != nil {
|
||||
log.ZWarn(newClient.ctx, "kickTokens err", err)
|
||||
}
|
||||
}
|
||||
@@ -354,12 +338,7 @@ func (ws *WsServer) multiTerminalLoginChecker(clientOK bool, oldClients []*Clien
|
||||
[]string{newClient.ctx.GetOperationID(), newClient.ctx.GetUserID(),
|
||||
constant.PlatformIDToName(newClient.PlatformID), newClient.ctx.GetConnID()},
|
||||
)
|
||||
req := &pbAuth.InvalidateTokenReq{
|
||||
PreservedToken: newClient.token,
|
||||
UserID: newClient.UserID,
|
||||
PlatformID: int32(newClient.PlatformID),
|
||||
}
|
||||
if err := ws.authClient.InvalidateToken(ctx, req); err != nil {
|
||||
if _, err := ws.authClient.InvalidateToken(ctx, newClient.token, newClient.UserID, newClient.PlatformID); err != nil {
|
||||
log.ZWarn(newClient.ctx, "InvalidateToken err", err, "userID", newClient.UserID,
|
||||
"platformID", newClient.PlatformID)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
discRegister "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mw"
|
||||
@@ -81,11 +82,11 @@ func Start(ctx context.Context, index int, config *Config) error {
|
||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||
|
||||
msgModel := redis.NewMsgCache(rdb)
|
||||
msgDocModel, err := mgo.NewMsgMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgModel := redis.NewMsgCache(rdb, msgDocModel)
|
||||
seqConversation, err := mgo.NewSeqConversationMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -100,7 +101,9 @@ func Start(ctx context.Context, index int, config *Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
historyCH, err := NewOnlineHistoryRedisConsumerHandler(ctx, client, config, msgTransferDatabase)
|
||||
conversationRpcClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
historyCH, err := NewOnlineHistoryRedisConsumerHandler(&config.KafkaConfig, msgTransferDatabase, &conversationRpcClient, &groupRpcClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -133,6 +136,11 @@ func (m *MsgTransfer) Start(index int, config *Config) error {
|
||||
|
||||
if config.MsgTransfer.Prometheus.Enable {
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
mw.PanicStackToLog(m.ctx, r)
|
||||
}
|
||||
}()
|
||||
prometheusPort, err := datautil.GetElemByIndex(config.MsgTransfer.Prometheus.Ports, index)
|
||||
if err != nil {
|
||||
netErr = err
|
||||
|
||||
@@ -18,22 +18,21 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/tools/mw"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/tools/batcher"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbconv "github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
@@ -70,32 +69,21 @@ type OnlineHistoryRedisConsumerHandler struct {
|
||||
redisMessageBatches *batcher.Batcher[sarama.ConsumerMessage]
|
||||
|
||||
msgTransferDatabase controller.MsgTransferDatabase
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient
|
||||
groupRpcClient *rpcclient.GroupRpcClient
|
||||
conversationUserHasReadChan chan *userHasReadSeq
|
||||
wg sync.WaitGroup
|
||||
|
||||
groupClient *rpcli.GroupClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
}
|
||||
|
||||
func NewOnlineHistoryRedisConsumerHandler(ctx context.Context, client discovery.SvcDiscoveryRegistry, config *Config, database controller.MsgTransferDatabase) (*OnlineHistoryRedisConsumerHandler, error) {
|
||||
kafkaConf := config.KafkaConfig
|
||||
func NewOnlineHistoryRedisConsumerHandler(kafkaConf *config.Kafka, database controller.MsgTransferDatabase,
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient) (*OnlineHistoryRedisConsumerHandler, error) {
|
||||
historyConsumerGroup, err := kafka.NewMConsumerGroup(kafkaConf.Build(), kafkaConf.ToRedisGroupID, []string{kafkaConf.ToRedisTopic}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var och OnlineHistoryRedisConsumerHandler
|
||||
och.msgTransferDatabase = database
|
||||
och.conversationUserHasReadChan = make(chan *userHasReadSeq, hasReadChanBuffer)
|
||||
och.groupClient = rpcli.NewGroupClient(groupConn)
|
||||
och.conversationClient = rpcli.NewConversationClient(conversationConn)
|
||||
och.wg.Add(1)
|
||||
|
||||
b := batcher.New[sarama.ConsumerMessage](
|
||||
@@ -115,21 +103,25 @@ func NewOnlineHistoryRedisConsumerHandler(ctx context.Context, client discovery.
|
||||
}
|
||||
b.Do = och.do
|
||||
och.redisMessageBatches = b
|
||||
och.conversationRpcClient = conversationRpcClient
|
||||
och.groupRpcClient = groupRpcClient
|
||||
och.historyConsumerGroup = historyConsumerGroup
|
||||
|
||||
return &och, nil
|
||||
return &och, err
|
||||
}
|
||||
func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, channelID int, val *batcher.Msg[sarama.ConsumerMessage]) {
|
||||
ctx = mcontext.WithTriggerIDContext(ctx, val.TriggerID())
|
||||
ctxMessages := och.parseConsumerMessages(ctx, val.Val())
|
||||
ctx = withAggregationCtx(ctx, ctxMessages)
|
||||
log.ZInfo(ctx, "msg arrived channel", "channel id", channelID, "msgList length", len(ctxMessages), "key", val.Key())
|
||||
log.ZInfo(ctx, "msg arrived channel", "channel id", channelID, "msgList length", len(ctxMessages),
|
||||
"key", val.Key())
|
||||
och.doSetReadSeq(ctx, ctxMessages)
|
||||
|
||||
storageMsgList, notStorageMsgList, storageNotificationList, notStorageNotificationList :=
|
||||
och.categorizeMessageLists(ctxMessages)
|
||||
log.ZDebug(ctx, "number of categorized messages", "storageMsgList", len(storageMsgList), "notStorageMsgList",
|
||||
len(notStorageMsgList), "storageNotificationList", len(storageNotificationList), "notStorageNotificationList", len(notStorageNotificationList))
|
||||
len(notStorageMsgList), "storageNotificationList", len(storageNotificationList), "notStorageNotificationList",
|
||||
len(notStorageNotificationList))
|
||||
|
||||
conversationIDMsg := msgprocessor.GetChatConversationIDByMsg(ctxMessages[0].message)
|
||||
conversationIDNotification := msgprocessor.GetNotificationConversationIDByMsg(ctxMessages[0].message)
|
||||
@@ -293,27 +285,22 @@ func (och *OnlineHistoryRedisConsumerHandler) handleMsg(ctx context.Context, key
|
||||
case constant.ReadGroupChatType:
|
||||
log.ZDebug(ctx, "group chat first create conversation", "conversationID",
|
||||
conversationID)
|
||||
|
||||
userIDs, err := och.groupClient.GetGroupMemberUserIDs(ctx, msg.GroupID)
|
||||
userIDs, err := och.groupRpcClient.GetGroupMemberIDs(ctx, msg.GroupID)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "get group member ids error", err, "conversationID",
|
||||
conversationID)
|
||||
} else {
|
||||
log.ZInfo(ctx, "GetGroupMemberIDs end")
|
||||
|
||||
if err := och.conversationClient.CreateGroupChatConversations(ctx, msg.GroupID, userIDs); err != nil {
|
||||
if err := och.conversationRpcClient.GroupChatFirstCreateConversation(ctx,
|
||||
msg.GroupID, userIDs); err != nil {
|
||||
log.ZWarn(ctx, "single chat first create conversation error", err,
|
||||
"conversationID", conversationID)
|
||||
}
|
||||
}
|
||||
case constant.SingleChatType, constant.NotificationChatType:
|
||||
req := &pbconv.CreateSingleChatConversationsReq{
|
||||
RecvID: msg.RecvID,
|
||||
SendID: msg.SendID,
|
||||
ConversationID: conversationID,
|
||||
ConversationType: msg.SessionType,
|
||||
}
|
||||
if err := och.conversationClient.CreateSingleChatConversations(ctx, req); err != nil {
|
||||
if err := och.conversationRpcClient.SingleChatFirstCreateConversation(ctx, msg.RecvID,
|
||||
msg.SendID, conversationID, msg.SessionType); err != nil {
|
||||
log.ZWarn(ctx, "single chat or notification first create conversation error", err,
|
||||
"conversationID", conversationID, "sessionType", msg.SessionType)
|
||||
}
|
||||
@@ -362,7 +349,7 @@ func (och *OnlineHistoryRedisConsumerHandler) handleNotification(ctx context.Con
|
||||
func (och *OnlineHistoryRedisConsumerHandler) HandleUserHasReadSeqMessages(ctx context.Context) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.ZPanic(ctx, "HandleUserHasReadSeqMessages Panic", errs.ErrPanic(r))
|
||||
mw.PanicStackToLog(ctx, r)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -77,13 +77,27 @@ func (mc *OnlineHistoryMongoConsumerHandler) handleChatWs2Mongo(ctx context.Cont
|
||||
for _, msg := range msgFromMQ.MsgData {
|
||||
seqs = append(seqs, msg.Seq)
|
||||
}
|
||||
err = mc.msgTransferDatabase.DeleteMessagesFromCache(ctx, msgFromMQ.ConversationID, seqs)
|
||||
if err != nil {
|
||||
log.ZError(
|
||||
ctx,
|
||||
"remove cache msg from redis err",
|
||||
err,
|
||||
"msg",
|
||||
msgFromMQ.MsgData,
|
||||
"conversationID",
|
||||
msgFromMQ.ConversationID,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (*OnlineHistoryMongoConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
|
||||
func (*OnlineHistoryMongoConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
func (*OnlineHistoryMongoConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||
|
||||
func (mc *OnlineHistoryMongoConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error { // an instance in the consumer group
|
||||
func (mc *OnlineHistoryMongoConsumerHandler) ConsumeClaim(
|
||||
sess sarama.ConsumerGroupSession,
|
||||
claim sarama.ConsumerGroupClaim,
|
||||
) error { // an instance in the consumer group
|
||||
log.ZDebug(context.Background(), "online new session msg come", "highWaterMarkOffset",
|
||||
claim.HighWaterMarkOffset(), "topic", claim.Topic(), "partition", claim.Partition())
|
||||
for msg := range claim.Messages() {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
)
|
||||
|
||||
type pushServer struct {
|
||||
pbpush.UnimplementedPushMsgServiceServer
|
||||
database controller.PushDatabase
|
||||
disCov discovery.SvcDiscoveryRegistry
|
||||
offlinePusher offlinepush.OfflinePusher
|
||||
@@ -32,8 +31,11 @@ type Config struct {
|
||||
LocalCacheConfig config.LocalCache
|
||||
Discovery config.Discovery
|
||||
FcmConfigPath string
|
||||
}
|
||||
|
||||
runTimeEnv string
|
||||
func (p pushServer) PushMsg(ctx context.Context, req *pbpush.PushMsgReq) (*pbpush.PushMsgResp, error) {
|
||||
//todo reserved Interface
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p pushServer) DelUserPushToken(ctx context.Context,
|
||||
@@ -57,7 +59,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
|
||||
database := controller.NewPushDatabase(cacheModel, &config.KafkaConfig)
|
||||
|
||||
consumer, err := NewConsumerHandler(ctx, config, database, offlinePusher, rdb, client)
|
||||
consumer, err := NewConsumerHandler(config, database, offlinePusher, rdb, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package push
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/util/conversationutil"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
@@ -40,15 +41,14 @@ type ConsumerHandler struct {
|
||||
onlineCache *rpccache.OnlineCache
|
||||
groupLocalCache *rpccache.GroupLocalCache
|
||||
conversationLocalCache *rpccache.ConversationLocalCache
|
||||
msgRpcClient rpcclient.MessageRpcClient
|
||||
conversationRpcClient rpcclient.ConversationRpcClient
|
||||
groupRpcClient rpcclient.GroupRpcClient
|
||||
webhookClient *webhook.Client
|
||||
config *Config
|
||||
userClient *rpcli.UserClient
|
||||
groupClient *rpcli.GroupClient
|
||||
msgClient *rpcli.MsgClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
}
|
||||
|
||||
func NewConsumerHandler(ctx context.Context, config *Config, database controller.PushDatabase, offlinePusher offlinepush.OfflinePusher, rdb redis.UniversalClient,
|
||||
func NewConsumerHandler(config *Config, database controller.PushDatabase, offlinePusher offlinepush.OfflinePusher, rdb redis.UniversalClient,
|
||||
client discovery.SvcDiscoveryRegistry) (*ConsumerHandler, error) {
|
||||
var consumerHandler ConsumerHandler
|
||||
var err error
|
||||
@@ -57,35 +57,20 @@ func NewConsumerHandler(ctx context.Context, config *Config, database controller
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
consumerHandler.userClient = rpcli.NewUserClient(userConn)
|
||||
consumerHandler.groupClient = rpcli.NewGroupClient(groupConn)
|
||||
consumerHandler.msgClient = rpcli.NewMsgClient(msgConn)
|
||||
consumerHandler.conversationClient = rpcli.NewConversationClient(conversationConn)
|
||||
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
|
||||
consumerHandler.offlinePusher = offlinePusher
|
||||
consumerHandler.onlinePusher = NewOnlinePusher(client, config)
|
||||
consumerHandler.groupLocalCache = rpccache.NewGroupLocalCache(consumerHandler.groupClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.conversationLocalCache = rpccache.NewConversationLocalCache(consumerHandler.conversationClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.groupRpcClient = rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
consumerHandler.groupLocalCache = rpccache.NewGroupLocalCache(consumerHandler.groupRpcClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.msgRpcClient = rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
consumerHandler.conversationRpcClient = rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
consumerHandler.conversationLocalCache = rpccache.NewConversationLocalCache(consumerHandler.conversationRpcClient, &config.LocalCacheConfig, rdb)
|
||||
consumerHandler.webhookClient = webhook.NewWebhookClient(config.WebhooksConfig.URL)
|
||||
consumerHandler.config = config
|
||||
consumerHandler.pushDatabase = database
|
||||
consumerHandler.onlineCache, err = rpccache.NewOnlineCache(consumerHandler.userClient, consumerHandler.groupLocalCache, rdb, config.RpcConfig.FullUserCache, nil)
|
||||
consumerHandler.onlineCache, err = rpccache.NewOnlineCache(userRpcClient, consumerHandler.groupLocalCache, rdb, config.RpcConfig.FullUserCache, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -342,7 +327,7 @@ func (c *ConsumerHandler) groupMessagesHandler(ctx context.Context, groupID stri
|
||||
ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUserID[0])
|
||||
}
|
||||
defer func(groupID string) {
|
||||
if err := c.groupClient.DismissGroup(ctx, groupID, true); err != nil {
|
||||
if err = c.groupRpcClient.DismissGroup(ctx, groupID); err != nil {
|
||||
log.ZError(ctx, "DismissGroup Notification clear members", err, "groupID", groupID)
|
||||
}
|
||||
}(groupID)
|
||||
@@ -368,7 +353,10 @@ func (c *ConsumerHandler) offlinePushMsg(ctx context.Context, msg *sdkws.MsgData
|
||||
|
||||
func (c *ConsumerHandler) filterGroupMessageOfflinePush(ctx context.Context, groupID string, msg *sdkws.MsgData,
|
||||
offlinePushUserIDs []string) (userIDs []string, err error) {
|
||||
needOfflinePushUserIDs, err := c.conversationClient.GetConversationOfflinePushUserIDs(ctx, conversationutil.GenGroupConversationID(groupID), offlinePushUserIDs)
|
||||
|
||||
//todo local cache Obtain the difference set through local comparison.
|
||||
needOfflinePushUserIDs, err := c.conversationRpcClient.GetConversationOfflinePushUserIDs(
|
||||
ctx, conversationutil.GenGroupConversationID(groupID), offlinePushUserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -422,11 +410,11 @@ func (c *ConsumerHandler) getOfflinePushInfos(msg *sdkws.MsgData) (title, conten
|
||||
|
||||
func (c *ConsumerHandler) DeleteMemberAndSetConversationSeq(ctx context.Context, groupID string, userIDs []string) error {
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := c.msgClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
maxSeq, err := c.msgRpcClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.conversationClient.SetConversationMaxSeq(ctx, conversationID, userIDs, maxSeq)
|
||||
return c.conversationRpcClient.SetConversationMaxSeq(ctx, userIDs, conversationID, maxSeq)
|
||||
}
|
||||
|
||||
func unmarshalNotificationElem(bytes []byte, t any) error {
|
||||
@@ -434,5 +422,6 @@ func unmarshalNotificationElem(bytes []byte, t any) error {
|
||||
if err := json.Unmarshal(bytes, ¬ification); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal([]byte(notification.Detail), t)
|
||||
}
|
||||
|
||||
+14
-15
@@ -17,7 +17,6 @@ package auth
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
redis2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
@@ -29,6 +28,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
pbauth "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msggateway"
|
||||
@@ -40,11 +40,10 @@ import (
|
||||
)
|
||||
|
||||
type authServer struct {
|
||||
pbauth.UnimplementedAuthServer
|
||||
authDatabase controller.AuthDatabase
|
||||
userRpcClient *rpcclient.UserRpcClient
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry
|
||||
config *Config
|
||||
userClient *rpcli.UserClient
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -59,11 +58,9 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
pbauth.RegisterAuthServer(server, &authServer{
|
||||
userRpcClient: &userRpcClient,
|
||||
RegisterCenter: client,
|
||||
authDatabase: controller.NewAuthDatabase(
|
||||
redis2.NewTokenCacheModel(rdb, config.RpcConfig.TokenPolicy.Expire),
|
||||
@@ -72,8 +69,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
config.Share.MultiLogin,
|
||||
config.Share.IMAdminUserID,
|
||||
),
|
||||
config: config,
|
||||
userClient: rpcli.NewUserClient(userConn),
|
||||
config: config,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -89,7 +85,7 @@ func (s *authServer) GetAdminToken(ctx context.Context, req *pbauth.GetAdminToke
|
||||
|
||||
}
|
||||
|
||||
if err := s.userClient.CheckUser(ctx, []string{req.UserID}); err != nil {
|
||||
if _, err := s.userRpcClient.GetUserInfo(ctx, req.UserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -118,7 +114,7 @@ func (s *authServer) GetUserToken(ctx context.Context, req *pbauth.GetUserTokenR
|
||||
if authverify.IsManagerUserID(req.UserID, s.config.Share.IMAdminUserID) {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("don't get Admin token")
|
||||
}
|
||||
if err := s.userClient.CheckUser(ctx, []string{req.UserID}); err != nil {
|
||||
if _, err := s.userRpcClient.GetUserInfo(ctx, req.UserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
token, err := s.authDatabase.CreateToken(ctx, req.UserID, int(req.PlatformID))
|
||||
@@ -133,7 +129,7 @@ func (s *authServer) GetUserToken(ctx context.Context, req *pbauth.GetUserTokenR
|
||||
func (s *authServer) parseToken(ctx context.Context, tokensString string) (claims *tokenverify.Claims, err error) {
|
||||
claims, err = tokenverify.GetClaimFromToken(tokensString, authverify.Secret(s.config.Share.Secret))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
isAdmin := authverify.IsManagerUserID(claims.UserID, s.config.Share.IMAdminUserID)
|
||||
if isAdmin {
|
||||
@@ -159,7 +155,10 @@ func (s *authServer) parseToken(ctx context.Context, tokensString string) (claim
|
||||
return nil, servererrs.ErrTokenNotExist.Wrap()
|
||||
}
|
||||
|
||||
func (s *authServer) ParseToken(ctx context.Context, req *pbauth.ParseTokenReq) (resp *pbauth.ParseTokenResp, err error) {
|
||||
func (s *authServer) ParseToken(
|
||||
ctx context.Context,
|
||||
req *pbauth.ParseTokenReq,
|
||||
) (resp *pbauth.ParseTokenResp, err error) {
|
||||
resp = &pbauth.ParseTokenResp{}
|
||||
claims, err := s.parseToken(ctx, req.Token)
|
||||
if err != nil {
|
||||
@@ -197,7 +196,7 @@ func (s *authServer) forceKickOff(ctx context.Context, userID string, platformID
|
||||
}
|
||||
|
||||
m, err := s.authDatabase.GetTokensWithoutError(ctx, userID, int(platformID))
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
if err != nil && errors.Is(err, redis.Nil) {
|
||||
return err
|
||||
}
|
||||
for k := range m {
|
||||
@@ -215,7 +214,7 @@ func (s *authServer) forceKickOff(ctx context.Context, userID string, platformID
|
||||
|
||||
func (s *authServer) InvalidateToken(ctx context.Context, req *pbauth.InvalidateTokenReq) (*pbauth.InvalidateTokenResp, error) {
|
||||
m, err := s.authDatabase.GetTokensWithoutError(ctx, req.UserID, int(req.PlatformID))
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
if err != nil && errors.Is(err, redis.Nil) {
|
||||
return nil, err
|
||||
}
|
||||
if m == nil {
|
||||
|
||||
@@ -16,7 +16,6 @@ package conversation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
@@ -26,12 +25,12 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
dbModel "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -44,15 +43,13 @@ import (
|
||||
)
|
||||
|
||||
type conversationServer struct {
|
||||
pbconversation.UnimplementedConversationServer
|
||||
msgRpcClient *rpcclient.MessageRpcClient
|
||||
user *rpcclient.UserRpcClient
|
||||
groupRpcClient *rpcclient.GroupRpcClient
|
||||
conversationDatabase controller.ConversationDatabase
|
||||
|
||||
conversationNotificationSender *ConversationNotificationSender
|
||||
config *Config
|
||||
|
||||
userClient *rpcli.UserClient
|
||||
msgClient *rpcli.MsgClient
|
||||
groupClient *rpcli.GroupClient
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -78,27 +75,17 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgClient := rpcli.NewMsgClient(msgConn)
|
||||
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
pbconversation.RegisterConversationServer(server, &conversationServer{
|
||||
conversationNotificationSender: NewConversationNotificationSender(&config.NotificationConfig, msgClient),
|
||||
msgRpcClient: &msgRpcClient,
|
||||
user: &userRpcClient,
|
||||
conversationNotificationSender: NewConversationNotificationSender(&config.NotificationConfig, &msgRpcClient),
|
||||
groupRpcClient: &groupRpcClient,
|
||||
conversationDatabase: controller.NewConversationDatabase(conversationDB,
|
||||
redis.NewConversationRedis(rdb, &config.LocalCacheConfig, redis.GetRocksCacheOptions(), conversationDB), mgocli.GetTx()),
|
||||
userClient: rpcli.NewUserClient(userConn),
|
||||
groupClient: rpcli.NewGroupClient(groupConn),
|
||||
msgClient: msgClient,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -135,12 +122,13 @@ func (c *conversationServer) GetSortedConversationList(ctx context.Context, req
|
||||
if len(conversations) == 0 {
|
||||
return nil, errs.ErrRecordNotFound.Wrap()
|
||||
}
|
||||
maxSeqs, err := c.msgClient.GetMaxSeqs(ctx, conversationIDs)
|
||||
|
||||
maxSeqs, err := c.msgRpcClient.GetMaxSeqs(ctx, conversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chatLogs, err := c.msgClient.GetMsgByConversationIDs(ctx, conversationIDs, maxSeqs)
|
||||
chatLogs, err := c.msgRpcClient.GetMsgByConversationIDs(ctx, conversationIDs, maxSeqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -150,7 +138,7 @@ func (c *conversationServer) GetSortedConversationList(ctx context.Context, req
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasReadSeqs, err := c.msgClient.GetHasReadSeqs(ctx, conversationIDs, req.UserID)
|
||||
hasReadSeqs, err := c.msgRpcClient.GetHasReadSeqs(ctx, req.UserID, conversationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -239,7 +227,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
|
||||
}
|
||||
|
||||
if req.Conversation.ConversationType == constant.WriteGroupChatType {
|
||||
groupInfo, err := c.groupClient.GetGroupInfo(ctx, req.Conversation.GroupID)
|
||||
groupInfo, err := c.groupRpcClient.GetGroupInfo(ctx, req.Conversation.GroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -363,15 +351,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
|
||||
needUpdateUsersList = append(needUpdateUsersList, userID)
|
||||
}
|
||||
}
|
||||
if len(m) != 0 && len(needUpdateUsersList) != 0 {
|
||||
if err := c.conversationDatabase.SetUsersConversationFieldTx(ctx, needUpdateUsersList, &conversation, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range needUpdateUsersList {
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, v, []string{req.Conversation.ConversationID})
|
||||
}
|
||||
}
|
||||
if req.Conversation.IsPrivateChat != nil && req.Conversation.ConversationType != constant.ReadGroupChatType {
|
||||
var conversations []*dbModel.Conversation
|
||||
for _, ownerUserID := range req.UserIDs {
|
||||
@@ -389,6 +369,16 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
|
||||
c.conversationNotificationSender.ConversationSetPrivateNotification(ctx, userID, req.Conversation.UserID,
|
||||
req.Conversation.IsPrivateChat.Value, req.Conversation.ConversationID)
|
||||
}
|
||||
} else {
|
||||
if len(m) != 0 && len(needUpdateUsersList) != 0 {
|
||||
if err := c.conversationDatabase.SetUsersConversationFieldTx(ctx, needUpdateUsersList, &conversation, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range needUpdateUsersList {
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, v, []string{req.Conversation.ConversationID})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &pbconversation.SetConversationsResp{}, nil
|
||||
@@ -442,38 +432,22 @@ func (c *conversationServer) CreateGroupChatConversations(ctx context.Context, r
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, req.GroupID)
|
||||
if err := c.msgClient.SetUserConversationMaxSeq(ctx, conversationID, req.UserIDs, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pbconversation.CreateGroupChatConversationsResp{}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbconversation.SetConversationMaxSeqReq) (*pbconversation.SetConversationMaxSeqResp, error) {
|
||||
if err := c.msgClient.SetUserConversationMaxSeq(ctx, req.ConversationID, req.OwnerUserID, req.MaxSeq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.OwnerUserID, req.ConversationID,
|
||||
map[string]any{"max_seq": req.MaxSeq}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, userID := range req.OwnerUserID {
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, userID, []string{req.ConversationID})
|
||||
}
|
||||
return &pbconversation.SetConversationMaxSeqResp{}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) SetConversationMinSeq(ctx context.Context, req *pbconversation.SetConversationMinSeqReq) (*pbconversation.SetConversationMinSeqResp, error) {
|
||||
if err := c.msgClient.SetUserConversationMin(ctx, req.ConversationID, req.OwnerUserID, req.MinSeq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.OwnerUserID, req.ConversationID,
|
||||
map[string]any{"min_seq": req.MinSeq}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, userID := range req.OwnerUserID {
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, userID, []string{req.ConversationID})
|
||||
}
|
||||
return &pbconversation.SetConversationMinSeqResp{}, nil
|
||||
}
|
||||
|
||||
@@ -574,7 +548,7 @@ func (c *conversationServer) getConversationInfo(
|
||||
}
|
||||
}
|
||||
if len(sendIDs) != 0 {
|
||||
sendInfos, err := c.userClient.GetUsersInfo(ctx, sendIDs)
|
||||
sendInfos, err := c.user.GetUsersInfo(ctx, sendIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -583,7 +557,7 @@ func (c *conversationServer) getConversationInfo(
|
||||
}
|
||||
}
|
||||
if len(groupIDs) != 0 {
|
||||
groupInfos, err := c.groupClient.GetGroupsInfo(ctx, groupIDs)
|
||||
groupInfos, err := c.groupRpcClient.GetGroupInfos(ctx, groupIDs, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -695,7 +669,7 @@ func (c *conversationServer) GetOwnerConversation(ctx context.Context, req *pbco
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) GetConversationsNeedClearMsg(ctx context.Context, _ *pbconversation.GetConversationsNeedClearMsgReq) (*pbconversation.GetConversationsNeedClearMsgResp, error) {
|
||||
func (c *conversationServer) GetConversationsNeedDestructMsgs(ctx context.Context, _ *pbconversation.GetConversationsNeedDestructMsgsReq) (*pbconversation.GetConversationsNeedDestructMsgsResp, error) {
|
||||
num, err := c.conversationDatabase.GetAllConversationIDsNumber(ctx)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "GetAllConversationIDsNumber failed", err)
|
||||
@@ -719,7 +693,7 @@ func (c *conversationServer) GetConversationsNeedClearMsg(ctx context.Context, _
|
||||
|
||||
conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
|
||||
// log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -742,7 +716,7 @@ func (c *conversationServer) GetConversationsNeedClearMsg(ctx context.Context, _
|
||||
}
|
||||
}
|
||||
|
||||
return &pbconversation.GetConversationsNeedClearMsgResp{Conversations: convert.ConversationsDB2Pb(temp)}, nil
|
||||
return &pbconversation.GetConversationsNeedDestructMsgsResp{Conversations: convert.ConversationsDB2Pb(temp)}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) GetNotNotifyConversationIDs(ctx context.Context, req *pbconversation.GetNotNotifyConversationIDsReq) (*pbconversation.GetNotNotifyConversationIDsResp, error) {
|
||||
@@ -760,51 +734,3 @@ func (c *conversationServer) GetPinnedConversationIDs(ctx context.Context, req *
|
||||
}
|
||||
return &pbconversation.GetPinnedConversationIDsResp{ConversationIDs: conversationIDs}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) ClearUserConversationMsg(ctx context.Context, req *pbconversation.ClearUserConversationMsgReq) (*pbconversation.ClearUserConversationMsgResp, error) {
|
||||
conversations, err := c.conversationDatabase.FindRandConversation(ctx, req.Timestamp, int(req.Limit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
latestMsgDestructTime := time.UnixMilli(req.Timestamp)
|
||||
for i, conversation := range conversations {
|
||||
if conversation.IsMsgDestruct == false || conversation.MsgDestructTime == 0 {
|
||||
continue
|
||||
}
|
||||
seq, err := c.msgClient.GetLastMessageSeqByTime(ctx, conversation.ConversationID, req.Timestamp-conversation.MsgDestructTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if seq <= 0 {
|
||||
log.ZDebug(ctx, "ClearUserConversationMsg GetLastMessageSeqByTime seq <= 0", "index", i, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID, "msgDestructTime", conversation.MsgDestructTime, "seq", seq)
|
||||
if err := c.setConversationMinSeqAndLatestMsgDestructTime(ctx, conversation.ConversationID, conversation.OwnerUserID, -1, latestMsgDestructTime); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
seq++
|
||||
if err := c.setConversationMinSeqAndLatestMsgDestructTime(ctx, conversation.ConversationID, conversation.OwnerUserID, seq, latestMsgDestructTime); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "ClearUserConversationMsg set min seq", "index", i, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID, "seq", seq, "msgDestructTime", conversation.MsgDestructTime)
|
||||
}
|
||||
return &pbconversation.ClearUserConversationMsgResp{Count: int32(len(conversations))}, nil
|
||||
}
|
||||
|
||||
func (c *conversationServer) setConversationMinSeqAndLatestMsgDestructTime(ctx context.Context, conversationID string, ownerUserID string, minSeq int64, latestMsgDestructTime time.Time) error {
|
||||
update := map[string]any{
|
||||
"latest_msg_destruct_time": latestMsgDestructTime,
|
||||
}
|
||||
if minSeq >= 0 {
|
||||
if err := c.msgClient.SetUserConversationMin(ctx, conversationID, []string{ownerUserID}, minSeq); err != nil {
|
||||
return err
|
||||
}
|
||||
update["min_seq"] = minSeq
|
||||
}
|
||||
|
||||
if err := c.conversationDatabase.UpdateUsersConversationField(ctx, []string{ownerUserID}, conversationID, update); err != nil {
|
||||
return err
|
||||
}
|
||||
c.conversationNotificationSender.ConversationChangeNotification(ctx, ownerUserID, []string{conversationID})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,11 +16,9 @@ package conversation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
@@ -29,10 +27,8 @@ type ConversationNotificationSender struct {
|
||||
*rpcclient.NotificationSender
|
||||
}
|
||||
|
||||
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 msgClient.SendMsg(ctx, req)
|
||||
}))}
|
||||
func NewConversationNotificationSender(conf *config.Notification, msgRpcClient *rpcclient.MessageRpcClient) *ConversationNotificationSender {
|
||||
return &ConversationNotificationSender{rpcclient.NewNotificationSender(conf, rpcclient.WithRpcClient(msgRpcClient))}
|
||||
}
|
||||
|
||||
// SetPrivate invote.
|
||||
|
||||
@@ -110,7 +110,7 @@ func UpdateGroupMemberMap(req *pbgroup.SetGroupMemberInfo) map[string]any {
|
||||
m["nickname"] = req.Nickname.Value
|
||||
}
|
||||
if req.FaceURL != nil {
|
||||
m["face_url"] = req.FaceURL.Value
|
||||
m["user_group_face_url"] = req.FaceURL.Value
|
||||
}
|
||||
if req.RoleLevel != nil {
|
||||
m["role_level"] = req.RoleLevel.Value
|
||||
|
||||
+64
-50
@@ -17,7 +17,6 @@ package group
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
@@ -37,7 +36,9 @@ import (
|
||||
"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/notification/grouphash"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||
pbgroup "github.com/openimsdk/protocol/group"
|
||||
@@ -56,14 +57,13 @@ import (
|
||||
)
|
||||
|
||||
type groupServer struct {
|
||||
pbgroup.UnimplementedGroupServer
|
||||
db controller.GroupDatabase
|
||||
notification *NotificationSender
|
||||
config *Config
|
||||
webhookClient *webhook.Client
|
||||
userClient *rpcli.UserClient
|
||||
msgClient *rpcli.MsgClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
db controller.GroupDatabase
|
||||
user rpcclient.UserRpcClient
|
||||
notification *GroupNotificationSender
|
||||
conversationRpcClient rpcclient.ConversationRpcClient
|
||||
msgRpcClient rpcclient.MessageRpcClient
|
||||
config *Config
|
||||
webhookClient *webhook.Client
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -98,33 +98,32 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
//msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
//conversationRpcClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gs := groupServer{
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
userClient: rpcli.NewUserClient(userConn),
|
||||
msgClient: rpcli.NewMsgClient(msgConn),
|
||||
conversationClient: rpcli.NewConversationClient(conversationConn),
|
||||
}
|
||||
gs.db = controller.NewGroupDatabase(rdb, &config.LocalCacheConfig, groupDB, groupMemberDB, groupRequestDB, mgocli.GetTx(), grouphash.NewGroupHashFromGroupServer(&gs))
|
||||
gs.notification = NewNotificationSender(gs.db, config, gs.userClient, gs.msgClient, gs.conversationClient)
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
conversationRpcClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
var gs groupServer
|
||||
database := controller.NewGroupDatabase(rdb, &config.LocalCacheConfig, groupDB, groupMemberDB, groupRequestDB, mgocli.GetTx(), grouphash.NewGroupHashFromGroupServer(&gs))
|
||||
gs.db = database
|
||||
gs.user = userRpcClient
|
||||
gs.notification = NewGroupNotificationSender(
|
||||
database,
|
||||
&msgRpcClient,
|
||||
&userRpcClient,
|
||||
&conversationRpcClient,
|
||||
config,
|
||||
func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) {
|
||||
users, err := userRpcClient.GetUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.Slice(users, func(e *sdkws.UserInfo) notification.CommonUser { return e }), nil
|
||||
},
|
||||
)
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
gs.conversationRpcClient = conversationRpcClient
|
||||
gs.msgRpcClient = msgRpcClient
|
||||
gs.config = config
|
||||
gs.webhookClient = webhook.NewWebhookClient(config.WebhooksConfig.URL)
|
||||
pbgroup.RegisterGroupServer(server, &gs)
|
||||
return nil
|
||||
}
|
||||
@@ -168,6 +167,19 @@ func (g *groupServer) CheckGroupAdmin(ctx context.Context, groupID string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *groupServer) GetPublicUserInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.PublicUserInfo, error) {
|
||||
if len(userIDs) == 0 {
|
||||
return map[string]*sdkws.PublicUserInfo{}, nil
|
||||
}
|
||||
users, err := g.user.GetPublicUserInfos(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.SliceToMapAny(users, func(e *sdkws.PublicUserInfo) (string, *sdkws.PublicUserInfo) {
|
||||
return e.UserID, e
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (g *groupServer) IsNotFound(err error) bool {
|
||||
return errs.ErrRecordNotFound.Is(specialerror.ErrCode(errs.Unwrap(err)))
|
||||
}
|
||||
@@ -209,6 +221,7 @@ func (g *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
|
||||
return nil, errs.ErrArgs.WrapMsg("no group owner")
|
||||
}
|
||||
if err := authverify.CheckAccessV3(ctx, req.OwnerUserID, g.config.Share.IMAdminUserID); err != nil {
|
||||
|
||||
return nil, err
|
||||
}
|
||||
userIDs := append(append(req.MemberUserIDs, req.AdminUserIDs...), req.OwnerUserID)
|
||||
@@ -221,7 +234,7 @@ func (g *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
|
||||
return nil, errs.ErrArgs.WrapMsg("group member repeated")
|
||||
}
|
||||
|
||||
userMap, err := g.userClient.GetUsersInfoMap(ctx, userIDs)
|
||||
userMap, err := g.user.GetUsersInfoMap(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -372,7 +385,7 @@ func (g *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
|
||||
return nil, servererrs.ErrDismissedAlready.WrapMsg("group dismissed checking group status found it dismissed")
|
||||
}
|
||||
|
||||
userMap, err := g.userClient.GetUsersInfoMap(ctx, req.InvitedUserIDs)
|
||||
userMap, err := g.user.GetUsersInfoMap(ctx, req.InvitedUserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -683,7 +696,7 @@ func (g *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
|
||||
userIDs = append(userIDs, gr.UserID)
|
||||
}
|
||||
userIDs = datautil.Distinct(userIDs)
|
||||
userMap, err := g.userClient.GetUsersInfoMap(ctx, userIDs)
|
||||
userMap, err := g.user.GetPublicUserInfoMap(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -795,7 +808,7 @@ func (g *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
|
||||
} else if !g.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
if err := g.userClient.CheckUser(ctx, []string{req.FromUserID}); err != nil {
|
||||
if _, err := g.user.GetPublicUserInfo(ctx, req.FromUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var member *model.GroupMember
|
||||
@@ -839,7 +852,7 @@ func (g *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
|
||||
}
|
||||
|
||||
func (g *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq) (*pbgroup.JoinGroupResp, error) {
|
||||
user, err := g.userClient.GetUserInfo(ctx, req.InviterUserID)
|
||||
user, err := g.user.GetUserInfo(ctx, req.InviterUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -945,12 +958,12 @@ func (g *groupServer) QuitGroup(ctx context.Context, req *pbgroup.QuitGroupReq)
|
||||
}
|
||||
|
||||
func (g *groupServer) deleteMemberAndSetConversationSeq(ctx context.Context, groupID string, userIDs []string) error {
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := g.msgClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
conevrsationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := g.msgRpcClient.GetConversationMaxSeq(ctx, conevrsationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return g.conversationClient.SetConversationMaxSeq(ctx, conversationID, userIDs, maxSeq)
|
||||
return g.conversationRpcClient.SetConversationMaxSeq(ctx, userIDs, conevrsationID, maxSeq)
|
||||
}
|
||||
|
||||
func (g *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInfoReq) (*pbgroup.SetGroupInfoResp, error) {
|
||||
@@ -1026,7 +1039,7 @@ func (g *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
|
||||
return
|
||||
}
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.GroupNotification}
|
||||
if err := g.conversationClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
|
||||
if err := g.conversationRpcClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, "UserIDs", resp.UserIDs, "conversation", conversation)
|
||||
}
|
||||
}()
|
||||
@@ -1139,7 +1152,8 @@ func (g *groupServer) SetGroupInfoEx(ctx context.Context, req *pbgroup.SetGroupI
|
||||
}
|
||||
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.GroupNotification}
|
||||
if err := g.conversationClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
|
||||
|
||||
if err := g.conversationRpcClient.SetConversations(ctx, resp.UserIDs, conversation); err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, "UserIDs", resp.UserIDs, "conversation", conversation)
|
||||
}
|
||||
}()
|
||||
@@ -1291,7 +1305,7 @@ func (g *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbgroup.GetGr
|
||||
}
|
||||
|
||||
func (g *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgroup.GetUserReqApplicationListReq) (*pbgroup.GetUserReqApplicationListResp, error) {
|
||||
user, err := g.userClient.GetUserInfo(ctx, req.UserID)
|
||||
user, err := g.user.GetPublicUserInfo(ctx, req.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1747,7 +1761,7 @@ func (g *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
|
||||
return nil, servererrs.ErrGroupIDNotFound.WrapMsg(strings.Join(ids, ","))
|
||||
}
|
||||
|
||||
userMap, err := g.userClient.GetUsersInfoMap(ctx, req.UserIDs)
|
||||
userMap, err := g.user.GetPublicUserInfoMap(ctx, req.UserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1778,7 +1792,7 @@ func (g *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
|
||||
ownerUserID = owner.UserID
|
||||
}
|
||||
|
||||
var userInfo *sdkws.UserInfo
|
||||
var userInfo *sdkws.PublicUserInfo
|
||||
if user, ok := userMap[e.UserID]; !ok {
|
||||
userInfo = user
|
||||
}
|
||||
@@ -1824,7 +1838,7 @@ func (g *groupServer) GetSpecifiedUserGroupRequestInfo(ctx context.Context, req
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userInfos, err := g.userClient.GetUsersInfo(ctx, []string{req.UserID})
|
||||
userInfos, err := g.user.GetPublicUserInfos(ctx, []string{req.UserID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -18,10 +18,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
@@ -30,8 +26,8 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
pbgroup "github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
@@ -42,6 +38,7 @@ import (
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GroupApplicationReceiver
|
||||
@@ -50,38 +47,36 @@ const (
|
||||
adminReceiver
|
||||
)
|
||||
|
||||
func NewNotificationSender(db controller.GroupDatabase, config *Config, userClient *rpcli.UserClient, msgClient *rpcli.MsgClient, conversationClient *rpcli.ConversationClient) *NotificationSender {
|
||||
return &NotificationSender{
|
||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig,
|
||||
rpcclient.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msgClient.SendMsg(ctx, req)
|
||||
}),
|
||||
rpcclient.WithUserRpcClient(userClient.GetUserInfo),
|
||||
),
|
||||
getUsersInfo: func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error) {
|
||||
users, err := userClient.GetUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.Slice(users, func(e *sdkws.UserInfo) common_user.CommonUser { return e }), nil
|
||||
},
|
||||
func NewGroupNotificationSender(
|
||||
db controller.GroupDatabase,
|
||||
msgRpcClient *rpcclient.MessageRpcClient,
|
||||
userRpcClient *rpcclient.UserRpcClient,
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient,
|
||||
config *Config,
|
||||
fn func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error),
|
||||
) *GroupNotificationSender {
|
||||
return &GroupNotificationSender{
|
||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithRpcClient(msgRpcClient), rpcclient.WithUserRpcClient(userRpcClient)),
|
||||
getUsersInfo: fn,
|
||||
db: db,
|
||||
config: config,
|
||||
msgClient: msgClient,
|
||||
conversationClient: conversationClient,
|
||||
|
||||
conversationRpcClient: conversationRpcClient,
|
||||
msgRpcClient: msgRpcClient,
|
||||
}
|
||||
}
|
||||
|
||||
type NotificationSender struct {
|
||||
type GroupNotificationSender struct {
|
||||
*rpcclient.NotificationSender
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||
db controller.GroupDatabase
|
||||
config *Config
|
||||
msgClient *rpcli.MsgClient
|
||||
conversationClient *rpcli.ConversationClient
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error)
|
||||
db controller.GroupDatabase
|
||||
config *Config
|
||||
|
||||
conversationRpcClient *rpcclient.ConversationRpcClient
|
||||
msgRpcClient *rpcclient.MessageRpcClient
|
||||
}
|
||||
|
||||
func (g *NotificationSender) PopulateGroupMember(ctx context.Context, members ...*model.GroupMember) error {
|
||||
func (g *GroupNotificationSender) PopulateGroupMember(ctx context.Context, members ...*model.GroupMember) error {
|
||||
if len(members) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -96,7 +91,7 @@ func (g *NotificationSender) PopulateGroupMember(ctx context.Context, members ..
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userMap := make(map[string]common_user.CommonUser)
|
||||
userMap := make(map[string]notification.CommonUser)
|
||||
for i, user := range users {
|
||||
userMap[user.GetUserID()] = users[i]
|
||||
}
|
||||
@@ -116,7 +111,7 @@ func (g *NotificationSender) PopulateGroupMember(ctx context.Context, members ..
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) {
|
||||
func (g *GroupNotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) {
|
||||
users, err := g.getUsersInfo(ctx, []string{userID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -132,7 +127,7 @@ func (g *NotificationSender) getUser(ctx context.Context, userID string) (*sdkws
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupInfo(ctx context.Context, groupID string) (*sdkws.GroupInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID string) (*sdkws.GroupInfo, error) {
|
||||
gm, err := g.db.TakeGroup(ctx, groupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -153,7 +148,7 @@ func (g *NotificationSender) getGroupInfo(ctx context.Context, groupID string) (
|
||||
return convert.Db2PbGroupInfo(gm, ownerUserID, num), nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
|
||||
members, err := g.db.FindGroupMembers(ctx, groupID, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -169,7 +164,7 @@ func (g *NotificationSender) getGroupMembers(ctx context.Context, groupID string
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupMemberMap(ctx context.Context, groupID string, userIDs []string) (map[string]*sdkws.GroupMemberFullInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupMemberMap(ctx context.Context, groupID string, userIDs []string) (map[string]*sdkws.GroupMemberFullInfo, error) {
|
||||
members, err := g.getGroupMembers(ctx, groupID, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -181,7 +176,7 @@ func (g *NotificationSender) getGroupMemberMap(ctx context.Context, groupID stri
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupMember(ctx context.Context, groupID string, userID string) (*sdkws.GroupMemberFullInfo, error) {
|
||||
func (g *GroupNotificationSender) getGroupMember(ctx context.Context, groupID string, userID string) (*sdkws.GroupMemberFullInfo, error) {
|
||||
members, err := g.getGroupMembers(ctx, groupID, []string{userID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -192,7 +187,7 @@ func (g *NotificationSender) getGroupMember(ctx context.Context, groupID string,
|
||||
return members[0], nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) {
|
||||
func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) {
|
||||
members, err := g.db.FindGroupMemberRoleLevels(ctx, groupID, []int32{constant.GroupOwner, constant.GroupAdmin})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -204,7 +199,7 @@ func (g *NotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, gr
|
||||
return datautil.Slice(members, fn), nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
|
||||
func (g *GroupNotificationSender) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
|
||||
return &sdkws.GroupMemberFullInfo{
|
||||
GroupID: member.GroupID,
|
||||
UserID: member.UserID,
|
||||
@@ -221,7 +216,7 @@ func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMember, appMang
|
||||
}
|
||||
}
|
||||
|
||||
/* func (g *NotificationSender) getUsersInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error) {
|
||||
/* func (g *GroupNotificationSender) getUsersInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error) {
|
||||
users, err := g.getUsersInfo(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -233,11 +228,11 @@ func (g *NotificationSender) groupMemberDB2PB(member *model.GroupMember, appMang
|
||||
return result, nil
|
||||
} */
|
||||
|
||||
func (g *NotificationSender) fillOpUser(ctx context.Context, opUser **sdkws.GroupMemberFullInfo, groupID string) (err error) {
|
||||
func (g *GroupNotificationSender) fillOpUser(ctx context.Context, opUser **sdkws.GroupMemberFullInfo, groupID string) (err error) {
|
||||
return g.fillOpUserByUserID(ctx, mcontext.GetOpUserID(ctx), opUser, groupID)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) fillOpUserByUserID(ctx context.Context, userID string, opUser **sdkws.GroupMemberFullInfo, groupID string) error {
|
||||
func (g *GroupNotificationSender) fillOpUserByUserID(ctx context.Context, userID string, opUser **sdkws.GroupMemberFullInfo, groupID string) error {
|
||||
if opUser == nil {
|
||||
return errs.ErrInternalServer.WrapMsg("**sdkws.GroupMemberFullInfo is nil")
|
||||
}
|
||||
@@ -281,7 +276,7 @@ func (g *NotificationSender) fillOpUserByUserID(ctx context.Context, userID stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) setVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string) {
|
||||
func (g *GroupNotificationSender) setVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string) {
|
||||
versions := versionctx.GetVersionLog(ctx).Get()
|
||||
for _, coll := range versions {
|
||||
if coll.Name == collName && coll.Doc.DID == id {
|
||||
@@ -292,7 +287,7 @@ func (g *NotificationSender) setVersion(ctx context.Context, version *uint64, ve
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) setSortVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string, sortVersion *uint64) {
|
||||
func (g *GroupNotificationSender) setSortVersion(ctx context.Context, version *uint64, versionID *string, collName string, id string, sortVersion *uint64) {
|
||||
versions := versionctx.GetVersionLog(ctx).Get()
|
||||
for _, coll := range versions {
|
||||
if coll.Name == collName && coll.Doc.DID == id {
|
||||
@@ -307,7 +302,7 @@ func (g *NotificationSender) setSortVersion(ctx context.Context, version *uint64
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips) {
|
||||
func (g *GroupNotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -321,7 +316,7 @@ func (g *NotificationSender) GroupCreatedNotification(ctx context.Context, tips
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupCreatedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupInfoSetNotification(ctx context.Context, tips *sdkws.GroupInfoSetTips) {
|
||||
func (g *GroupNotificationSender) GroupInfoSetNotification(ctx context.Context, tips *sdkws.GroupInfoSetTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -335,7 +330,7 @@ func (g *NotificationSender) GroupInfoSetNotification(ctx context.Context, tips
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNotification, tips, rpcclient.WithRpcGetUserName())
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupInfoSetNameNotification(ctx context.Context, tips *sdkws.GroupInfoSetNameTips) {
|
||||
func (g *GroupNotificationSender) GroupInfoSetNameNotification(ctx context.Context, tips *sdkws.GroupInfoSetNameTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -349,7 +344,7 @@ func (g *NotificationSender) GroupInfoSetNameNotification(ctx context.Context, t
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNameNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Context, tips *sdkws.GroupInfoSetAnnouncementTips) {
|
||||
func (g *GroupNotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Context, tips *sdkws.GroupInfoSetAnnouncementTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -363,7 +358,7 @@ func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Co
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetAnnouncementNotification, tips, rpcclient.WithRpcGetUserName())
|
||||
}
|
||||
|
||||
func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbgroup.JoinGroupReq) {
|
||||
func (g *GroupNotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbgroup.JoinGroupReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -391,7 +386,7 @@ func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Contex
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) MemberQuitNotification(ctx context.Context, member *sdkws.GroupMemberFullInfo) {
|
||||
func (g *GroupNotificationSender) MemberQuitNotification(ctx context.Context, member *sdkws.GroupMemberFullInfo) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -408,7 +403,7 @@ func (g *NotificationSender) MemberQuitNotification(ctx context.Context, member
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), member.GroupID, constant.MemberQuitNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -441,7 +436,7 @@ func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Co
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx context.Context, req *pbgroup.GroupApplicationResponseReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -474,7 +469,7 @@ func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Co
|
||||
}
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupOwnerTransferredNotification(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) {
|
||||
func (g *GroupNotificationSender) GroupOwnerTransferredNotification(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -505,7 +500,7 @@ func (g *NotificationSender) GroupOwnerTransferredNotification(ctx context.Conte
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupOwnerTransferredNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips) {
|
||||
func (g *GroupNotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -519,7 +514,7 @@ func (g *NotificationSender) MemberKickedNotification(ctx context.Context, tips
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.MemberKickedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx context.Context, groupID string, invitedOpUserID string, entrantUserID ...string) error {
|
||||
func (g *GroupNotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx context.Context, groupID string, invitedOpUserID string, entrantUserID ...string) error {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -529,15 +524,20 @@ func (g *NotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx co
|
||||
|
||||
if !g.config.RpcConfig.EnableHistoryForNewMembers {
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := g.msgClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
maxSeq, err := g.msgRpcClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.msgClient.SetUserConversationsMinSeq(ctx, conversationID, entrantUserID, maxSeq+1); err != nil {
|
||||
if _, err = g.msgRpcClient.SetUserConversationsMinSeq(ctx, &msg.SetUserConversationsMinSeqReq{
|
||||
UserIDs: entrantUserID,
|
||||
ConversationID: conversationID,
|
||||
Seq: maxSeq,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := g.conversationClient.CreateGroupChatConversations(ctx, groupID, entrantUserID); err != nil {
|
||||
|
||||
if err := g.conversationRpcClient.GroupChatFirstCreateConversation(ctx, groupID, entrantUserID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -573,7 +573,7 @@ func (g *NotificationSender) GroupApplicationAgreeMemberEnterNotification(ctx co
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) MemberEnterNotification(ctx context.Context, groupID string, entrantUserID string) error {
|
||||
func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, groupID string, entrantUserID string) error {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -583,17 +583,23 @@ func (g *NotificationSender) MemberEnterNotification(ctx context.Context, groupI
|
||||
|
||||
if !g.config.RpcConfig.EnableHistoryForNewMembers {
|
||||
conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
|
||||
maxSeq, err := g.msgClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
maxSeq, err := g.msgRpcClient.GetConversationMaxSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.msgClient.SetUserConversationsMinSeq(ctx, conversationID, []string{entrantUserID}, maxSeq+1); err != nil {
|
||||
if _, err = g.msgRpcClient.SetUserConversationsMinSeq(ctx, &msg.SetUserConversationsMinSeqReq{
|
||||
UserIDs: []string{entrantUserID},
|
||||
ConversationID: conversationID,
|
||||
Seq: maxSeq,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := g.conversationClient.CreateGroupChatConversations(ctx, groupID, []string{entrantUserID}); err != nil {
|
||||
|
||||
if err := g.conversationRpcClient.GroupChatFirstCreateConversation(ctx, groupID, []string{entrantUserID}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var group *sdkws.GroupInfo
|
||||
group, err = g.getGroupInfo(ctx, groupID)
|
||||
if err != nil {
|
||||
@@ -614,7 +620,7 @@ func (g *NotificationSender) MemberEnterNotification(ctx context.Context, groupI
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupDismissedNotification(ctx context.Context, tips *sdkws.GroupDismissedTips) {
|
||||
func (g *GroupNotificationSender) GroupDismissedNotification(ctx context.Context, tips *sdkws.GroupDismissedTips) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -627,7 +633,7 @@ func (g *NotificationSender) GroupDismissedNotification(ctx context.Context, tip
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupDismissedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) {
|
||||
func (g *GroupNotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -655,7 +661,7 @@ func (g *NotificationSender) GroupMemberMutedNotification(ctx context.Context, g
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberCancelMutedNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberCancelMutedNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -680,7 +686,7 @@ func (g *NotificationSender) GroupMemberCancelMutedNotification(ctx context.Cont
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMutedNotification(ctx context.Context, groupID string) {
|
||||
func (g *GroupNotificationSender) GroupMutedNotification(ctx context.Context, groupID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -708,7 +714,7 @@ func (g *NotificationSender) GroupMutedNotification(ctx context.Context, groupID
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupCancelMutedNotification(ctx context.Context, groupID string) {
|
||||
func (g *GroupNotificationSender) GroupCancelMutedNotification(ctx context.Context, groupID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -736,7 +742,7 @@ func (g *NotificationSender) GroupCancelMutedNotification(ctx context.Context, g
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupCancelMutedNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberInfoSetNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberInfoSetNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -761,7 +767,7 @@ func (g *NotificationSender) GroupMemberInfoSetNotification(ctx context.Context,
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberInfoSetNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberSetToAdminNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberSetToAdminNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -785,7 +791,7 @@ func (g *NotificationSender) GroupMemberSetToAdminNotification(ctx context.Conte
|
||||
g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberSetToAdminNotification, tips)
|
||||
}
|
||||
|
||||
func (g *NotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
func (g *GroupNotificationSender) GroupMemberSetToOrdinaryUserNotification(ctx context.Context, groupID, groupMemberUserID string) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
|
||||
@@ -137,7 +137,7 @@ func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkCon
|
||||
return nil, err
|
||||
}
|
||||
hasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID)
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
if err != nil && errors.Is(err, redis.Nil) {
|
||||
return nil, err
|
||||
}
|
||||
var seqs []int64
|
||||
|
||||
+105
-40
@@ -2,59 +2,124 @@ package msg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/wrapperspb"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"strings"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/utils/idutil"
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// DestructMsgs hard delete in Database.
|
||||
func (m *msgServer) DestructMsgs(ctx context.Context, req *msg.DestructMsgsReq) (*msg.DestructMsgsResp, error) {
|
||||
// hard delete in Database.
|
||||
func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.ClearMsgResp, err error) {
|
||||
if err := authverify.CheckAdmin(ctx, m.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs, err := m.MsgDatabase.GetRandBeforeMsg(ctx, req.Timestamp, int(req.Limit))
|
||||
if req.Timestamp > time.Now().UnixMilli() {
|
||||
return nil, errs.ErrArgs.WrapMsg("request millisecond timestamp error")
|
||||
}
|
||||
var (
|
||||
docNum int
|
||||
msgNum int
|
||||
start = time.Now()
|
||||
)
|
||||
|
||||
clearMsg := func(ctx context.Context) (bool, error) {
|
||||
docIDs, err := m.MsgDatabase.GetDocIDs(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
msgs, err := m.MsgDatabase.GetBeforeMsg(ctx, req.Timestamp, docIDs, 5000)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for _, msg := range msgs {
|
||||
index, err := m.MsgDatabase.DeleteDocMsgBefore(ctx, req.Timestamp, msg)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(index) == 0 {
|
||||
return false, errs.ErrInternalServer.WrapMsg("delete doc msg failed")
|
||||
}
|
||||
|
||||
docNum++
|
||||
msgNum += len(index)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
_, err = clearMsg(ctx)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "clear msg failed", err, "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start))
|
||||
return nil, err
|
||||
}
|
||||
for i, doc := range docs {
|
||||
if err := m.MsgDatabase.DeleteDoc(ctx, doc.DocID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "DestructMsgs delete doc", "index", i, "docID", doc.DocID)
|
||||
index := strings.LastIndex(doc.DocID, ":")
|
||||
if index < 0 {
|
||||
continue
|
||||
}
|
||||
var minSeq int64
|
||||
for _, model := range doc.Msg {
|
||||
if model.Msg == nil {
|
||||
continue
|
||||
}
|
||||
if model.Msg.Seq > minSeq {
|
||||
minSeq = model.Msg.Seq
|
||||
}
|
||||
}
|
||||
if minSeq <= 0 {
|
||||
continue
|
||||
}
|
||||
conversationID := doc.DocID[:index]
|
||||
if conversationID == "" {
|
||||
continue
|
||||
}
|
||||
minSeq++
|
||||
if err := m.MsgDatabase.SetMinSeq(ctx, conversationID, minSeq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "DestructMsgs delete doc set min seq", "index", i, "docID", doc.DocID, "conversationID", conversationID, "setMinSeq", minSeq)
|
||||
}
|
||||
return &msg.DestructMsgsResp{Count: int32(len(docs))}, nil
|
||||
|
||||
log.ZDebug(ctx, "clearing message", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start))
|
||||
|
||||
return &msg.ClearMsgResp{}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) GetLastMessageSeqByTime(ctx context.Context, req *msg.GetLastMessageSeqByTimeReq) (*msg.GetLastMessageSeqByTimeResp, error) {
|
||||
seq, err := m.MsgDatabase.GetLastMessageSeqByTime(ctx, req.ConversationID, req.Time)
|
||||
if err != nil {
|
||||
// soft delete for self
|
||||
func (m *msgServer) DestructMsgs(ctx context.Context, req *msg.DestructMsgsReq) (_ *msg.DestructMsgsResp, err error) {
|
||||
temp := convert.ConversationsPb2DB(req.Conversations)
|
||||
|
||||
batchNum := 100
|
||||
|
||||
errg, _ := errgroup.WithContext(ctx)
|
||||
errg.SetLimit(100)
|
||||
|
||||
for i := 0; i < len(temp); i += batchNum {
|
||||
batch := temp[i:min(i+batchNum, len(temp))]
|
||||
|
||||
errg.Go(func() error {
|
||||
for _, conversation := range batch {
|
||||
handleCtx := mcontext.NewCtx(stringutil.GetSelfFuncName() + "-" + idutil.OperationIDGenerator() + "-" + conversation.ConversationID + "-" + conversation.OwnerUserID)
|
||||
log.ZDebug(handleCtx, "User MsgsDestruct",
|
||||
"conversationID", conversation.ConversationID,
|
||||
"ownerUserID", conversation.OwnerUserID,
|
||||
"msgDestructTime", conversation.MsgDestructTime,
|
||||
"lastMsgDestructTime", conversation.LatestMsgDestructTime)
|
||||
|
||||
seqs, err := m.MsgDatabase.UserMsgsDestruct(handleCtx, conversation.OwnerUserID, conversation.ConversationID, conversation.MsgDestructTime, conversation.LatestMsgDestructTime)
|
||||
if err != nil {
|
||||
log.ZError(handleCtx, "user msg destruct failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(seqs) > 0 {
|
||||
if err := m.Conversation.UpdateConversation(handleCtx,
|
||||
&pbconversation.UpdateConversationReq{
|
||||
UserIDs: []string{conversation.OwnerUserID},
|
||||
ConversationID: conversation.ConversationID,
|
||||
LatestMsgDestructTime: wrapperspb.Int64(time.Now().UnixMilli())}); err != nil {
|
||||
log.ZError(handleCtx, "updateUsersConversationField failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID)
|
||||
continue
|
||||
}
|
||||
|
||||
// if you need Notify SDK client userseq is update.
|
||||
// m.msgNotificationSender.UserDeleteMsgsNotification(handleCtx, conversation.OwnerUserID, conversation.ConversationID, seqs)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msg.GetLastMessageSeqByTimeResp{Seq: seq}, nil
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
+15
-14
@@ -74,13 +74,19 @@ func (m *msgServer) DeleteMsgs(ctx context.Context, req *msg.DeleteMsgsReq) (*ms
|
||||
if err := m.MsgDatabase.DeleteMsgsPhysicalBySeqs(ctx, req.ConversationID, req.Seqs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conv, err := m.conversationClient.GetConversationsByConversationID(ctx, req.ConversationID)
|
||||
conversations, err := m.Conversation.GetConversationsByConversationID(ctx, []string{req.ConversationID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tips := &sdkws.DeleteMsgsTips{UserID: req.UserID, ConversationID: req.ConversationID, Seqs: req.Seqs}
|
||||
m.notificationSender.NotificationWithSessionType(ctx, req.UserID, m.conversationAndGetRecvID(conv, req.UserID),
|
||||
constant.DeleteMsgsNotification, conv.ConversationType, tips)
|
||||
m.notificationSender.NotificationWithSessionType(
|
||||
ctx,
|
||||
req.UserID,
|
||||
m.conversationAndGetRecvID(conversations[0], req.UserID),
|
||||
constant.DeleteMsgsNotification,
|
||||
conversations[0].ConversationType,
|
||||
tips,
|
||||
)
|
||||
} else {
|
||||
if err := m.MsgDatabase.DeleteUserMsgsBySeqs(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil {
|
||||
return nil, err
|
||||
@@ -106,14 +112,16 @@ func (m *msgServer) DeleteMsgPhysical(ctx context.Context, req *msg.DeleteMsgPhy
|
||||
return nil, err
|
||||
}
|
||||
remainTime := timeutil.GetCurrentTimestampBySecond() - req.Timestamp
|
||||
if _, err := m.DestructMsgs(ctx, &msg.DestructMsgsReq{Timestamp: remainTime, Limit: 9999}); err != nil {
|
||||
return nil, err
|
||||
for _, conversationID := range req.ConversationIDs {
|
||||
if err := m.MsgDatabase.DeleteConversationMsgsAndSetMinSeq(ctx, conversationID, remainTime); err != nil {
|
||||
log.ZWarn(ctx, "DeleteConversationMsgsAndSetMinSeq error", err, "conversationID", conversationID, "err", err)
|
||||
}
|
||||
}
|
||||
return &msg.DeleteMsgPhysicalResp{}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) clearConversation(ctx context.Context, conversationIDs []string, userID string, deleteSyncOpt *msg.DeleteSyncOpt) error {
|
||||
conversations, err := m.conversationClient.GetConversationsByConversationIDs(ctx, conversationIDs)
|
||||
conversations, err := m.Conversation.GetConversationsByConversationID(ctx, conversationIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -130,16 +138,9 @@ func (m *msgServer) clearConversation(ctx context.Context, conversationIDs []str
|
||||
}
|
||||
isSyncSelf, isSyncOther := m.validateDeleteSyncOpt(deleteSyncOpt)
|
||||
if !isSyncOther {
|
||||
setSeqs := m.getMinSeqs(maxSeqs)
|
||||
if err := m.MsgDatabase.SetUserConversationsMinSeqs(ctx, userID, setSeqs); err != nil {
|
||||
if err := m.MsgDatabase.SetUserConversationsMinSeqs(ctx, userID, m.getMinSeqs(maxSeqs)); err != nil {
|
||||
return err
|
||||
}
|
||||
ownerUserIDs := []string{userID}
|
||||
for conversationID, seq := range setSeqs {
|
||||
if err := m.conversationClient.SetConversationMinSeq(ctx, conversationID, ownerUserIDs, seq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// notification 2 self
|
||||
if isSyncSelf {
|
||||
tips := &sdkws.ClearConversationTips{UserID: userID, ConversationIDs: existConversationIDs}
|
||||
|
||||
@@ -17,7 +17,7 @@ package msg
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
@@ -48,3 +48,7 @@ func (m *MsgNotificationSender) MarkAsReadNotification(ctx context.Context, conv
|
||||
}
|
||||
m.NotificationWithSessionType(ctx, sendID, recvID, constant.HasReadReceipt, sessionType, tips)
|
||||
}
|
||||
|
||||
func (m *MsgNotificationSender) StreamMsgNotification(ctx context.Context, sendID string, recvID string, sessionType int32, tips *sdkws.StreamMsgTips) {
|
||||
m.NotificationWithSessionType(ctx, sendID, recvID, constant.StreamMsgNotification, sessionType, tips)
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
|
||||
log.ZDebug(ctx, "GetMsgBySeqs", "conversationID", req.ConversationID, "seq", req.Seq, "msg", string(data))
|
||||
var role int32
|
||||
if !authverify.IsAppManagerUid(ctx, m.config.Share.IMAdminUserID) {
|
||||
sessionType := msgs[0].SessionType
|
||||
switch sessionType {
|
||||
switch msgs[0].SessionType {
|
||||
case constant.SingleChatType:
|
||||
if err := authverify.CheckAccessV3(ctx, msgs[0].SendID, m.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
@@ -90,7 +89,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
|
||||
role = member.RoleLevel
|
||||
}
|
||||
default:
|
||||
return nil, errs.ErrInternalServer.WrapMsg("msg sessionType not supported", "sessionType", sessionType)
|
||||
return nil, errs.ErrInternalServer.WrapMsg("msg sessionType not supported")
|
||||
}
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
+22
-16
@@ -16,6 +16,7 @@ package msg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/tools/mw"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
@@ -34,6 +35,11 @@ import (
|
||||
func (m *msgServer) SendMsg(ctx context.Context, req *pbmsg.SendMsgReq) (*pbmsg.SendMsgResp, error) {
|
||||
if req.MsgData != nil {
|
||||
m.encapsulateMsgData(req.MsgData)
|
||||
if req.MsgData.ContentType == constant.Stream {
|
||||
if err := m.handlerStreamMsg(ctx, req.MsgData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
switch req.MsgData.SessionType {
|
||||
case constant.SingleChatType:
|
||||
return m.sendMsgSingleChat(ctx, req)
|
||||
@@ -83,7 +89,7 @@ func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgDa
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.ZPanic(nctx, "setConversationAtInfo Panic", errs.ErrPanic(r))
|
||||
mw.PanicStackToLog(nctx, r)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -96,14 +102,14 @@ func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgDa
|
||||
ConversationType: msg.SessionType,
|
||||
GroupID: msg.GroupID,
|
||||
}
|
||||
memberUserIDList, err := m.GroupLocalCache.GetGroupMemberIDs(ctx, msg.GroupID)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "GetGroupMemberIDs", err)
|
||||
return
|
||||
}
|
||||
|
||||
tagAll := datautil.Contain(constant.AtAllString, msg.AtUserIDList...)
|
||||
if tagAll {
|
||||
memberUserIDList, err := m.GroupLocalCache.GetGroupMemberIDs(ctx, msg.GroupID)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "GetGroupMemberIDs", err)
|
||||
return
|
||||
}
|
||||
|
||||
memberUserIDList = datautil.DeleteElems(memberUserIDList, msg.SendID)
|
||||
|
||||
@@ -113,29 +119,29 @@ func (m *msgServer) setConversationAtInfo(nctx context.Context, msg *sdkws.MsgDa
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAll}
|
||||
} else { // @Everyone and @other people
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAllAtMe}
|
||||
atUserID = datautil.SliceIntersectFuncs(atUserID, memberUserIDList, func(a string) string { return a }, func(b string) string {
|
||||
return b
|
||||
})
|
||||
if err := m.conversationClient.SetConversations(ctx, atUserID, conversation); err != nil {
|
||||
|
||||
err = m.Conversation.SetConversations(ctx, atUserID, conversation)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, "userID", atUserID, "conversation", conversation)
|
||||
}
|
||||
|
||||
memberUserIDList = datautil.Single(atUserID, memberUserIDList)
|
||||
}
|
||||
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtAll}
|
||||
if err := m.conversationClient.SetConversations(ctx, memberUserIDList, conversation); err != nil {
|
||||
|
||||
err = m.Conversation.SetConversations(ctx, memberUserIDList, conversation)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, "userID", memberUserIDList, "conversation", conversation)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
atUserID = datautil.SliceIntersectFuncs(msg.AtUserIDList, memberUserIDList, func(a string) string { return a }, func(b string) string {
|
||||
return b
|
||||
})
|
||||
conversation.GroupAtType = &wrapperspb.Int32Value{Value: constant.AtMe}
|
||||
|
||||
if err := m.conversationClient.SetConversations(ctx, atUserID, conversation); err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, atUserID, conversation)
|
||||
err := m.Conversation.SetConversations(ctx, msg.AtUserIDList, conversation)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "SetConversations", err, msg.AtUserIDList, conversation)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,21 +84,3 @@ func (m *msgServer) GetActiveConversation(ctx context.Context, req *pbmsg.GetAct
|
||||
}
|
||||
return &pbmsg.GetActiveConversationResp{Conversations: conversations}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) SetUserConversationMaxSeq(ctx context.Context, req *pbmsg.SetUserConversationMaxSeqReq) (*pbmsg.SetUserConversationMaxSeqResp, error) {
|
||||
for _, userID := range req.OwnerUserID {
|
||||
if err := m.MsgDatabase.SetUserConversationsMaxSeq(ctx, req.ConversationID, userID, req.MaxSeq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &pbmsg.SetUserConversationMaxSeqResp{}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) SetUserConversationMinSeq(ctx context.Context, req *pbmsg.SetUserConversationMinSeqReq) (*pbmsg.SetUserConversationMinSeqResp, error) {
|
||||
for _, userID := range req.OwnerUserID {
|
||||
if err := m.MsgDatabase.SetUserConversationsMinSeq(ctx, req.ConversationID, userID, req.MinSeq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &pbmsg.SetUserConversationMinSeqResp{}, nil
|
||||
}
|
||||
|
||||
+46
-54
@@ -16,7 +16,6 @@ package msg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
@@ -27,8 +26,8 @@ import (
|
||||
"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/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
@@ -37,38 +36,39 @@ import (
|
||||
)
|
||||
|
||||
type MessageInterceptorFunc func(ctx context.Context, globalConfig *Config, req *msg.SendMsgReq) (*sdkws.MsgData, error)
|
||||
type (
|
||||
// MessageInterceptorChain defines a chain of message interceptor functions.
|
||||
MessageInterceptorChain []MessageInterceptorFunc
|
||||
|
||||
// MessageInterceptorChain defines a chain of message interceptor functions.
|
||||
type MessageInterceptorChain []MessageInterceptorFunc
|
||||
// MsgServer encapsulates dependencies required for message handling.
|
||||
msgServer struct {
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry // Service discovery registry for service registration.
|
||||
MsgDatabase controller.CommonMsgDatabase // Interface for message database operations.
|
||||
StreamMsgDatabase controller.StreamMsgDatabase
|
||||
Conversation *rpcclient.ConversationRpcClient // RPC client for conversation service.
|
||||
UserLocalCache *rpccache.UserLocalCache // Local cache for user data.
|
||||
FriendLocalCache *rpccache.FriendLocalCache // Local cache for friend data.
|
||||
GroupLocalCache *rpccache.GroupLocalCache // Local cache for group data.
|
||||
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
|
||||
Handlers MessageInterceptorChain // Chain of handlers for processing messages.
|
||||
notificationSender *rpcclient.NotificationSender // RPC client for sending notifications.
|
||||
msgNotificationSender *MsgNotificationSender // RPC client for sending msg notifications.
|
||||
config *Config // Global configuration settings.
|
||||
webhookClient *webhook.Client
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
RpcConfig config.Msg
|
||||
RedisConfig config.Redis
|
||||
MongodbConfig config.Mongo
|
||||
KafkaConfig config.Kafka
|
||||
NotificationConfig config.Notification
|
||||
Share config.Share
|
||||
WebhooksConfig config.Webhooks
|
||||
LocalCacheConfig config.LocalCache
|
||||
Discovery config.Discovery
|
||||
}
|
||||
|
||||
// MsgServer encapsulates dependencies required for message handling.
|
||||
type msgServer struct {
|
||||
msg.UnimplementedMsgServer
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry // Service discovery registry for service registration.
|
||||
MsgDatabase controller.CommonMsgDatabase // Interface for message database operations.
|
||||
UserLocalCache *rpccache.UserLocalCache // Local cache for user data.
|
||||
FriendLocalCache *rpccache.FriendLocalCache // Local cache for friend data.
|
||||
GroupLocalCache *rpccache.GroupLocalCache // Local cache for group data.
|
||||
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
|
||||
Handlers MessageInterceptorChain // Chain of handlers for processing messages.
|
||||
notificationSender *rpcclient.NotificationSender // RPC client for sending notifications.
|
||||
msgNotificationSender *MsgNotificationSender // RPC client for sending msg notifications.
|
||||
config *Config // Global configuration settings.
|
||||
webhookClient *webhook.Client
|
||||
conversationClient *rpcli.ConversationClient
|
||||
}
|
||||
Config struct {
|
||||
RpcConfig config.Msg
|
||||
RedisConfig config.Redis
|
||||
MongodbConfig config.Mongo
|
||||
KafkaConfig config.Kafka
|
||||
NotificationConfig config.Notification
|
||||
Share config.Share
|
||||
WebhooksConfig config.Webhooks
|
||||
LocalCacheConfig config.LocalCache
|
||||
Discovery config.Discovery
|
||||
}
|
||||
)
|
||||
|
||||
func (m *msgServer) addInterceptorHandler(interceptorFunc ...MessageInterceptorFunc) {
|
||||
m.Handlers = append(m.Handlers, interceptorFunc...)
|
||||
@@ -88,7 +88,11 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgModel := redis.NewMsgCache(rdb, msgDocModel)
|
||||
msgModel := redis.NewMsgCache(rdb)
|
||||
conversationClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
friendRpcClient := rpcclient.NewFriendRpcClient(client, config.Share.RpcRegisterName.Friend)
|
||||
seqConversation, err := mgo.NewSeqConversationMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -98,38 +102,26 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
streamMsg, err := mgo.NewStreamMsgMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
seqUserCache := redis.NewSeqUserCacheRedis(rdb, seqUser)
|
||||
msgDatabase, err := controller.NewCommonMsgDatabase(msgDocModel, msgModel, seqUserCache, seqConversationCache, &config.KafkaConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conversationClient := rpcli.NewConversationClient(conversationConn)
|
||||
s := &msgServer{
|
||||
Conversation: &conversationClient,
|
||||
MsgDatabase: msgDatabase,
|
||||
StreamMsgDatabase: controller.NewStreamMsgDatabase(streamMsg),
|
||||
RegisterCenter: client,
|
||||
UserLocalCache: rpccache.NewUserLocalCache(rpcli.NewUserClient(userConn), &config.LocalCacheConfig, rdb),
|
||||
GroupLocalCache: rpccache.NewGroupLocalCache(rpcli.NewGroupClient(groupConn), &config.LocalCacheConfig, rdb),
|
||||
UserLocalCache: rpccache.NewUserLocalCache(userRpcClient, &config.LocalCacheConfig, rdb),
|
||||
GroupLocalCache: rpccache.NewGroupLocalCache(groupRpcClient, &config.LocalCacheConfig, rdb),
|
||||
ConversationLocalCache: rpccache.NewConversationLocalCache(conversationClient, &config.LocalCacheConfig, rdb),
|
||||
FriendLocalCache: rpccache.NewFriendLocalCache(rpcli.NewRelationClient(friendConn), &config.LocalCacheConfig, rdb),
|
||||
FriendLocalCache: rpccache.NewFriendLocalCache(friendRpcClient, &config.LocalCacheConfig, rdb),
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
conversationClient: conversationClient,
|
||||
}
|
||||
|
||||
s.notificationSender = rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithLocalSendMsg(s.SendMsg))
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package msg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"time"
|
||||
)
|
||||
|
||||
const StreamDeadlineTime = time.Second * 60 * 10
|
||||
|
||||
func (m *msgServer) handlerStreamMsg(ctx context.Context, msgData *sdkws.MsgData) error {
|
||||
now := time.Now()
|
||||
val := &model.StreamMsg{
|
||||
ClientMsgID: msgData.ClientMsgID,
|
||||
ConversationID: msgprocessor.GetConversationIDByMsg(msgData),
|
||||
UserID: msgData.SendID,
|
||||
CreateTime: now,
|
||||
DeadlineTime: now.Add(StreamDeadlineTime),
|
||||
}
|
||||
return m.StreamMsgDatabase.CreateStreamMsg(ctx, val)
|
||||
}
|
||||
|
||||
func (m *msgServer) getStreamMsg(ctx context.Context, clientMsgID string) (*model.StreamMsg, error) {
|
||||
res, err := m.StreamMsgDatabase.GetStreamMsg(ctx, clientMsgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
now := time.Now()
|
||||
if !res.End && res.DeadlineTime.Before(now) {
|
||||
res.End = true
|
||||
res.DeadlineTime = now
|
||||
_ = m.StreamMsgDatabase.AppendStreamMsg(ctx, res.ClientMsgID, 0, nil, true, now)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) AppendStreamMsg(ctx context.Context, req *msg.AppendStreamMsgReq) (*msg.AppendStreamMsgResp, error) {
|
||||
res, err := m.getStreamMsg(ctx, req.ClientMsgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.End {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("stream msg is end")
|
||||
}
|
||||
if len(res.Packets) < int(req.StartIndex) {
|
||||
return nil, errs.ErrNoPermission.WrapMsg("start index is invalid")
|
||||
}
|
||||
if val := len(res.Packets) - int(req.StartIndex); val > 0 {
|
||||
exist := res.Packets[int(req.StartIndex):]
|
||||
for i, s := range exist {
|
||||
if len(req.Packets) == 0 {
|
||||
break
|
||||
}
|
||||
if s != req.Packets[i] {
|
||||
return nil, errs.ErrNoPermission.WrapMsg(fmt.Sprintf("packet %d has been written and is inconsistent", i))
|
||||
}
|
||||
req.StartIndex++
|
||||
req.Packets = req.Packets[1:]
|
||||
}
|
||||
}
|
||||
if len(req.Packets) == 0 && res.End == req.End {
|
||||
return &msg.AppendStreamMsgResp{}, nil
|
||||
}
|
||||
deadlineTime := time.Now().Add(StreamDeadlineTime)
|
||||
if err := m.StreamMsgDatabase.AppendStreamMsg(ctx, req.ClientMsgID, int(req.StartIndex), req.Packets, req.End, deadlineTime); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conversation, err := m.Conversation.GetConversation(ctx, res.UserID, res.ConversationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tips := &sdkws.StreamMsgTips{
|
||||
ConversationID: res.ConversationID,
|
||||
ClientMsgID: res.ClientMsgID,
|
||||
StartIndex: req.StartIndex,
|
||||
Packets: req.Packets,
|
||||
End: req.End,
|
||||
}
|
||||
var (
|
||||
recvID string
|
||||
sessionType int32
|
||||
)
|
||||
if conversation.GroupID == "" {
|
||||
sessionType = constant.SingleChatType
|
||||
recvID = conversation.UserID
|
||||
} else {
|
||||
sessionType = constant.ReadGroupChatType
|
||||
recvID = conversation.GroupID
|
||||
}
|
||||
m.msgNotificationSender.StreamMsgNotification(ctx, res.UserID, recvID, sessionType, tips)
|
||||
return &msg.AppendStreamMsgResp{}, nil
|
||||
}
|
||||
|
||||
func (m *msgServer) GetStreamMsg(ctx context.Context, req *msg.GetStreamMsgReq) (*msg.GetStreamMsgResp, error) {
|
||||
res, err := m.getStreamMsg(ctx, req.ClientMsgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msg.GetStreamMsgResp{
|
||||
ClientMsgID: res.ClientMsgID,
|
||||
ConversationID: res.ConversationID,
|
||||
UserID: res.UserID,
|
||||
Packets: res.Packets,
|
||||
End: res.End,
|
||||
CreateTime: res.CreateTime.UnixMilli(),
|
||||
DeadlineTime: res.DeadlineTime.UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (m *msgServer) GetSeqMessage(ctx context.Context, req *msg.GetSeqMessageReq
|
||||
NotificationMsgs: make(map[string]*sdkws.PullMsgs),
|
||||
}
|
||||
for _, conv := range req.Conversations {
|
||||
isEnd, endSeq, msgs, err := m.MsgDatabase.GetMessagesBySeqWithBounds(ctx, req.UserID, conv.ConversationID, conv.Seqs, req.GetOrder())
|
||||
_, _, msgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, conv.ConversationID, conv.Seqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -111,8 +111,6 @@ func (m *msgServer) GetSeqMessage(ctx context.Context, req *msg.GetSeqMessageReq
|
||||
}
|
||||
}
|
||||
pullMsgs.Msgs = append(pullMsgs.Msgs, msgs...)
|
||||
pullMsgs.IsEnd = isEnd
|
||||
pullMsgs.EndSeq = endSeq
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (s *friendServer) GetPaginationBlacks(ctx context.Context, req *relation.Ge
|
||||
return nil, err
|
||||
}
|
||||
resp = &relation.GetPaginationBlacksResp{}
|
||||
resp.Blacks, err = convert.BlackDB2Pb(ctx, blacks, s.userClient.GetUsersInfoMap)
|
||||
resp.Blacks, err = convert.BlackDB2Pb(ctx, blacks, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -81,7 +81,9 @@ func (s *friendServer) AddBlack(ctx context.Context, req *relation.AddBlackReq)
|
||||
if err := s.webhookBeforeAddBlack(ctx, &s.config.WebhooksConfig.BeforeAddBlack, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.userClient.CheckUser(ctx, []string{req.OwnerUserID, req.BlackUserID}); err != nil {
|
||||
|
||||
_, err := s.userRpcClient.GetUsersInfo(ctx, []string{req.OwnerUserID, req.BlackUserID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
black := model.Black{
|
||||
@@ -112,7 +114,7 @@ func (s *friendServer) GetSpecifiedBlacks(ctx context.Context, req *relation.Get
|
||||
return nil, errs.ErrArgs.WrapMsg("userIDList repeated")
|
||||
}
|
||||
|
||||
userMap, err := s.userClient.GetUsersInfoMap(ctx, req.UserIDList)
|
||||
userMap, err := s.userRpcClient.GetPublicUserInfoMap(ctx, req.UserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -130,26 +132,13 @@ func (s *friendServer) GetSpecifiedBlacks(ctx context.Context, req *relation.Get
|
||||
Blacks: make([]*sdkws.BlackInfo, 0, len(req.UserIDList)),
|
||||
}
|
||||
|
||||
toPublcUser := func(userID string) *sdkws.PublicUserInfo {
|
||||
v, ok := userMap[userID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return &sdkws.PublicUserInfo{
|
||||
UserID: v.UserID,
|
||||
Nickname: v.Nickname,
|
||||
FaceURL: v.FaceURL,
|
||||
Ex: v.Ex,
|
||||
}
|
||||
}
|
||||
|
||||
for _, userID := range req.UserIDList {
|
||||
if black := blackMap[userID]; black != nil {
|
||||
resp.Blacks = append(resp.Blacks,
|
||||
&sdkws.BlackInfo{
|
||||
OwnerUserID: black.OwnerUserID,
|
||||
CreateTime: black.CreateTime.UnixMilli(),
|
||||
BlackUserInfo: toPublcUser(userID),
|
||||
BlackUserInfo: userMap[userID],
|
||||
AddSource: black.AddSource,
|
||||
OperatorUserID: black.OperatorUserID,
|
||||
Ex: black.Ex,
|
||||
|
||||
@@ -16,7 +16,6 @@ package relation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
|
||||
"github.com/openimsdk/tools/mq/memamq"
|
||||
|
||||
@@ -32,6 +31,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -43,15 +43,15 @@ import (
|
||||
)
|
||||
|
||||
type friendServer struct {
|
||||
relation.UnimplementedFriendServer
|
||||
db controller.FriendDatabase
|
||||
blackDatabase controller.BlackDatabase
|
||||
notificationSender *FriendNotificationSender
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry
|
||||
config *Config
|
||||
webhookClient *webhook.Client
|
||||
queue *memamq.MemoryQueue
|
||||
userClient *rpcli.UserClient
|
||||
db controller.FriendDatabase
|
||||
blackDatabase controller.BlackDatabase
|
||||
userRpcClient *rpcclient.UserRpcClient
|
||||
notificationSender *FriendNotificationSender
|
||||
conversationRpcClient rpcclient.ConversationRpcClient
|
||||
RegisterCenter discovery.SvcDiscoveryRegistry
|
||||
config *Config
|
||||
webhookClient *webhook.Client
|
||||
queue *memamq.MemoryQueue
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -91,21 +91,15 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
return err
|
||||
}
|
||||
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userClient := rpcli.NewUserClient(userConn)
|
||||
// Initialize RPC clients
|
||||
userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
|
||||
// Initialize notification sender
|
||||
notificationSender := NewFriendNotificationSender(
|
||||
&config.NotificationConfig,
|
||||
rpcli.NewMsgClient(msgConn),
|
||||
WithRpcFunc(userClient.GetUsersInfo),
|
||||
&msgRpcClient,
|
||||
WithRpcFunc(userRpcClient.GetUsersInfo),
|
||||
)
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
|
||||
@@ -121,12 +115,13 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
blackMongoDB,
|
||||
redis.NewBlackCacheRedis(rdb, &config.LocalCacheConfig, blackMongoDB, redis.GetRocksCacheOptions()),
|
||||
),
|
||||
notificationSender: notificationSender,
|
||||
RegisterCenter: client,
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
queue: memamq.NewMemoryQueue(16, 1024*1024),
|
||||
userClient: userClient,
|
||||
userRpcClient: &userRpcClient,
|
||||
notificationSender: notificationSender,
|
||||
RegisterCenter: client,
|
||||
conversationRpcClient: rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation),
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
queue: memamq.NewMemoryQueue(16, 1024*1024),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -143,7 +138,7 @@ func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *relation.Apply
|
||||
if err = s.webhookBeforeAddFriend(ctx, &s.config.WebhooksConfig.BeforeAddFriend, req); err != nil && err != servererrs.ErrCallbackContinue {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.userClient.CheckUser(ctx, []string{req.ToUserID, req.FromUserID}); err != nil {
|
||||
if _, err := s.userRpcClient.GetUsersInfoMap(ctx, []string{req.ToUserID, req.FromUserID}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -167,8 +162,7 @@ func (s *friendServer) ImportFriends(ctx context.Context, req *relation.ImportFr
|
||||
if err := authverify.CheckAdmin(ctx, s.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.userClient.CheckUser(ctx, append([]string{req.OwnerUserID}, req.FriendUserIDs...)); err != nil {
|
||||
if _, err := s.userRpcClient.GetUsersInfo(ctx, append([]string{req.OwnerUserID}, req.FriendUserIDs...)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if datautil.Contain(req.OwnerUserID, req.FriendUserIDs...) {
|
||||
@@ -309,7 +303,7 @@ func (s *friendServer) getFriend(ctx context.Context, ownerUserID string, friend
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return convert.FriendsDB2Pb(ctx, friends, s.userClient.GetUsersInfoMap)
|
||||
return convert.FriendsDB2Pb(ctx, friends, s.userRpcClient.GetUsersInfoMap)
|
||||
}
|
||||
|
||||
// Get the list of friend requests sent out proactively.
|
||||
@@ -321,7 +315,7 @@ func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
resp = &relation.GetDesignatedFriendsApplyResp{}
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userClient.GetUsersInfoMap)
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -340,7 +334,7 @@ func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *rel
|
||||
}
|
||||
|
||||
resp = &relation.GetPaginationFriendsApplyToResp{}
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userClient.GetUsersInfoMap)
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -362,7 +356,7 @@ func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userClient.GetUsersInfoMap)
|
||||
resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -393,7 +387,7 @@ func (s *friendServer) GetPaginationFriends(ctx context.Context, req *relation.G
|
||||
}
|
||||
|
||||
resp = &relation.GetPaginationFriendsResp{}
|
||||
resp.FriendsInfo, err = convert.FriendsDB2Pb(ctx, friends, s.userClient.GetUsersInfoMap)
|
||||
resp.FriendsInfo, err = convert.FriendsDB2Pb(ctx, friends, s.userRpcClient.GetUsersInfoMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -426,7 +420,7 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *relatio
|
||||
return nil, errs.ErrArgs.WrapMsg("userIDList repeated")
|
||||
}
|
||||
|
||||
userMap, err := s.userClient.GetUsersInfoMap(ctx, req.UserIDList)
|
||||
userMap, err := s.userRpcClient.GetUsersInfoMap(ctx, req.UserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -530,3 +524,18 @@ func (s *friendServer) UpdateFriends(
|
||||
s.notificationSender.FriendsInfoUpdateNotification(ctx, req.OwnerUserID, req.FriendUserIDs)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *friendServer) GetIncrementalFriendsApplyTo(ctx context.Context, req *relation.GetIncrementalFriendsApplyToReq) (*relation.GetIncrementalFriendsApplyToResp, error) {
|
||||
// TODO implement me
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *friendServer) GetIncrementalFriendsApplyFrom(ctx context.Context, req *relation.GetIncrementalFriendsApplyFromReq) (*relation.GetIncrementalFriendsApplyFromResp, error) {
|
||||
// TODO implement me
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *friendServer) GetIncrementalBlacks(ctx context.Context, req *relation.GetIncrementalBlacksReq) (*relation.GetIncrementalBlacksResp, error) {
|
||||
// TODO implement me
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@ package relation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
|
||||
|
||||
@@ -27,8 +24,8 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
@@ -38,7 +35,7 @@ import (
|
||||
type FriendNotificationSender struct {
|
||||
*rpcclient.NotificationSender
|
||||
// Target not found err
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error)
|
||||
// db controller
|
||||
db controller.FriendDatabase
|
||||
}
|
||||
@@ -55,7 +52,7 @@ func WithDBFunc(
|
||||
fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error),
|
||||
) friendNotificationSenderOptions {
|
||||
return func(s *FriendNotificationSender) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
|
||||
users, err := fn(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -73,7 +70,7 @@ func WithRpcFunc(
|
||||
fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error),
|
||||
) friendNotificationSenderOptions {
|
||||
return func(s *FriendNotificationSender) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
|
||||
users, err := fn(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -87,11 +84,13 @@ func WithRpcFunc(
|
||||
}
|
||||
}
|
||||
|
||||
func NewFriendNotificationSender(conf *config.Notification, msgClient *rpcli.MsgClient, opts ...friendNotificationSenderOptions) *FriendNotificationSender {
|
||||
func NewFriendNotificationSender(
|
||||
conf *config.Notification,
|
||||
msgRpcClient *rpcclient.MessageRpcClient,
|
||||
opts ...friendNotificationSenderOptions,
|
||||
) *FriendNotificationSender {
|
||||
f := &FriendNotificationSender{
|
||||
NotificationSender: rpcclient.NewNotificationSender(conf, rpcclient.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msgClient.SendMsg(ctx, req)
|
||||
})),
|
||||
NotificationSender: rpcclient.NewNotificationSender(conf, rpcclient.WithRpcClient(msgRpcClient)),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(f)
|
||||
|
||||
+11
-10
@@ -19,9 +19,10 @@ import (
|
||||
"crypto/rand"
|
||||
"time"
|
||||
|
||||
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
@@ -49,14 +50,14 @@ func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq)
|
||||
platform := constant.PlatformID2Name[int(req.Platform)]
|
||||
for _, fileURL := range req.FileURLs {
|
||||
log := relationtb.Log{
|
||||
Platform: platform,
|
||||
UserID: userID,
|
||||
CreateTime: time.Now(),
|
||||
Url: fileURL.URL,
|
||||
FileName: fileURL.Filename,
|
||||
AppFramework: req.AppFramework,
|
||||
Version: req.Version,
|
||||
Ex: req.Ex,
|
||||
Platform: platform,
|
||||
UserID: userID,
|
||||
CreateTime: time.Now(),
|
||||
Url: fileURL.URL,
|
||||
FileName: fileURL.Filename,
|
||||
SystemType: req.SystemType,
|
||||
Version: req.Version,
|
||||
Ex: req.Ex,
|
||||
}
|
||||
for i := 0; i < 20; i++ {
|
||||
id := genLogID()
|
||||
@@ -148,7 +149,7 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
|
||||
for _, log := range logs {
|
||||
userIDs = append(userIDs, log.UserID)
|
||||
}
|
||||
userMap, err := t.userClient.GetUsersInfoMap(ctx, userIDs)
|
||||
userMap, err := t.userRpcClient.GetUsersInfoMap(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+41
-23
@@ -19,14 +19,17 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
@@ -285,35 +288,50 @@ func (t *thirdServer) apiAddress(prefix, name string) string {
|
||||
}
|
||||
|
||||
func (t *thirdServer) DeleteOutdatedData(ctx context.Context, req *third.DeleteOutdatedDataReq) (*third.DeleteOutdatedDataResp, error) {
|
||||
if err := authverify.CheckAdmin(ctx, t.config.Share.IMAdminUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
engine := t.config.RpcConfig.Object.Enable
|
||||
var conf config.Third
|
||||
expireTime := time.UnixMilli(req.ExpireTime)
|
||||
// Find all expired data in S3 database
|
||||
models, err := t.s3dataBase.FindExpirationObject(ctx, engine, expireTime, req.ObjectGroup, int64(req.Limit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var deltotal int
|
||||
findPagination := &sdkws.RequestPagination{
|
||||
PageNumber: 1,
|
||||
ShowNumber: 1000,
|
||||
}
|
||||
for i, obj := range models {
|
||||
if err := t.s3dataBase.DeleteSpecifiedData(ctx, engine, []string{obj.Name}); err != nil {
|
||||
for {
|
||||
total, models, err := t.s3dataBase.FindByExpires(ctx, expireTime, findPagination)
|
||||
if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
if err := t.s3dataBase.DelS3Key(ctx, engine, obj.Name); err != nil {
|
||||
return nil, err
|
||||
needDelObjectKeys := make([]string, 0)
|
||||
for _, model := range models {
|
||||
needDelObjectKeys = append(needDelObjectKeys, model.Key)
|
||||
}
|
||||
count, err := t.s3dataBase.GetKeyCount(ctx, engine, obj.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "delete s3 object record", "index", i, "s3", obj, "count", count)
|
||||
if count == 0 {
|
||||
if err := t.s3.DeleteObject(ctx, obj.Key); err != nil {
|
||||
return nil, err
|
||||
|
||||
needDelObjectKeys = datautil.Distinct(needDelObjectKeys)
|
||||
for _, key := range needDelObjectKeys {
|
||||
count, err := t.s3dataBase.FindNotDelByS3(ctx, key, expireTime)
|
||||
if err != nil && errs.Unwrap(err) != mongo.ErrNoDocuments {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
if int(count) < 1 && t.minio != nil {
|
||||
thumbnailKey, _ := t.getMinioImageThumbnailKey(ctx, key)
|
||||
|
||||
t.s3dataBase.DeleteObject(ctx, thumbnailKey)
|
||||
t.s3dataBase.DelS3Key(ctx, conf.Object.Enable, needDelObjectKeys...)
|
||||
t.s3dataBase.DeleteObject(ctx, key)
|
||||
}
|
||||
}
|
||||
for _, model := range models {
|
||||
err := t.s3dataBase.DeleteSpecifiedData(ctx, model.Engine, model.Name)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
}
|
||||
if total < int64(findPagination.ShowNumber) {
|
||||
break
|
||||
}
|
||||
deltotal += int(total)
|
||||
}
|
||||
return &third.DeleteOutdatedDataResp{Count: int32(len(models))}, nil
|
||||
log.ZDebug(ctx, "DeleteOutdatedData", "delete Total", deltotal)
|
||||
return &third.DeleteOutdatedDataResp{}, nil
|
||||
}
|
||||
|
||||
type FormDataMate struct {
|
||||
|
||||
+16
-15
@@ -17,14 +17,14 @@ package third
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/localcache"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
@@ -38,13 +38,12 @@ import (
|
||||
)
|
||||
|
||||
type thirdServer struct {
|
||||
third.UnimplementedThirdServer
|
||||
thirdDatabase controller.ThirdDatabase
|
||||
s3dataBase controller.S3Database
|
||||
userRpcClient rpcclient.UserRpcClient
|
||||
defaultExpire time.Duration
|
||||
config *Config
|
||||
s3 s3.Interface
|
||||
userClient *rpcli.UserClient
|
||||
minio *minio.Minio
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -79,11 +78,13 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
// Select the oss method according to the profile policy
|
||||
enable := config.RpcConfig.Object.Enable
|
||||
var (
|
||||
o s3.Interface
|
||||
o s3.Interface
|
||||
minioCli *minio.Minio
|
||||
)
|
||||
switch enable {
|
||||
case "minio":
|
||||
o, err = minio.NewMinio(ctx, redis.NewMinioCache(rdb), *config.MinioConfig.Build())
|
||||
minioCli, err = minio.NewMinio(ctx, redis.NewMinioCache(rdb), *config.MinioConfig.Build())
|
||||
o = minioCli
|
||||
case "cos":
|
||||
o, err = cos.NewCos(*config.RpcConfig.Object.Cos.Build())
|
||||
case "oss":
|
||||
@@ -96,22 +97,22 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.User)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
third.RegisterThirdServer(server, &thirdServer{
|
||||
thirdDatabase: controller.NewThirdDatabase(redis.NewThirdCache(rdb), logdb),
|
||||
userRpcClient: rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID),
|
||||
s3dataBase: controller.NewS3Database(rdb, o, s3db),
|
||||
defaultExpire: time.Hour * 24 * 7,
|
||||
config: config,
|
||||
s3: o,
|
||||
userClient: rpcli.NewUserClient(userConn),
|
||||
minio: minioCli,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *thirdServer) getMinioImageThumbnailKey(ctx context.Context, name string) (string, error) {
|
||||
return t.minio.GetImageThumbnailKey(ctx, name)
|
||||
}
|
||||
|
||||
func (t *thirdServer) FcmUpdateToken(ctx context.Context, req *third.FcmUpdateTokenReq) (resp *third.FcmUpdateTokenResp, err error) {
|
||||
err = t.thirdDatabase.FcmUpdateToken(ctx, req.Account, int(req.PlatformID), req.FcmToken, req.ExpireTime)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,21 +16,18 @@ package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
|
||||
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification/common_user"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/notification"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
type UserNotificationSender struct {
|
||||
*rpcclient.NotificationSender
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]common_user.CommonUser, error)
|
||||
getUsersInfo func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error)
|
||||
// db controller
|
||||
db controller.UserDatabase
|
||||
}
|
||||
@@ -47,7 +44,7 @@ func WithUserFunc(
|
||||
fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error),
|
||||
) userNotificationSenderOptions {
|
||||
return func(u *UserNotificationSender) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) {
|
||||
f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
|
||||
users, err := fn(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -61,11 +58,9 @@ func WithUserFunc(
|
||||
}
|
||||
}
|
||||
|
||||
func NewUserNotificationSender(config *Config, msgClient *rpcli.MsgClient, opts ...userNotificationSenderOptions) *UserNotificationSender {
|
||||
func NewUserNotificationSender(config *Config, msgRpcClient *rpcclient.MessageRpcClient, opts ...userNotificationSenderOptions) *UserNotificationSender {
|
||||
f := &UserNotificationSender{
|
||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msgClient.SendMsg(ctx, req)
|
||||
})),
|
||||
NotificationSender: rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithRpcClient(msgRpcClient)),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(f)
|
||||
|
||||
+12
-24
@@ -17,7 +17,6 @@ package user
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcli"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -40,6 +39,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
pbuser "github.com/openimsdk/protocol/user"
|
||||
@@ -52,16 +52,15 @@ import (
|
||||
)
|
||||
|
||||
type userServer struct {
|
||||
pbuser.UnimplementedUserServer
|
||||
online cache.OnlineCache
|
||||
db controller.UserDatabase
|
||||
friendNotificationSender *relation.FriendNotificationSender
|
||||
userNotificationSender *UserNotificationSender
|
||||
friendRpcClient *rpcclient.FriendRpcClient
|
||||
groupRpcClient *rpcclient.GroupRpcClient
|
||||
RegisterCenter registry.SvcDiscoveryRegistry
|
||||
config *Config
|
||||
webhookClient *webhook.Client
|
||||
groupClient *rpcli.GroupClient
|
||||
relationClient *rpcli.RelationClient
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -94,33 +93,22 @@ func Start(ctx context.Context, config *Config, client registry.SvcDiscoveryRegi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
friendConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Friend)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgClient := rpcli.NewMsgClient(msgConn)
|
||||
userCache := redis.NewUserCacheRedis(rdb, &config.LocalCacheConfig, userDB, redis.GetRocksCacheOptions())
|
||||
database := controller.NewUserDatabase(userDB, userCache, mgocli.GetTx())
|
||||
friendRpcClient := rpcclient.NewFriendRpcClient(client, config.Share.RpcRegisterName.Friend)
|
||||
groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
|
||||
msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
|
||||
localcache.InitLocalCache(&config.LocalCacheConfig)
|
||||
u := &userServer{
|
||||
online: redis.NewUserOnline(rdb),
|
||||
db: database,
|
||||
RegisterCenter: client,
|
||||
friendNotificationSender: relation.NewFriendNotificationSender(&config.NotificationConfig, msgClient, relation.WithDBFunc(database.FindWithError)),
|
||||
userNotificationSender: NewUserNotificationSender(config, msgClient, WithUserFunc(database.FindWithError)),
|
||||
friendRpcClient: &friendRpcClient,
|
||||
groupRpcClient: &groupRpcClient,
|
||||
friendNotificationSender: relation.NewFriendNotificationSender(&config.NotificationConfig, &msgRpcClient, relation.WithDBFunc(database.FindWithError)),
|
||||
userNotificationSender: NewUserNotificationSender(config, &msgRpcClient, WithUserFunc(database.FindWithError)),
|
||||
config: config,
|
||||
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
|
||||
|
||||
groupClient: rpcli.NewGroupClient(groupConn),
|
||||
relationClient: rpcli.NewRelationClient(friendConn),
|
||||
}
|
||||
pbuser.RegisterUserServer(server, u)
|
||||
return u.db.InitOnce(context.Background(), users)
|
||||
@@ -652,7 +640,7 @@ func (s *userServer) NotificationUserInfoUpdate(ctx context.Context, userID stri
|
||||
wg.Add(len(es))
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, es[0] = s.groupClient.NotificationUserInfoUpdate(ctx, &group.NotificationUserInfoUpdateReq{
|
||||
_, es[0] = s.groupRpcClient.Client.NotificationUserInfoUpdate(ctx, &group.NotificationUserInfoUpdateReq{
|
||||
UserID: userID,
|
||||
OldUserInfo: oldUserInfo,
|
||||
NewUserInfo: newUserInfo,
|
||||
@@ -661,7 +649,7 @@ func (s *userServer) NotificationUserInfoUpdate(ctx context.Context, userID stri
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, es[1] = s.relationClient.NotificationUserInfoUpdate(ctx, &friendpb.NotificationUserInfoUpdateReq{
|
||||
_, es[1] = s.friendRpcClient.Client.NotificationUserInfoUpdate(ctx, &friendpb.NotificationUserInfoUpdateReq{
|
||||
UserID: userID,
|
||||
OldUserInfo: oldUserInfo,
|
||||
NewUserInfo: newUserInfo,
|
||||
|
||||
+67
-52
@@ -16,11 +16,14 @@ package tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
@@ -55,68 +58,80 @@ func Start(ctx context.Context, config *CronTaskConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// thirdConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
conversationConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Conversation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srv := &cronServer{
|
||||
ctx: ctx,
|
||||
config: config,
|
||||
cron: cron.New(),
|
||||
msgClient: msg.NewMsgClient(msgConn),
|
||||
conversationClient: pbconversation.NewConversationClient(conversationConn),
|
||||
thirdClient: third.NewThirdClient(thirdConn),
|
||||
msgClient := msg.NewMsgClient(msgConn)
|
||||
conversationClient := pbconversation.NewConversationClient(conversationConn)
|
||||
// thirdClient := third.NewThirdClient(thirdConn)
|
||||
|
||||
crontab := cron.New()
|
||||
|
||||
// scheduled hard delete outdated Msgs in specific time.
|
||||
clearMsgFunc := func() {
|
||||
now := time.Now()
|
||||
deltime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.RetainChatRecords))
|
||||
ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deltime.UnixMilli()))
|
||||
log.ZDebug(ctx, "clear chat records", "deltime", deltime, "timestamp", deltime.UnixMilli())
|
||||
|
||||
if _, err := msgClient.ClearMsg(ctx, &msg.ClearMsgReq{Timestamp: deltime.UnixMilli()}); err != nil {
|
||||
log.ZError(ctx, "cron clear chat records failed", err, "deltime", deltime, "cont", time.Since(now))
|
||||
return
|
||||
}
|
||||
log.ZDebug(ctx, "cron clear chat records success", "deltime", deltime, "cont", time.Since(now))
|
||||
}
|
||||
if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, clearMsgFunc); err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
if err := srv.registerClearS3(); err != nil {
|
||||
return err
|
||||
// scheduled soft delete outdated Msgs in specific time when user set `is_msg_destruct` feature.
|
||||
msgDestructFunc := func() {
|
||||
now := time.Now()
|
||||
ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), now.UnixMilli()))
|
||||
log.ZDebug(ctx, "msg destruct cron start", "now", now)
|
||||
|
||||
conversations, err := conversationClient.GetConversationsNeedDestructMsgs(ctx, &pbconversation.GetConversationsNeedDestructMsgsReq{})
|
||||
if err != nil {
|
||||
log.ZError(ctx, "Get conversation need Destruct msgs failed.", err)
|
||||
return
|
||||
} else {
|
||||
_, err := msgClient.DestructMsgs(ctx, &msg.DestructMsgsReq{Conversations: conversations.Conversations})
|
||||
if err != nil {
|
||||
log.ZError(ctx, "Destruct Msgs failed.", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.ZDebug(ctx, "msg destruct cron task completed", "cont", time.Since(now))
|
||||
}
|
||||
if err := srv.registerDeleteMsg(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.registerClearUserMsg(); err != nil {
|
||||
return err
|
||||
if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, msgDestructFunc); err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
// // scheduled delete outdated file Objects and their datas in specific time.
|
||||
// deleteObjectFunc := func() {
|
||||
// now := time.Now()
|
||||
// deleteTime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.FileExpireTime))
|
||||
// ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deleteTime.UnixMilli()))
|
||||
// log.ZDebug(ctx, "deleteoutDatedData ", "deletetime", deleteTime, "timestamp", deleteTime.UnixMilli())
|
||||
// if _, err := thirdClient.DeleteOutdatedData(ctx, &third.DeleteOutdatedDataReq{ExpireTime: deleteTime.UnixMilli()}); err != nil {
|
||||
// log.ZError(ctx, "cron deleteoutDatedData failed", err, "deleteTime", deleteTime, "cont", time.Since(now))
|
||||
// return
|
||||
// }
|
||||
// log.ZDebug(ctx, "cron deleteoutDatedData success", "deltime", deleteTime, "cont", time.Since(now))
|
||||
// }
|
||||
// if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, deleteObjectFunc); err != nil {
|
||||
// return errs.Wrap(err)
|
||||
// }
|
||||
|
||||
log.ZDebug(ctx, "start cron task", "CronExecuteTime", config.CronTask.CronExecuteTime)
|
||||
srv.cron.Start()
|
||||
crontab.Start()
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
type cronServer struct {
|
||||
ctx context.Context
|
||||
config *CronTaskConfig
|
||||
cron *cron.Cron
|
||||
msgClient msg.MsgClient
|
||||
conversationClient pbconversation.ConversationClient
|
||||
thirdClient third.ThirdClient
|
||||
}
|
||||
|
||||
func (c *cronServer) registerClearS3() error {
|
||||
if c.config.CronTask.FileExpireTime <= 0 || len(c.config.CronTask.DeleteObjectType) == 0 {
|
||||
log.ZInfo(c.ctx, "disable scheduled cleanup of s3", "fileExpireTime", c.config.CronTask.FileExpireTime, "deleteObjectType", c.config.CronTask.DeleteObjectType)
|
||||
return nil
|
||||
}
|
||||
_, err := c.cron.AddFunc(c.config.CronTask.CronExecuteTime, c.clearS3)
|
||||
return errs.WrapMsg(err, "failed to register clear s3 cron task")
|
||||
}
|
||||
|
||||
func (c *cronServer) registerDeleteMsg() error {
|
||||
if c.config.CronTask.RetainChatRecords <= 0 {
|
||||
log.ZInfo(c.ctx, "disable scheduled cleanup of chat records", "retainChatRecords", c.config.CronTask.RetainChatRecords)
|
||||
return nil
|
||||
}
|
||||
_, err := c.cron.AddFunc(c.config.CronTask.CronExecuteTime, c.deleteMsg)
|
||||
return errs.WrapMsg(err, "failed to register delete msg cron task")
|
||||
}
|
||||
|
||||
func (c *cronServer) registerClearUserMsg() error {
|
||||
_, err := c.cron.AddFunc(c.config.CronTask.CronExecuteTime, c.clearUserMsg)
|
||||
return errs.WrapMsg(err, "failed to register clear user msg cron task")
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
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()
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openimsdk/protocol/msg"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *cronServer) deleteMsg() {
|
||||
now := time.Now()
|
||||
deltime := now.Add(-time.Hour * 24 * time.Duration(c.config.CronTask.RetainChatRecords))
|
||||
operationID := fmt.Sprintf("cron_msg_%d_%d", os.Getpid(), deltime.UnixMilli())
|
||||
ctx := mcontext.SetOperationID(c.ctx, operationID)
|
||||
log.ZDebug(ctx, "Destruct chat records", "deltime", deltime, "timestamp", deltime.UnixMilli())
|
||||
const (
|
||||
deleteCount = 10000
|
||||
deleteLimit = 50
|
||||
)
|
||||
var count int
|
||||
for i := 1; i <= deleteCount; i++ {
|
||||
ctx := mcontext.SetOperationID(c.ctx, fmt.Sprintf("%s_%d", operationID, i))
|
||||
resp, err := c.msgClient.DestructMsgs(ctx, &msg.DestructMsgsReq{Timestamp: deltime.UnixMilli(), Limit: deleteLimit})
|
||||
if err != nil {
|
||||
log.ZError(ctx, "cron destruct chat records failed", err)
|
||||
break
|
||||
}
|
||||
count += int(resp.Count)
|
||||
if resp.Count < deleteLimit {
|
||||
break
|
||||
}
|
||||
}
|
||||
log.ZDebug(ctx, "cron destruct chat records end", "deltime", deltime, "cont", time.Since(now), "count", count)
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openimsdk/protocol/third"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *cronServer) clearS3() {
|
||||
start := time.Now()
|
||||
deleteTime := start.Add(-time.Hour * 24 * time.Duration(c.config.CronTask.FileExpireTime))
|
||||
operationID := fmt.Sprintf("cron_s3_%d_%d", os.Getpid(), deleteTime.UnixMilli())
|
||||
ctx := mcontext.SetOperationID(c.ctx, operationID)
|
||||
log.ZDebug(ctx, "deleteoutDatedData", "deletetime", deleteTime, "timestamp", deleteTime.UnixMilli())
|
||||
const (
|
||||
deleteCount = 10000
|
||||
deleteLimit = 100
|
||||
)
|
||||
|
||||
var count int
|
||||
for i := 1; i <= deleteCount; i++ {
|
||||
resp, err := c.thirdClient.DeleteOutdatedData(ctx, &third.DeleteOutdatedDataReq{ExpireTime: deleteTime.UnixMilli(), ObjectGroup: c.config.CronTask.DeleteObjectType, Limit: deleteLimit})
|
||||
if err != nil {
|
||||
log.ZError(ctx, "cron deleteoutDatedData failed", err)
|
||||
return
|
||||
}
|
||||
count += int(resp.Count)
|
||||
if resp.Count < deleteLimit {
|
||||
break
|
||||
}
|
||||
}
|
||||
log.ZDebug(ctx, "cron deleteoutDatedData success", "deltime", deleteTime, "cont", time.Since(start), "count", count)
|
||||
}
|
||||
|
||||
// var req *third.DeleteOutdatedDataReq
|
||||
// count1, err := ExtractField(ctx, c.thirdClient.DeleteOutdatedData, req, (*third.DeleteOutdatedDataResp).GetCount)
|
||||
//
|
||||
// c.thirdClient.DeleteOutdatedData(ctx, &third.DeleteOutdatedDataReq{})
|
||||
// msggateway.GetUsersOnlineStatusCaller.Invoke(ctx, &msggateway.GetUsersOnlineStatusReq{})
|
||||
//
|
||||
// var cli ThirdClient
|
||||
//
|
||||
// c111, err := cli.DeleteOutdatedData(ctx, 100)
|
||||
//
|
||||
// cli.ThirdClient.DeleteOutdatedData(ctx, &third.DeleteOutdatedDataReq{})
|
||||
//
|
||||
// cli.AuthSign(ctx, &third.AuthSignReq{})
|
||||
//
|
||||
// cli.SetAppBadge()
|
||||
//
|
||||
//}
|
||||
//
|
||||
//func extractField[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) {
|
||||
// resp, err := fn(ctx, req)
|
||||
// if err != nil {
|
||||
// var c C
|
||||
// return c, err
|
||||
// }
|
||||
// return get(resp), nil
|
||||
//}
|
||||
//
|
||||
//func ignore(_ any, err error) error {
|
||||
// return err
|
||||
//}
|
||||
//
|
||||
//type ThirdClient struct {
|
||||
// third.ThirdClient
|
||||
//}
|
||||
//
|
||||
//func (c *ThirdClient) DeleteOutdatedData(ctx context.Context, expireTime int64) (int32, error) {
|
||||
// return extractField(ctx, c.ThirdClient.DeleteOutdatedData, &third.DeleteOutdatedDataReq{ExpireTime: expireTime}, (*third.DeleteOutdatedDataResp).GetCount)
|
||||
//}
|
||||
//
|
||||
//func (c *ThirdClient) DeleteOutdatedData1(ctx context.Context, expireTime int64) error {
|
||||
// return ignore(c.ThirdClient.DeleteOutdatedData(ctx, &third.DeleteOutdatedDataReq{ExpireTime: expireTime}))
|
||||
//}
|
||||
@@ -1,34 +0,0 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
pbconversation "github.com/openimsdk/protocol/conversation"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *cronServer) clearUserMsg() {
|
||||
now := time.Now()
|
||||
operationID := fmt.Sprintf("cron_user_msg_%d_%d", os.Getpid(), now.UnixMilli())
|
||||
ctx := mcontext.SetOperationID(c.ctx, operationID)
|
||||
log.ZDebug(ctx, "clear user msg cron start")
|
||||
const (
|
||||
deleteCount = 10000
|
||||
deleteLimit = 100
|
||||
)
|
||||
var count int
|
||||
for i := 1; i <= deleteCount; i++ {
|
||||
resp, err := c.conversationClient.ClearUserConversationMsg(ctx, &pbconversation.ClearUserConversationMsgReq{Timestamp: now.UnixMilli(), Limit: deleteLimit})
|
||||
if err != nil {
|
||||
log.ZError(ctx, "ClearUserConversationMsg failed.", err)
|
||||
return
|
||||
}
|
||||
count += int(resp.Count)
|
||||
if resp.Count < deleteLimit {
|
||||
break
|
||||
}
|
||||
}
|
||||
log.ZDebug(ctx, "clear user msg cron task completed", "cont", time.Since(now), "count", count)
|
||||
}
|
||||
@@ -81,6 +81,11 @@ type TextElem struct {
|
||||
Content string `json:"content" validate:"required"`
|
||||
}
|
||||
|
||||
type StreamMsgElem struct {
|
||||
Type string `mapstructure:"type" validate:"required"`
|
||||
Content string `mapstructure:"content" validate:"required"`
|
||||
}
|
||||
|
||||
type RevokeElem struct {
|
||||
RevokeMsgClientID string `mapstructure:"revokeMsgClientID" validate:"required"`
|
||||
}
|
||||
|
||||
@@ -113,10 +113,9 @@ type API struct {
|
||||
}
|
||||
|
||||
type CronTask struct {
|
||||
CronExecuteTime string `mapstructure:"cronExecuteTime"`
|
||||
RetainChatRecords int `mapstructure:"retainChatRecords"`
|
||||
FileExpireTime int `mapstructure:"fileExpireTime"`
|
||||
DeleteObjectType []string `mapstructure:"deleteObjectType"`
|
||||
CronExecuteTime string `mapstructure:"cronExecuteTime"`
|
||||
RetainChatRecords int `mapstructure:"retainChatRecords"`
|
||||
FileExpireTime int `mapstructure:"fileExpireTime"`
|
||||
}
|
||||
|
||||
type OfflinePushConfig struct {
|
||||
|
||||
@@ -80,18 +80,9 @@ func Db2PbGroupMember(m *model.GroupMember) *sdkws.GroupMemberFullInfo {
|
||||
}
|
||||
}
|
||||
|
||||
func Db2PbGroupRequest(m *model.GroupRequest, user *sdkws.UserInfo, group *sdkws.GroupInfo) *sdkws.GroupRequest {
|
||||
var pu *sdkws.PublicUserInfo
|
||||
if user != nil {
|
||||
pu = &sdkws.PublicUserInfo{
|
||||
UserID: user.UserID,
|
||||
Nickname: user.Nickname,
|
||||
FaceURL: user.FaceURL,
|
||||
Ex: user.Ex,
|
||||
}
|
||||
}
|
||||
func Db2PbGroupRequest(m *model.GroupRequest, user *sdkws.PublicUserInfo, group *sdkws.GroupInfo) *sdkws.GroupRequest {
|
||||
return &sdkws.GroupRequest{
|
||||
UserInfo: pu,
|
||||
UserInfo: user,
|
||||
GroupInfo: group,
|
||||
HandleResult: m.HandleResult,
|
||||
ReqMsg: m.ReqMsg,
|
||||
|
||||
@@ -68,9 +68,13 @@ func Start[T any](ctx context.Context, discovery *config.Discovery, prometheusCo
|
||||
|
||||
defer client.Close()
|
||||
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
|
||||
registerIP, err = network.GetRpcRegisterIP(registerIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// var reg *prometheus.Registry
|
||||
// var metric *grpcprometheus.ServerMetrics
|
||||
//var reg *prometheus.Registry
|
||||
//var metric *grpcprometheus.ServerMetrics
|
||||
if prometheusConfig.Enable {
|
||||
//cusMetrics := prommetrics.GetGrpcCusMetrics(rpcRegisterName, share)
|
||||
//reg, metric, _ = prommetrics.NewGrpcPromObj(cusMetrics)
|
||||
|
||||
+38
-4
@@ -15,16 +15,50 @@
|
||||
package cachekey
|
||||
|
||||
import (
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
sendMsgFailedFlag = "SEND_MSG_FAILED_FLAG:"
|
||||
messageCache = "MSG_CACHE:"
|
||||
messageCache = "MESSAGE_CACHE:"
|
||||
messageDelUserList = "MESSAGE_DEL_USER_LIST:"
|
||||
userDelMessagesList = "USER_DEL_MESSAGES_LIST:"
|
||||
sendMsgFailedFlag = "SEND_MSG_FAILED_FLAG:"
|
||||
exTypeKeyLocker = "EX_LOCK:"
|
||||
reactionExSingle = "EX_SINGLE_"
|
||||
reactionWriteGroup = "EX_GROUP_"
|
||||
reactionReadGroup = "EX_SUPER_GROUP_"
|
||||
reactionNotification = "EX_NOTIFICATION_"
|
||||
)
|
||||
|
||||
func GetMsgCacheKey(conversationID string, seq int64) string {
|
||||
return messageCache + conversationID + ":" + strconv.Itoa(int(seq))
|
||||
func GetMessageCacheKey(conversationID string, seq int64) string {
|
||||
return messageCache + conversationID + "_" + strconv.Itoa(int(seq))
|
||||
}
|
||||
|
||||
func GetMessageDelUserListKey(conversationID string, seq int64) string {
|
||||
return messageDelUserList + conversationID + ":" + strconv.Itoa(int(seq))
|
||||
}
|
||||
|
||||
func GetUserDelListKey(conversationID, userID string) string {
|
||||
return userDelMessagesList + conversationID + ":" + userID
|
||||
}
|
||||
|
||||
func GetMessageReactionExKey(clientMsgID string, sessionType int32) string {
|
||||
switch sessionType {
|
||||
case constant.SingleChatType:
|
||||
return reactionExSingle + clientMsgID
|
||||
case constant.WriteGroupChatType:
|
||||
return reactionWriteGroup + clientMsgID
|
||||
case constant.ReadGroupChatType:
|
||||
return reactionReadGroup + clientMsgID
|
||||
case constant.NotificationChatType:
|
||||
return reactionNotification + clientMsgID
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
func GetLockMessageTypeKey(clientMsgID string, TypeKey string) string {
|
||||
return exTypeKeyLocker + clientMsgID + "_" + TypeKey
|
||||
}
|
||||
|
||||
func GetSendMsgKey(id string) string {
|
||||
|
||||
Vendored
+14
-5
@@ -16,14 +16,23 @@ package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
type MsgCache interface {
|
||||
GetMessagesBySeq(ctx context.Context, conversationID string, seqs []int64) (seqMsg []*sdkws.MsgData, failedSeqList []int64, err error)
|
||||
SetMessagesToCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int, error)
|
||||
DeleteMessagesFromCache(ctx context.Context, conversationID string, seqs []int64) error
|
||||
SetSendMsgStatus(ctx context.Context, id string, status int32) error
|
||||
GetSendMsgStatus(ctx context.Context, id string) (int32, error)
|
||||
|
||||
GetMessageBySeqs(ctx context.Context, conversationID string, seqs []int64) ([]*model.MsgInfoModel, error)
|
||||
DelMessageBySeqs(ctx context.Context, conversationID string, seqs []int64) error
|
||||
SetMessageBySeqs(ctx context.Context, conversationID string, msgs []*model.MsgInfoModel) error
|
||||
JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error)
|
||||
GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error)
|
||||
DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error
|
||||
SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error)
|
||||
GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error)
|
||||
SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error
|
||||
LockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error
|
||||
UnLockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error
|
||||
}
|
||||
|
||||
+128
-52
@@ -2,12 +2,10 @@ package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/dtm-labs/rockscache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
|
||||
"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/msgprocessor"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -15,26 +13,76 @@ import (
|
||||
) //
|
||||
|
||||
// msgCacheTimeout is expiration time of message cache, 86400 seconds
|
||||
const msgCacheTimeout = time.Hour * 24
|
||||
const msgCacheTimeout = 86400
|
||||
|
||||
func NewMsgCache(client redis.UniversalClient, db database.Msg) cache.MsgCache {
|
||||
return &msgCache{
|
||||
rdb: client,
|
||||
rcClient: rockscache.NewClient(client, *GetRocksCacheOptions()),
|
||||
msgDocDatabase: db,
|
||||
}
|
||||
func NewMsgCache(client redis.UniversalClient) cache.MsgCache {
|
||||
return &msgCache{rdb: client}
|
||||
}
|
||||
|
||||
type msgCache struct {
|
||||
rdb redis.UniversalClient
|
||||
rcClient *rockscache.Client
|
||||
msgDocDatabase database.Msg
|
||||
rdb redis.UniversalClient
|
||||
}
|
||||
|
||||
func (c *msgCache) getMessageCacheKey(conversationID string, seq int64) string {
|
||||
return cachekey.GetMessageCacheKey(conversationID, seq)
|
||||
}
|
||||
func (c *msgCache) getMessageDelUserListKey(conversationID string, seq int64) string {
|
||||
return cachekey.GetMessageDelUserListKey(conversationID, seq)
|
||||
}
|
||||
|
||||
func (c *msgCache) getUserDelList(conversationID, userID string) string {
|
||||
return cachekey.GetUserDelListKey(conversationID, userID)
|
||||
}
|
||||
|
||||
func (c *msgCache) getSendMsgKey(id string) string {
|
||||
return cachekey.GetSendMsgKey(id)
|
||||
}
|
||||
|
||||
func (c *msgCache) getLockMessageTypeKey(clientMsgID string, TypeKey string) string {
|
||||
return cachekey.GetLockMessageTypeKey(clientMsgID, TypeKey)
|
||||
}
|
||||
|
||||
func (c *msgCache) getMessageReactionExPrefix(clientMsgID string, sessionType int32) string {
|
||||
return cachekey.GetMessageReactionExKey(clientMsgID, sessionType)
|
||||
}
|
||||
|
||||
func (c *msgCache) SetMessagesToCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int, error) {
|
||||
msgMap := datautil.SliceToMap(msgs, func(msg *sdkws.MsgData) string {
|
||||
return c.getMessageCacheKey(conversationID, msg.Seq)
|
||||
})
|
||||
keys := datautil.Slice(msgs, func(msg *sdkws.MsgData) string {
|
||||
return c.getMessageCacheKey(conversationID, msg.Seq)
|
||||
})
|
||||
err := ProcessKeysBySlot(ctx, c.rdb, keys, func(ctx context.Context, slot int64, keys []string) error {
|
||||
var values []string
|
||||
for _, key := range keys {
|
||||
if msg, ok := msgMap[key]; ok {
|
||||
s, err := msgprocessor.Pb2String(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
values = append(values, s)
|
||||
}
|
||||
}
|
||||
return LuaSetBatchWithCommonExpire(ctx, c.rdb, keys, values, msgCacheTimeout)
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(msgs), nil
|
||||
}
|
||||
|
||||
func (c *msgCache) DeleteMessagesFromCache(ctx context.Context, conversationID string, seqs []int64) error {
|
||||
var keys []string
|
||||
for _, seq := range seqs {
|
||||
keys = append(keys, c.getMessageCacheKey(conversationID, seq))
|
||||
}
|
||||
|
||||
return ProcessKeysBySlot(ctx, c.rdb, keys, func(ctx context.Context, slot int64, keys []string) error {
|
||||
return LuaDeleteBatch(ctx, c.rdb, keys)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *msgCache) SetSendMsgStatus(ctx context.Context, id string, status int32) error {
|
||||
return errs.Wrap(c.rdb.Set(ctx, c.getSendMsgKey(id), status, time.Hour*24).Err())
|
||||
}
|
||||
@@ -44,53 +92,81 @@ func (c *msgCache) GetSendMsgStatus(ctx context.Context, id string) (int32, erro
|
||||
return int32(result), errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (c *msgCache) GetMessageBySeqs(ctx context.Context, conversationID string, seqs []int64) ([]*model.MsgInfoModel, error) {
|
||||
if len(seqs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
getKey := func(seq int64) string {
|
||||
return cachekey.GetMsgCacheKey(conversationID, seq)
|
||||
}
|
||||
getMsgID := func(msg *model.MsgInfoModel) int64 {
|
||||
return msg.Msg.Seq
|
||||
}
|
||||
find := func(ctx context.Context, seqs []int64) ([]*model.MsgInfoModel, error) {
|
||||
return c.msgDocDatabase.FindSeqs(ctx, conversationID, seqs)
|
||||
}
|
||||
return batchGetCache2(ctx, c.rcClient, msgCacheTimeout, seqs, getKey, getMsgID, find)
|
||||
func (c *msgCache) LockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error {
|
||||
key := c.getLockMessageTypeKey(clientMsgID, TypeKey)
|
||||
return errs.Wrap(c.rdb.SetNX(ctx, key, 1, time.Minute).Err())
|
||||
}
|
||||
|
||||
func (c *msgCache) DelMessageBySeqs(ctx context.Context, conversationID string, seqs []int64) error {
|
||||
if len(seqs) == 0 {
|
||||
return nil
|
||||
}
|
||||
keys := datautil.Slice(seqs, func(seq int64) string {
|
||||
return cachekey.GetMsgCacheKey(conversationID, seq)
|
||||
})
|
||||
slotKeys, err := groupKeysBySlot(ctx, getRocksCacheRedisClient(c.rcClient), keys)
|
||||
func (c *msgCache) UnLockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error {
|
||||
key := c.getLockMessageTypeKey(clientMsgID, TypeKey)
|
||||
return errs.Wrap(c.rdb.Del(ctx, key).Err())
|
||||
}
|
||||
|
||||
func (c *msgCache) JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error) {
|
||||
n, err := c.rdb.Exists(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType)).Result()
|
||||
if err != nil {
|
||||
return err
|
||||
return false, errs.Wrap(err)
|
||||
}
|
||||
for _, keys := range slotKeys {
|
||||
if err := c.rcClient.TagAsDeletedBatch2(ctx, keys); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return n > 0, nil
|
||||
}
|
||||
|
||||
func (c *msgCache) SetMessageBySeqs(ctx context.Context, conversationID string, msgs []*model.MsgInfoModel) error {
|
||||
for _, msg := range msgs {
|
||||
if msg == nil || msg.Msg == nil || msg.Msg.Seq <= 0 {
|
||||
continue
|
||||
}
|
||||
data, err := json.Marshal(msg)
|
||||
func (c *msgCache) SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error {
|
||||
return errs.Wrap(c.rdb.HSet(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType), typeKey, value).Err())
|
||||
}
|
||||
|
||||
func (c *msgCache) SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error) {
|
||||
val, err := c.rdb.Expire(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType), expiration).Result()
|
||||
return val, errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (c *msgCache) GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error) {
|
||||
val, err := c.rdb.HGet(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType), typeKey).Result()
|
||||
return val, errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (c *msgCache) GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error) {
|
||||
val, err := c.rdb.HGetAll(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType)).Result()
|
||||
return val, errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (c *msgCache) DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error {
|
||||
return errs.Wrap(c.rdb.HDel(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType), subKey).Err())
|
||||
}
|
||||
|
||||
func (c *msgCache) GetMessagesBySeq(ctx context.Context, conversationID string, seqs []int64) (seqMsgs []*sdkws.MsgData, failedSeqs []int64, err error) {
|
||||
var keys []string
|
||||
keySeqMap := make(map[string]int64, 10)
|
||||
for _, seq := range seqs {
|
||||
key := c.getMessageCacheKey(conversationID, seq)
|
||||
keys = append(keys, key)
|
||||
keySeqMap[key] = seq
|
||||
}
|
||||
err = ProcessKeysBySlot(ctx, c.rdb, keys, func(ctx context.Context, slot int64, keys []string) error {
|
||||
result, err := LuaGetBatch(ctx, c.rdb, keys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.rcClient.RawSet(ctx, cachekey.GetMsgCacheKey(conversationID, msg.Msg.Seq), string(data), msgCacheTimeout); err != nil {
|
||||
return err
|
||||
for i, value := range result {
|
||||
seq := keySeqMap[keys[i]]
|
||||
if value == nil {
|
||||
failedSeqs = append(failedSeqs, seq)
|
||||
continue
|
||||
}
|
||||
|
||||
msg := &sdkws.MsgData{}
|
||||
msgString, ok := value.(string)
|
||||
if !ok || msgprocessor.String2Pb(msgString, msg) != nil {
|
||||
failedSeqs = append(failedSeqs, seq)
|
||||
continue
|
||||
}
|
||||
seqMsgs = append(seqMsgs, msg)
|
||||
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return nil
|
||||
return seqMsgs, failedSeqs, nil
|
||||
}
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
// 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 redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_msgCache_SetMessagesToCache(t *testing.T) {
|
||||
type fields struct {
|
||||
rdb redis.UniversalClient
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
conversationID string
|
||||
msgs []*sdkws.MsgData
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want int
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{"test1", fields{rdb: redis.NewClient(&redis.Options{Addr: "localhost:16379", Username: "", Password: "openIM123", DB: 0})}, args{context.Background(),
|
||||
"cid", []*sdkws.MsgData{{Seq: 1}, {Seq: 2}, {Seq: 3}}}, 3, assert.NoError},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &msgCache{
|
||||
rdb: tt.fields.rdb,
|
||||
}
|
||||
got, err := c.SetMessagesToCache(tt.args.ctx, tt.args.conversationID, tt.args.msgs)
|
||||
if !tt.wantErr(t, err, fmt.Sprintf("SetMessagesToCache(%v, %v, %v)", tt.args.ctx, tt.args.conversationID, tt.args.msgs)) {
|
||||
return
|
||||
}
|
||||
assert.Equalf(t, tt.want, got, "SetMessagesToCache(%v, %v, %v)", tt.args.ctx, tt.args.conversationID, tt.args.msgs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_msgCache_GetMessagesBySeq(t *testing.T) {
|
||||
type fields struct {
|
||||
rdb redis.UniversalClient
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
conversationID string
|
||||
seqs []int64
|
||||
}
|
||||
var failedSeq []int64
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantSeqMsgs []*sdkws.MsgData
|
||||
wantFailedSeqs []int64
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{"test1", fields{rdb: redis.NewClient(&redis.Options{Addr: "localhost:16379", Password: "openIM123", DB: 0})},
|
||||
args{context.Background(), "cid", []int64{1, 2, 3}},
|
||||
[]*sdkws.MsgData{{Seq: 1}, {Seq: 2}, {Seq: 3}}, failedSeq, assert.NoError},
|
||||
{"test2", fields{rdb: redis.NewClient(&redis.Options{Addr: "localhost:16379", Password: "openIM123", DB: 0})},
|
||||
args{context.Background(), "cid", []int64{4, 5, 6}},
|
||||
nil, []int64{4, 5, 6}, assert.NoError},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &msgCache{
|
||||
rdb: tt.fields.rdb,
|
||||
}
|
||||
gotSeqMsgs, gotFailedSeqs, err := c.GetMessagesBySeq(tt.args.ctx, tt.args.conversationID, tt.args.seqs)
|
||||
if !tt.wantErr(t, err, fmt.Sprintf("GetMessagesBySeq(%v, %v, %v)", tt.args.ctx, tt.args.conversationID, tt.args.seqs)) {
|
||||
return
|
||||
}
|
||||
equalMsgDataSlices(t, tt.wantSeqMsgs, gotSeqMsgs)
|
||||
assert.Equalf(t, tt.wantFailedSeqs, gotFailedSeqs, "GetMessagesBySeq(%v, %v, %v)", tt.args.ctx, tt.args.conversationID, tt.args.seqs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func equalMsgDataSlices(t *testing.T, expected, actual []*sdkws.MsgData) {
|
||||
assert.Equal(t, len(expected), len(actual), "Slices have different lengths")
|
||||
for i := range expected {
|
||||
assert.True(t, proto.Equal(expected[i], actual[i]), "Element %d not equal: expected %v, got %v", i, expected[i], actual[i])
|
||||
}
|
||||
}
|
||||
|
||||
func Test_msgCache_DeleteMessagesFromCache(t *testing.T) {
|
||||
type fields struct {
|
||||
rdb redis.UniversalClient
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
conversationID string
|
||||
seqs []int64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{"test1", fields{rdb: redis.NewClient(&redis.Options{Addr: "localhost:16379", Password: "openIM123"})},
|
||||
args{context.Background(), "cid", []int64{1, 2, 3}}, assert.NoError},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &msgCache{
|
||||
rdb: tt.fields.rdb,
|
||||
}
|
||||
tt.wantErr(t, c.DeleteMessagesFromCache(tt.args.ctx, tt.args.conversationID, tt.args.seqs),
|
||||
fmt.Sprintf("DeleteMessagesFromCache(%v, %v, %v)", tt.args.ctx, tt.args.conversationID, tt.args.seqs))
|
||||
})
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -2,14 +2,13 @@ package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type tokenCache struct {
|
||||
@@ -100,7 +99,7 @@ func (c *tokenCache) SetTokenMapByUidPid(ctx context.Context, userID string, pla
|
||||
return errs.Wrap(c.rdb.HSet(ctx, cachekey.GetTokenKey(userID, platformID), mm).Err())
|
||||
}
|
||||
|
||||
func (c *tokenCache) BatchSetTokenMapByUidPid(ctx context.Context, tokens map[string]map[string]any) error {
|
||||
func (c *tokenCache) BatchSetTokenMapByUidPid(ctx context.Context, tokens map[string]map[string]int) error {
|
||||
pipe := c.rdb.Pipeline()
|
||||
for k, v := range tokens {
|
||||
pipe.HSet(ctx, k, v)
|
||||
|
||||
Vendored
+1
-1
@@ -11,6 +11,6 @@ type TokenModel interface {
|
||||
GetTokensWithoutError(ctx context.Context, userID string, platformID int) (map[string]int, error)
|
||||
GetAllTokensWithoutError(ctx context.Context, userID string) (map[int]map[string]int, error)
|
||||
SetTokenMapByUidPid(ctx context.Context, userID string, platformID int, m map[string]int) error
|
||||
BatchSetTokenMapByUidPid(ctx context.Context, tokens map[string]map[string]any) error
|
||||
BatchSetTokenMapByUidPid(ctx context.Context, tokens map[string]map[string]int) error
|
||||
DeleteTokenByUidPid(ctx context.Context, userID string, platformID int, fields []string) error
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
@@ -42,7 +41,8 @@ func NewAuthDatabase(cache cache.TokenModel, accessSecret string, accessExpire i
|
||||
return &authDatabase{cache: cache, accessSecret: accessSecret, accessExpire: accessExpire, multiLogin: multiLoginConfig{
|
||||
Policy: multiLogin.Policy,
|
||||
MaxNumOneEnd: multiLogin.MaxNumOneEnd,
|
||||
}, adminUserIDs: adminUserIDs,
|
||||
},
|
||||
adminUserIDs: adminUserIDs,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func (a *authDatabase) SetTokenMapByUidPid(ctx context.Context, userID string, p
|
||||
}
|
||||
|
||||
func (a *authDatabase) BatchSetTokenMapByUidPid(ctx context.Context, tokens []string) error {
|
||||
setMap := make(map[string]map[string]any)
|
||||
setMap := make(map[string]map[string]int)
|
||||
for _, token := range tokens {
|
||||
claims, err := tokenverify.GetClaimFromToken(token, authverify.Secret(a.accessSecret))
|
||||
key := cachekey.GetTokenKey(claims.UserID, claims.PlatformID)
|
||||
@@ -66,7 +66,7 @@ func (a *authDatabase) BatchSetTokenMapByUidPid(ctx context.Context, tokens []st
|
||||
if v, ok := setMap[key]; ok {
|
||||
v[token] = constant.KickedToken
|
||||
} else {
|
||||
setMap[key] = map[string]any{
|
||||
setMap[key] = map[string]int{
|
||||
token: constant.KickedToken,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +74,6 @@ type ConversationDatabase interface {
|
||||
GetNotNotifyConversationIDs(ctx context.Context, userID string) ([]string, error)
|
||||
// GetPinnedConversationIDs gets pinned conversationIDs by userID
|
||||
GetPinnedConversationIDs(ctx context.Context, userID string) ([]string, error)
|
||||
// FindRandConversation finds random conversations based on the specified timestamp and limit.
|
||||
FindRandConversation(ctx context.Context, ts int64, limit int) ([]*relationtb.Conversation, error)
|
||||
}
|
||||
|
||||
func NewConversationDatabase(conversation database.Conversation, cache cache.ConversationCache, tx tx.Tx) ConversationDatabase {
|
||||
@@ -181,7 +179,7 @@ func (c *conversationDatabase) CreateConversation(ctx context.Context, conversat
|
||||
if conversation.RecvMsgOpt == constant.ReceiveNotNotifyMessage {
|
||||
notNotifyUserIDs = append(notNotifyUserIDs, conversation.OwnerUserID)
|
||||
}
|
||||
if conversation.IsPinned {
|
||||
if conversation.IsPinned == true {
|
||||
pinnedUserIDs = append(pinnedUserIDs, conversation.OwnerUserID)
|
||||
}
|
||||
}
|
||||
@@ -403,7 +401,3 @@ func (c *conversationDatabase) GetPinnedConversationIDs(ctx context.Context, use
|
||||
}
|
||||
return conversationIDs, nil
|
||||
}
|
||||
|
||||
func (c *conversationDatabase) FindRandConversation(ctx context.Context, ts int64, limit int) ([]*relationtb.Conversation, error) {
|
||||
return c.conversationDB.FindRandConversation(ctx, ts, limit)
|
||||
}
|
||||
|
||||
@@ -18,17 +18,12 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/openimsdk/tools/utils/jsonutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
||||
@@ -39,6 +34,9 @@ import (
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mq/kafka"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"github.com/openimsdk/tools/utils/timeutil"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -56,8 +54,11 @@ type CommonMsgDatabase interface {
|
||||
GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num, userMaxSeq int64) (minSeq int64, maxSeq int64, seqMsg []*sdkws.MsgData, err error)
|
||||
// GetMsgBySeqs retrieves messages for large groups from MongoDB by sequence numbers.
|
||||
GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (minSeq int64, maxSeq int64, seqMsg []*sdkws.MsgData, err error)
|
||||
|
||||
GetMessagesBySeqWithBounds(ctx context.Context, userID string, conversationID string, seqs []int64, pullOrder sdkws.PullOrder) (bool, int64, []*sdkws.MsgData, error)
|
||||
// DeleteConversationMsgsAndSetMinSeq deletes conversation messages and resets the minimum sequence number. If `remainTime` is 0, all messages are deleted (this method does not delete Redis
|
||||
// cache).
|
||||
DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error
|
||||
// UserMsgsDestruct marks messages for deletion based on destruct time and returns a list of sequence numbers for marked messages.
|
||||
UserMsgsDestruct(ctx context.Context, userID string, conversationID string, destructTime int64, lastMsgDestructTime time.Time) (seqs []int64, err error)
|
||||
// DeleteUserMsgsBySeqs allows a user to delete messages based on sequence numbers.
|
||||
DeleteUserMsgsBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) error
|
||||
// DeleteMsgsPhysicalBySeqs physically deletes messages by emptying them based on sequence numbers.
|
||||
@@ -66,7 +67,6 @@ type CommonMsgDatabase interface {
|
||||
GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error)
|
||||
GetMaxSeq(ctx context.Context, conversationID string) (int64, error)
|
||||
SetMinSeqs(ctx context.Context, seqs map[string]int64) error
|
||||
SetMinSeq(ctx context.Context, conversationID string, seq int64) error
|
||||
|
||||
SetUserConversationsMinSeqs(ctx context.Context, userID string, seqs map[string]int64) (err error)
|
||||
SetHasReadSeq(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error
|
||||
@@ -78,6 +78,8 @@ type CommonMsgDatabase interface {
|
||||
GetMaxSeqWithTime(ctx context.Context, conversationID string) (database.SeqTime, error)
|
||||
GetCacheMaxSeqWithTime(ctx context.Context, conversationIDs []string) (map[string]database.SeqTime, error)
|
||||
|
||||
//GetMongoMaxAndMinSeq(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo int64, err error)
|
||||
//GetConversationMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache int64, err error)
|
||||
SetSendMsgStatus(ctx context.Context, id string, status int32) error
|
||||
GetSendMsgStatus(ctx context.Context, id string) (int32, error)
|
||||
SearchMessage(ctx context.Context, req *pbmsg.SearchMessageReq) (total int64, msgData []*pbmsg.SearchedMsgData, err error)
|
||||
@@ -88,15 +90,13 @@ type CommonMsgDatabase interface {
|
||||
|
||||
RangeUserSendCount(ctx context.Context, start time.Time, end time.Time, group bool, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, users []*model.UserCount, dateCount map[string]int64, err error)
|
||||
RangeGroupSendCount(ctx context.Context, start time.Time, end time.Time, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, groups []*model.GroupCount, dateCount map[string]int64, err error)
|
||||
ConvertMsgsDocLen(ctx context.Context, conversationIDs []string)
|
||||
|
||||
GetRandBeforeMsg(ctx context.Context, ts int64, limit int) ([]*model.MsgDocModel, error)
|
||||
// clear msg
|
||||
GetBeforeMsg(ctx context.Context, ts int64, docIds []string, limit int) ([]*model.MsgDocModel, error)
|
||||
DeleteDocMsgBefore(ctx context.Context, ts int64, doc *model.MsgDocModel) ([]int, error)
|
||||
|
||||
SetUserConversationsMaxSeq(ctx context.Context, conversationID string, userID string, seq int64) error
|
||||
SetUserConversationsMinSeq(ctx context.Context, conversationID string, userID string, seq int64) error
|
||||
|
||||
DeleteDoc(ctx context.Context, docID string) error
|
||||
|
||||
GetLastMessageSeqByTime(ctx context.Context, conversationID string, time int64) (int64, error)
|
||||
GetDocIDs(ctx context.Context) ([]string, error)
|
||||
}
|
||||
|
||||
func NewCommonMsgDatabase(msgDocModel database.Msg, msg cache.MsgCache, seqUser cache.SeqUser, seqConversation cache.SeqConversationCache, kafkaConf *config.Kafka) (CommonMsgDatabase, error) {
|
||||
@@ -110,7 +110,7 @@ func NewCommonMsgDatabase(msgDocModel database.Msg, msg cache.MsgCache, seqUser
|
||||
}
|
||||
return &commonMsgDatabase{
|
||||
msgDocDatabase: msgDocModel,
|
||||
msgCache: msg,
|
||||
msg: msg,
|
||||
seqUser: seqUser,
|
||||
seqConversation: seqConversation,
|
||||
producer: producerToRedis,
|
||||
@@ -120,7 +120,7 @@ func NewCommonMsgDatabase(msgDocModel database.Msg, msg cache.MsgCache, seqUser
|
||||
type commonMsgDatabase struct {
|
||||
msgDocDatabase database.Msg
|
||||
msgTable model.MsgDocModel
|
||||
msgCache cache.MsgCache
|
||||
msg cache.MsgCache
|
||||
seqConversation cache.SeqConversationCache
|
||||
seqUser cache.SeqUser
|
||||
producer *kafka.Producer
|
||||
@@ -131,7 +131,7 @@ func (db *commonMsgDatabase) MsgToMQ(ctx context.Context, key string, msg2mq *sd
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) batchInsertBlock(ctx context.Context, conversationID string, fields []any, key int8, firstSeq int64) error {
|
||||
func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationID string, fields []any, key int8, firstSeq int64) error {
|
||||
if len(fields) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -229,15 +229,11 @@ func (db *commonMsgDatabase) batchInsertBlock(ctx context.Context, conversationI
|
||||
tryUpdate = false // The current block is inserted successfully, and the next block is inserted preferentially
|
||||
i += insert - 1 // Skip the inserted data
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) RevokeMsg(ctx context.Context, conversationID string, seq int64, revoke *model.RevokeModel) error {
|
||||
if err := db.batchInsertBlock(ctx, conversationID, []any{revoke}, updateKeyRevoke, seq); err != nil {
|
||||
return err
|
||||
}
|
||||
return db.msgCache.DelMessageBySeqs(ctx, conversationID, []int64{seq})
|
||||
return db.BatchInsertBlock(ctx, conversationID, []any{revoke}, updateKeyRevoke, seq)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) MarkSingleChatMsgsAsRead(ctx context.Context, userID string, conversationID string, totalSeqs []int64) error {
|
||||
@@ -252,17 +248,24 @@ func (db *commonMsgDatabase) MarkSingleChatMsgsAsRead(ctx context.Context, userI
|
||||
return err
|
||||
}
|
||||
}
|
||||
return db.msgCache.DelMessageBySeqs(ctx, conversationID, totalSeqs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, userID, conversationID string, seqs []int64) (totalMsgs []*sdkws.MsgData, err error) {
|
||||
return db.GetMessageBySeqs(ctx, conversationID, userID, seqs)
|
||||
for docID, seqs := range db.msgTable.GetDocIDSeqsMap(conversationID, seqs) {
|
||||
// log.ZDebug(ctx, "getMsgBySeqs", "docID", docID, "seqs", seqs)
|
||||
msgs, err := db.findMsgInfoBySeq(ctx, userID, docID, conversationID, seqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
totalMsgs = append(totalMsgs, convert.MsgDB2Pb(msg.Msg))
|
||||
}
|
||||
}
|
||||
return totalMsgs, nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][]*model.MsgInfoModel, userID, conversationID string, msg *model.MsgInfoModel) {
|
||||
if msg == nil || msg.Msg == nil {
|
||||
return
|
||||
}
|
||||
if msg.IsRead {
|
||||
msg.Msg.IsRead = true
|
||||
}
|
||||
@@ -272,53 +275,16 @@ func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][
|
||||
if msg.Msg.Content == "" {
|
||||
return
|
||||
}
|
||||
type MsgData struct {
|
||||
SendID string `json:"sendID"`
|
||||
RecvID string `json:"recvID"`
|
||||
GroupID string `json:"groupID"`
|
||||
ClientMsgID string `json:"clientMsgID"`
|
||||
ServerMsgID string `json:"serverMsgID"`
|
||||
SenderPlatformID int32 `json:"senderPlatformID"`
|
||||
SenderNickname string `json:"senderNickname"`
|
||||
SenderFaceURL string `json:"senderFaceURL"`
|
||||
SessionType int32 `json:"sessionType"`
|
||||
MsgFrom int32 `json:"msgFrom"`
|
||||
ContentType int32 `json:"contentType"`
|
||||
Content string `json:"content"`
|
||||
Seq int64 `json:"seq"`
|
||||
SendTime int64 `json:"sendTime"`
|
||||
CreateTime int64 `json:"createTime"`
|
||||
Status int32 `json:"status"`
|
||||
IsRead bool `json:"isRead"`
|
||||
Options map[string]bool `json:"options,omitempty"`
|
||||
OfflinePushInfo *sdkws.OfflinePushInfo `json:"offlinePushInfo"`
|
||||
AtUserIDList []string `json:"atUserIDList"`
|
||||
AttachedInfo string `json:"attachedInfo"`
|
||||
Ex string `json:"ex"`
|
||||
KeyVersion int32 `json:"keyVersion"`
|
||||
DstUserIDs []string `json:"dstUserIDs"`
|
||||
}
|
||||
var quoteMsg struct {
|
||||
Text string `json:"text,omitempty"`
|
||||
QuoteMessage *MsgData `json:"quoteMessage,omitempty"`
|
||||
QuoteMessage *sdkws.MsgData `json:"quoteMessage,omitempty"`
|
||||
MessageEntityList json.RawMessage `json:"messageEntityList,omitempty"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(msg.Msg.Content), "eMsg); err != nil {
|
||||
log.ZError(ctx, "json.Unmarshal", err)
|
||||
return
|
||||
}
|
||||
if quoteMsg.QuoteMessage == nil || quoteMsg.QuoteMessage.Content == "" {
|
||||
return
|
||||
}
|
||||
if quoteMsg.QuoteMessage.Content == "e30=" {
|
||||
quoteMsg.QuoteMessage.Content = "{}"
|
||||
data, err := json.Marshal("eMsg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg.Msg.Content = string(data)
|
||||
}
|
||||
if quoteMsg.QuoteMessage.Seq <= 0 && quoteMsg.QuoteMessage.ContentType == constant.MsgRevokeNotification {
|
||||
if quoteMsg.QuoteMessage == nil || quoteMsg.QuoteMessage.ContentType == constant.MsgRevokeNotification {
|
||||
return
|
||||
}
|
||||
var msgs []*model.MsgInfoModel
|
||||
@@ -340,9 +306,9 @@ func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][
|
||||
}
|
||||
quoteMsg.QuoteMessage.ContentType = constant.MsgRevokeNotification
|
||||
if len(msgs) > 0 {
|
||||
quoteMsg.QuoteMessage.Content = msgs[0].Msg.Content
|
||||
quoteMsg.QuoteMessage.Content = []byte(msgs[0].Msg.Content)
|
||||
} else {
|
||||
quoteMsg.QuoteMessage.Content = "{}"
|
||||
quoteMsg.QuoteMessage.Content = []byte("{}")
|
||||
}
|
||||
data, err := json.Marshal("eMsg)
|
||||
if err != nil {
|
||||
@@ -350,6 +316,9 @@ func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][
|
||||
return
|
||||
}
|
||||
msg.Msg.Content = string(data)
|
||||
if _, err := db.msgDocDatabase.UpdateMsg(ctx, db.msgTable.GetDocID(conversationID, msg.Msg.Seq), db.msgTable.GetMsgIndex(msg.Msg.Seq), "msg", msg.Msg); err != nil {
|
||||
log.ZError(ctx, "UpdateMsgContent", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) findMsgInfoBySeq(ctx context.Context, userID, docID string, conversationID string, seqs []int64) (totalMsgs []*model.MsgInfoModel, err error) {
|
||||
@@ -364,6 +333,24 @@ func (db *commonMsgDatabase) findMsgInfoBySeq(ctx context.Context, userID, docID
|
||||
return msgs, err
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) getMsgBySeqsRange(ctx context.Context, userID string, conversationID string, allSeqs []int64, begin, end int64) (seqMsgs []*sdkws.MsgData, err error) {
|
||||
log.ZDebug(ctx, "getMsgBySeqsRange", "conversationID", conversationID, "allSeqs", allSeqs, "begin", begin, "end", end)
|
||||
for docID, seqs := range db.msgTable.GetDocIDSeqsMap(conversationID, allSeqs) {
|
||||
log.ZDebug(ctx, "getMsgBySeqsRange", "docID", docID, "seqs", seqs)
|
||||
msgs, err := db.findMsgInfoBySeq(ctx, userID, docID, conversationID, seqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
if msg.IsRead {
|
||||
msg.Msg.IsRead = true
|
||||
}
|
||||
seqMsgs = append(seqMsgs, convert.MsgDB2Pb(msg.Msg))
|
||||
}
|
||||
}
|
||||
return seqMsgs, nil
|
||||
}
|
||||
|
||||
// GetMsgBySeqsRange In the context of group chat, we have the following parameters:
|
||||
//
|
||||
// "maxSeq" of a conversation: It represents the maximum value of messages in the group conversation.
|
||||
@@ -432,10 +419,37 @@ func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID strin
|
||||
seqs = append(seqs, i)
|
||||
}
|
||||
}
|
||||
successMsgs, err := db.GetMessageBySeqs(ctx, conversationID, userID, seqs)
|
||||
if err != nil {
|
||||
return 0, 0, nil, err
|
||||
|
||||
if len(seqs) == 0 {
|
||||
return 0, 0, nil, nil
|
||||
}
|
||||
newBegin := seqs[0]
|
||||
newEnd := seqs[len(seqs)-1]
|
||||
var successMsgs []*sdkws.MsgData
|
||||
log.ZDebug(ctx, "GetMsgBySeqsRange", "first seqs", seqs, "newBegin", newBegin, "newEnd", newEnd)
|
||||
cachedMsgs, failedSeqs, err := db.msg.GetMessagesBySeq(ctx, conversationID, seqs)
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
log.ZError(ctx, "get message from redis exception", err, "conversationID", conversationID, "seqs", seqs)
|
||||
}
|
||||
successMsgs = append(successMsgs, cachedMsgs...)
|
||||
log.ZDebug(ctx, "get msgs from cache", "cachedMsgs", cachedMsgs)
|
||||
// get from cache or db
|
||||
|
||||
if len(failedSeqs) > 0 {
|
||||
log.ZDebug(ctx, "msgs not exist in redis", "seqs", failedSeqs)
|
||||
mongoMsgs, err := db.getMsgBySeqsRange(ctx, userID, conversationID, failedSeqs, begin, end)
|
||||
if err != nil {
|
||||
|
||||
return 0, 0, nil, err
|
||||
}
|
||||
successMsgs = append(mongoMsgs, successMsgs...)
|
||||
|
||||
//_, err = db.msg.SetMessagesToCache(ctx, conversationID, mongoMsgs)
|
||||
//if err != nil {
|
||||
// return 0, 0, nil, err
|
||||
//}
|
||||
}
|
||||
|
||||
return minSeq, maxSeq, successMsgs, nil
|
||||
}
|
||||
|
||||
@@ -471,70 +485,168 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co
|
||||
newSeqs = append(newSeqs, seq)
|
||||
}
|
||||
}
|
||||
successMsgs, err := db.GetMessageBySeqs(ctx, conversationID, userID, newSeqs)
|
||||
if len(newSeqs) == 0 {
|
||||
return minSeq, maxSeq, nil, nil
|
||||
}
|
||||
successMsgs, failedSeqs, err := db.msg.GetMessagesBySeq(ctx, conversationID, newSeqs)
|
||||
if err != nil {
|
||||
return 0, 0, nil, err
|
||||
if errors.Is(err, redis.Nil) {
|
||||
log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
|
||||
}
|
||||
}
|
||||
log.ZDebug(ctx, "db.seq.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs",
|
||||
seqs, "len(successMsgs)", len(successMsgs), "failedSeqs", failedSeqs)
|
||||
|
||||
if len(failedSeqs) > 0 {
|
||||
mongoMsgs, err := db.getMsgBySeqs(ctx, userID, conversationID, failedSeqs)
|
||||
if err != nil {
|
||||
|
||||
return 0, 0, nil, err
|
||||
}
|
||||
|
||||
successMsgs = append(successMsgs, mongoMsgs...)
|
||||
|
||||
//_, err = db.msg.SetMessagesToCache(ctx, conversationID, mongoMsgs)
|
||||
//if err != nil {
|
||||
// return 0, 0, nil, err
|
||||
//}
|
||||
}
|
||||
return minSeq, maxSeq, successMsgs, nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetMessagesBySeqWithBounds(ctx context.Context, userID string, conversationID string, seqs []int64, pullOrder sdkws.PullOrder) (bool, int64, []*sdkws.MsgData, error) {
|
||||
var endSeq int64
|
||||
var isEnd bool
|
||||
userMinSeq, err := db.seqUser.GetUserMinSeq(ctx, conversationID, userID)
|
||||
func (db *commonMsgDatabase) DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error {
|
||||
var delStruct delMsgRecursionStruct
|
||||
var skip int64
|
||||
minSeq, err := db.deleteMsgRecursion(ctx, conversationID, skip, &delStruct, remainTime)
|
||||
if err != nil {
|
||||
return false, 0, nil, err
|
||||
return err
|
||||
}
|
||||
minSeq, err := db.seqConversation.GetMinSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return false, 0, nil, err
|
||||
log.ZDebug(ctx, "DeleteConversationMsgsAndSetMinSeq", "conversationID", conversationID, "minSeq", minSeq)
|
||||
if minSeq == 0 {
|
||||
return nil
|
||||
}
|
||||
maxSeq, err := db.seqConversation.GetMaxSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
return false, 0, nil, err
|
||||
}
|
||||
userMaxSeq, err := db.seqUser.GetUserMaxSeq(ctx, conversationID, userID)
|
||||
if err != nil {
|
||||
return false, 0, nil, err
|
||||
}
|
||||
if userMinSeq > minSeq {
|
||||
minSeq = userMinSeq
|
||||
}
|
||||
if userMaxSeq > 0 && userMaxSeq < maxSeq {
|
||||
maxSeq = userMaxSeq
|
||||
}
|
||||
newSeqs := make([]int64, 0, len(seqs))
|
||||
for _, seq := range seqs {
|
||||
if seq <= 0 {
|
||||
continue
|
||||
return db.seqConversation.SetMinSeq(ctx, conversationID, minSeq)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) UserMsgsDestruct(ctx context.Context, userID string, conversationID string, destructTime int64, lastMsgDestructTime time.Time) (seqs []int64, err error) {
|
||||
var index int64
|
||||
for {
|
||||
// from oldest 2 newest
|
||||
msgDocModel, err := db.msgDocDatabase.GetMsgDocModelByIndex(ctx, conversationID, index, 1)
|
||||
if err != nil || msgDocModel.DocID == "" {
|
||||
if err != nil {
|
||||
if err == model.ErrMsgListNotExist {
|
||||
log.ZDebug(ctx, "not doc find", "conversationID", conversationID, "userID", userID, "index", index)
|
||||
} else {
|
||||
log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index)
|
||||
}
|
||||
}
|
||||
// If an error is reported, or the error cannot be obtained, it is physically deleted and seq delMongoMsgsPhysical(delStruct.delDocIDList) is returned to end the recursion
|
||||
break
|
||||
}
|
||||
// The normal range and can fetch messages
|
||||
if seq >= minSeq && seq <= maxSeq {
|
||||
newSeqs = append(newSeqs, seq)
|
||||
continue
|
||||
}
|
||||
// If the requested seq is smaller than the minimum seq and the pull order is descending (pulling older messages)
|
||||
if seq < minSeq && pullOrder == sdkws.PullOrder_PullOrderDesc {
|
||||
isEnd = true
|
||||
endSeq = minSeq
|
||||
}
|
||||
// If the requested seq is larger than the maximum seq and the pull order is ascending (pulling newer messages)
|
||||
if seq > maxSeq && pullOrder == sdkws.PullOrder_PullOrderAsc {
|
||||
isEnd = true
|
||||
endSeq = maxSeq
|
||||
index++
|
||||
// && msgDocModel.Msg[0].Msg.SendTime > lastMsgDestructTime.UnixMilli()
|
||||
if len(msgDocModel.Msg) > 0 {
|
||||
i := 0
|
||||
var over bool
|
||||
for _, msg := range msgDocModel.Msg {
|
||||
i++
|
||||
if msg != nil && msg.Msg != nil && msg.Msg.SendTime+destructTime*1000 <= time.Now().UnixMilli() {
|
||||
if msg.Msg.SendTime+destructTime*1000 > lastMsgDestructTime.UnixMilli() && !datautil.Contain(userID, msg.DelList...) {
|
||||
seqs = append(seqs, msg.Msg.Seq)
|
||||
}
|
||||
} else {
|
||||
log.ZDebug(ctx, "all msg need destruct is found", "conversationID", conversationID, "userID", userID, "index", index, "stop index", i)
|
||||
over = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if over {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(newSeqs) == 0 {
|
||||
return isEnd, endSeq, nil, nil
|
||||
|
||||
log.ZDebug(ctx, "UserMsgsDestruct", "conversationID", conversationID, "userID", userID, "seqs", seqs)
|
||||
if len(seqs) > 0 {
|
||||
userMinSeq := seqs[len(seqs)-1] + 1
|
||||
currentUserMinSeq, err := db.seqUser.GetUserMinSeq(ctx, conversationID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if currentUserMinSeq < userMinSeq {
|
||||
if err := db.seqUser.SetUserMinSeq(ctx, conversationID, userID, userMinSeq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
successMsgs, err := db.GetMessageBySeqs(ctx, conversationID, userID, newSeqs)
|
||||
if err != nil {
|
||||
return false, 0, nil, err
|
||||
return seqs, nil
|
||||
}
|
||||
|
||||
// this is struct for recursion.
|
||||
type delMsgRecursionStruct struct {
|
||||
minSeq int64
|
||||
delDocIDs []string
|
||||
}
|
||||
|
||||
func (d *delMsgRecursionStruct) getSetMinSeq() int64 {
|
||||
return d.minSeq
|
||||
}
|
||||
|
||||
// index 0....19(del) 20...69
|
||||
// seq 70
|
||||
// set minSeq 21
|
||||
// recursion deletes the list and returns the set minimum seq.
|
||||
func (db *commonMsgDatabase) deleteMsgRecursion(ctx context.Context, conversationID string, index int64, delStruct *delMsgRecursionStruct, remainTime int64) (int64, error) {
|
||||
// find from oldest list
|
||||
msgDocModel, err := db.msgDocDatabase.GetMsgDocModelByIndex(ctx, conversationID, index, 1)
|
||||
if err != nil || msgDocModel.DocID == "" {
|
||||
if err != nil {
|
||||
if err == model.ErrMsgListNotExist {
|
||||
log.ZDebug(ctx, "deleteMsgRecursion ErrMsgListNotExist", "conversationID", conversationID, "index:", index)
|
||||
} else {
|
||||
log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index)
|
||||
}
|
||||
}
|
||||
// If an error is reported, or the error cannot be obtained, it is physically deleted and seq delMongoMsgsPhysical(delStruct.delDocIDList) is returned to end the recursion
|
||||
err = db.msgDocDatabase.DeleteDocs(ctx, delStruct.delDocIDs)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return delStruct.getSetMinSeq() + 1, nil
|
||||
}
|
||||
return isEnd, endSeq, successMsgs, nil
|
||||
log.ZDebug(ctx, "doc info", "conversationID", conversationID, "index", index, "docID", msgDocModel.DocID, "len", len(msgDocModel.Msg))
|
||||
if int64(len(msgDocModel.Msg)) > db.msgTable.GetSingleGocMsgNum() {
|
||||
log.ZWarn(ctx, "msgs too large", nil, "length", len(msgDocModel.Msg), "docID:", msgDocModel.DocID)
|
||||
}
|
||||
if msgDocModel.IsFull() && msgDocModel.Msg[len(msgDocModel.Msg)-1].Msg.SendTime+(remainTime*1000) < timeutil.GetCurrentTimestampByMill() {
|
||||
log.ZDebug(ctx, "doc is full and all msg is expired", "docID", msgDocModel.DocID)
|
||||
delStruct.delDocIDs = append(delStruct.delDocIDs, msgDocModel.DocID)
|
||||
delStruct.minSeq = msgDocModel.Msg[len(msgDocModel.Msg)-1].Msg.Seq
|
||||
} else {
|
||||
var delMsgIndexs []int
|
||||
for i, MsgInfoModel := range msgDocModel.Msg {
|
||||
if MsgInfoModel != nil && MsgInfoModel.Msg != nil {
|
||||
if timeutil.GetCurrentTimestampByMill() > MsgInfoModel.Msg.SendTime+(remainTime*1000) {
|
||||
delMsgIndexs = append(delMsgIndexs, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(delMsgIndexs) > 0 {
|
||||
if err = db.msgDocDatabase.DeleteMsgsInOneDocByIndex(ctx, msgDocModel.DocID, delMsgIndexs); err != nil {
|
||||
log.ZError(ctx, "deleteMsgRecursion DeleteMsgsInOneDocByIndex failed", err, "conversationID", conversationID, "index", index)
|
||||
}
|
||||
delStruct.minSeq = int64(msgDocModel.Msg[delMsgIndexs[len(delMsgIndexs)-1]].Msg.Seq)
|
||||
}
|
||||
}
|
||||
seq, err := db.deleteMsgRecursion(ctx, conversationID, index+1, delStruct, remainTime)
|
||||
return seq, err
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) DeleteMsgsPhysicalBySeqs(ctx context.Context, conversationID string, allSeqs []int64) error {
|
||||
if err := db.msg.DeleteMessagesFromCache(ctx, conversationID, allSeqs); err != nil {
|
||||
return err
|
||||
}
|
||||
for docID, seqs := range db.msgTable.GetDocIDSeqsMap(conversationID, allSeqs) {
|
||||
var indexes []int
|
||||
for _, seq := range seqs {
|
||||
@@ -544,10 +656,13 @@ func (db *commonMsgDatabase) DeleteMsgsPhysicalBySeqs(ctx context.Context, conve
|
||||
return err
|
||||
}
|
||||
}
|
||||
return db.msgCache.DelMessageBySeqs(ctx, conversationID, allSeqs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) DeleteUserMsgsBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) error {
|
||||
if err := db.msg.DeleteMessagesFromCache(ctx, conversationID, seqs); err != nil {
|
||||
return err
|
||||
}
|
||||
for docID, seqs := range db.msgTable.GetDocIDSeqsMap(conversationID, seqs) {
|
||||
for _, seq := range seqs {
|
||||
if _, err := db.msgDocDatabase.PushUnique(ctx, docID, db.msgTable.GetMsgIndex(seq), "del_list", []string{userID}); err != nil {
|
||||
@@ -555,7 +670,7 @@ func (db *commonMsgDatabase) DeleteUserMsgsBySeqs(ctx context.Context, userID st
|
||||
}
|
||||
}
|
||||
}
|
||||
return db.msgCache.DelMessageBySeqs(ctx, conversationID, seqs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) {
|
||||
@@ -566,6 +681,10 @@ func (db *commonMsgDatabase) GetMaxSeq(ctx context.Context, conversationID strin
|
||||
return db.seqConversation.GetMaxSeq(ctx, conversationID)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error {
|
||||
return db.seqConversation.SetMinSeq(ctx, conversationID, minSeq)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) SetMinSeqs(ctx context.Context, seqs map[string]int64) error {
|
||||
return db.seqConversation.SetMinSeqs(ctx, seqs)
|
||||
}
|
||||
@@ -574,14 +693,6 @@ func (db *commonMsgDatabase) SetUserConversationsMinSeqs(ctx context.Context, us
|
||||
return db.seqUser.SetUserMinSeqs(ctx, userID, seqs)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) SetUserConversationsMaxSeq(ctx context.Context, conversationID string, userID string, seq int64) error {
|
||||
return db.seqUser.SetUserMaxSeq(ctx, conversationID, userID, seq)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) SetUserConversationsMinSeq(ctx context.Context, conversationID string, userID string, seq int64) error {
|
||||
return db.seqUser.SetUserMinSeq(ctx, conversationID, userID, seq)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) UserSetHasReadSeqs(ctx context.Context, userID string, hasReadSeqs map[string]int64) error {
|
||||
return db.seqUser.SetUserReadSeqs(ctx, userID, hasReadSeqs)
|
||||
}
|
||||
@@ -599,11 +710,11 @@ func (db *commonMsgDatabase) GetHasReadSeq(ctx context.Context, userID string, c
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) SetSendMsgStatus(ctx context.Context, id string, status int32) error {
|
||||
return db.msgCache.SetSendMsgStatus(ctx, id, status)
|
||||
return db.msg.SetSendMsgStatus(ctx, id, status)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetSendMsgStatus(ctx context.Context, id string) (int32, error) {
|
||||
return db.msgCache.GetSendMsgStatus(ctx, id)
|
||||
return db.msg.GetSendMsgStatus(ctx, id)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetConversationMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache int64, err error) {
|
||||
@@ -640,11 +751,26 @@ func (db *commonMsgDatabase) GetMinMaxSeqMongo(ctx context.Context, conversation
|
||||
return
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) RangeUserSendCount(ctx context.Context, start time.Time, end time.Time, group bool, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, users []*model.UserCount, dateCount map[string]int64, err error) {
|
||||
func (db *commonMsgDatabase) RangeUserSendCount(
|
||||
ctx context.Context,
|
||||
start time.Time,
|
||||
end time.Time,
|
||||
group bool,
|
||||
ase bool,
|
||||
pageNumber int32,
|
||||
showNumber int32,
|
||||
) (msgCount int64, userCount int64, users []*model.UserCount, dateCount map[string]int64, err error) {
|
||||
return db.msgDocDatabase.RangeUserSendCount(ctx, start, end, group, ase, pageNumber, showNumber)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) RangeGroupSendCount(ctx context.Context, start time.Time, end time.Time, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, groups []*model.GroupCount, dateCount map[string]int64, err error) {
|
||||
func (db *commonMsgDatabase) RangeGroupSendCount(
|
||||
ctx context.Context,
|
||||
start time.Time,
|
||||
end time.Time,
|
||||
ase bool,
|
||||
pageNumber int32,
|
||||
showNumber int32,
|
||||
) (msgCount int64, userCount int64, groups []*model.GroupCount, dateCount map[string]int64, err error) {
|
||||
return db.msgDocDatabase.RangeGroupSendCount(ctx, start, end, ase, pageNumber, showNumber)
|
||||
}
|
||||
|
||||
@@ -684,11 +810,60 @@ func (db *commonMsgDatabase) FindOneByDocIDs(ctx context.Context, conversationID
|
||||
return totalMsgs, nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetRandBeforeMsg(ctx context.Context, ts int64, limit int) ([]*model.MsgDocModel, error) {
|
||||
return db.msgDocDatabase.GetRandBeforeMsg(ctx, ts, limit)
|
||||
func (db *commonMsgDatabase) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) {
|
||||
db.msgDocDatabase.ConvertMsgsDocLen(ctx, conversationIDs)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) SetMinSeq(ctx context.Context, conversationID string, seq int64) error {
|
||||
func (db *commonMsgDatabase) GetBeforeMsg(ctx context.Context, ts int64, docIDs []string, limit int) ([]*model.MsgDocModel, error) {
|
||||
var msgs []*model.MsgDocModel
|
||||
for i := 0; i < len(docIDs); i += 1000 {
|
||||
end := i + 1000
|
||||
if end > len(docIDs) {
|
||||
end = len(docIDs)
|
||||
}
|
||||
|
||||
res, err := db.msgDocDatabase.GetBeforeMsg(ctx, ts, docIDs[i:end], limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgs = append(msgs, res...)
|
||||
|
||||
if len(msgs) >= limit {
|
||||
return msgs[:limit], nil
|
||||
}
|
||||
}
|
||||
return msgs, nil
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) DeleteDocMsgBefore(ctx context.Context, ts int64, doc *model.MsgDocModel) ([]int, error) {
|
||||
var notNull int
|
||||
index := make([]int, 0, len(doc.Msg))
|
||||
for i, message := range doc.Msg {
|
||||
if message.Msg != nil {
|
||||
notNull++
|
||||
if message.Msg.SendTime < ts {
|
||||
index = append(index, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(index) == 0 {
|
||||
return index, nil
|
||||
}
|
||||
maxSeq := doc.Msg[index[len(index)-1]].Msg.Seq
|
||||
conversationID := doc.DocID[:strings.LastIndex(doc.DocID, ":")]
|
||||
if err := db.setMinSeq(ctx, conversationID, maxSeq+1); err != nil {
|
||||
return index, err
|
||||
}
|
||||
if len(index) == notNull {
|
||||
log.ZDebug(ctx, "Delete db in Doc", "DocID", doc.DocID, "index", index, "maxSeq", maxSeq)
|
||||
return index, db.msgDocDatabase.DeleteDoc(ctx, doc.DocID)
|
||||
} else {
|
||||
log.ZDebug(ctx, "delete db in index", "DocID", doc.DocID, "index", index, "maxSeq", maxSeq)
|
||||
return index, db.msgDocDatabase.DeleteMsgByIndex(ctx, doc.DocID, index)
|
||||
}
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) setMinSeq(ctx context.Context, conversationID string, seq int64) error {
|
||||
dbSeq, err := db.seqConversation.GetMinSeq(ctx, conversationID)
|
||||
if err != nil {
|
||||
if errors.Is(errs.Unwrap(err), redis.Nil) {
|
||||
@@ -702,6 +877,10 @@ func (db *commonMsgDatabase) SetMinSeq(ctx context.Context, conversationID strin
|
||||
return db.seqConversation.SetMinSeq(ctx, conversationID, seq)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetDocIDs(ctx context.Context) ([]string, error) {
|
||||
return db.msgDocDatabase.GetDocIDs(ctx)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetCacheMaxSeqWithTime(ctx context.Context, conversationIDs []string) (map[string]database.SeqTime, error) {
|
||||
return db.seqConversation.GetCacheMaxSeqWithTime(ctx, conversationIDs)
|
||||
}
|
||||
@@ -714,105 +893,3 @@ func (db *commonMsgDatabase) GetMaxSeqsWithTime(ctx context.Context, conversatio
|
||||
// todo: only the time in the redis cache will be taken, not the message time
|
||||
return db.seqConversation.GetMaxSeqsWithTime(ctx, conversationIDs)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) DeleteDoc(ctx context.Context, docID string) error {
|
||||
index := strings.LastIndex(docID, ":")
|
||||
if index <= 0 {
|
||||
return errs.ErrInternalServer.WrapMsg("docID is invalid", "docID", docID)
|
||||
}
|
||||
index, err := strconv.Atoi(docID[index+1:])
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "strconv.Atoi", "docID", docID)
|
||||
}
|
||||
conversationID := docID[:index]
|
||||
seqs := make([]int64, db.msgTable.GetSingleGocMsgNum())
|
||||
minSeq := db.msgTable.GetMinSeq(index)
|
||||
for i := range seqs {
|
||||
seqs[i] = minSeq + int64(i)
|
||||
}
|
||||
if err := db.msgDocDatabase.DeleteDoc(ctx, docID); err != nil {
|
||||
return err
|
||||
}
|
||||
return db.msgCache.DelMessageBySeqs(ctx, conversationID, seqs)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetLastMessageSeqByTime(ctx context.Context, conversationID string, time int64) (int64, error) {
|
||||
return db.msgDocDatabase.GetLastMessageSeqByTime(ctx, conversationID, time)
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) handlerDeleteAndRevoked(ctx context.Context, userID string, msgs []*model.MsgInfoModel) {
|
||||
for i := range msgs {
|
||||
msg := msgs[i]
|
||||
if msg == nil || msg.Msg == nil {
|
||||
continue
|
||||
}
|
||||
msg.Msg.IsRead = msg.IsRead
|
||||
if datautil.Contain(userID, msg.DelList...) {
|
||||
msg.Msg.Content = ""
|
||||
msg.Msg.Status = constant.MsgDeleted
|
||||
}
|
||||
if msg.Revoke == nil {
|
||||
continue
|
||||
}
|
||||
msg.Msg.ContentType = constant.MsgRevokeNotification
|
||||
revokeContent := sdkws.MessageRevokedContent{
|
||||
RevokerID: msg.Revoke.UserID,
|
||||
RevokerRole: msg.Revoke.Role,
|
||||
ClientMsgID: msg.Msg.ClientMsgID,
|
||||
RevokerNickname: msg.Revoke.Nickname,
|
||||
RevokeTime: msg.Revoke.Time,
|
||||
SourceMessageSendTime: msg.Msg.SendTime,
|
||||
SourceMessageSendID: msg.Msg.SendID,
|
||||
SourceMessageSenderNickname: msg.Msg.SenderNickname,
|
||||
SessionType: msg.Msg.SessionType,
|
||||
Seq: msg.Msg.Seq,
|
||||
Ex: msg.Msg.Ex,
|
||||
}
|
||||
data, err := jsonutil.JsonMarshal(&revokeContent)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "handlerDeleteAndRevoked JsonMarshal MessageRevokedContent", err, "msg", msg)
|
||||
continue
|
||||
}
|
||||
elem := sdkws.NotificationElem{
|
||||
Detail: string(data),
|
||||
}
|
||||
content, err := jsonutil.JsonMarshal(&elem)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "handlerDeleteAndRevoked JsonMarshal NotificationElem", err, "msg", msg)
|
||||
continue
|
||||
}
|
||||
msg.Msg.Content = string(content)
|
||||
}
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) handlerQuote(ctx context.Context, userID, conversationID string, msgs []*model.MsgInfoModel) {
|
||||
temp := make(map[int64][]*model.MsgInfoModel)
|
||||
for i := range msgs {
|
||||
db.handlerDBMsg(ctx, temp, userID, conversationID, msgs[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (db *commonMsgDatabase) GetMessageBySeqs(ctx context.Context, conversationID string, userID string, seqs []int64) ([]*sdkws.MsgData, error) {
|
||||
msgs, err := db.msgCache.GetMessageBySeqs(ctx, conversationID, seqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.handlerDeleteAndRevoked(ctx, userID, msgs)
|
||||
db.handlerQuote(ctx, userID, conversationID, msgs)
|
||||
seqMsgs := make(map[int64]*model.MsgInfoModel)
|
||||
for i, msg := range msgs {
|
||||
if msg.Msg == nil {
|
||||
continue
|
||||
}
|
||||
seqMsgs[msg.Msg.Seq] = msgs[i]
|
||||
}
|
||||
res := make([]*sdkws.MsgData, 0, len(seqs))
|
||||
for _, seq := range seqs {
|
||||
if v, ok := seqMsgs[seq]; ok {
|
||||
res = append(res, convert.MsgDB2Pb(v.Msg))
|
||||
} else {
|
||||
res = append(res, &sdkws.MsgData{Seq: seq})
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
@@ -51,7 +50,7 @@ func NewMsgTransferDatabase(msgDocModel database.Msg, msg cache.MsgCache, seqUse
|
||||
}
|
||||
return &msgTransferDatabase{
|
||||
msgDocDatabase: msgDocModel,
|
||||
msgCache: msg,
|
||||
msg: msg,
|
||||
seqUser: seqUser,
|
||||
seqConversation: seqConversation,
|
||||
producerToMongo: producerToMongo,
|
||||
@@ -62,7 +61,7 @@ func NewMsgTransferDatabase(msgDocModel database.Msg, msg cache.MsgCache, seqUse
|
||||
type msgTransferDatabase struct {
|
||||
msgDocDatabase database.Msg
|
||||
msgTable model.MsgDocModel
|
||||
msgCache cache.MsgCache
|
||||
msg cache.MsgCache
|
||||
seqConversation cache.SeqConversationCache
|
||||
seqUser cache.SeqUser
|
||||
producerToMongo *kafka.Producer
|
||||
@@ -74,12 +73,10 @@ func (db *msgTransferDatabase) BatchInsertChat2DB(ctx context.Context, conversat
|
||||
return errs.ErrArgs.WrapMsg("msgList is empty")
|
||||
}
|
||||
msgs := make([]any, len(msgList))
|
||||
seqs := make([]int64, len(msgList))
|
||||
for i, msg := range msgList {
|
||||
if msg == nil {
|
||||
continue
|
||||
}
|
||||
seqs[i] = msg.Seq
|
||||
var offlinePushModel *model.OfflinePushModel
|
||||
if msg.OfflinePushInfo != nil {
|
||||
offlinePushModel = &model.OfflinePushModel{
|
||||
@@ -117,11 +114,7 @@ func (db *msgTransferDatabase) BatchInsertChat2DB(ctx context.Context, conversat
|
||||
Ex: msg.Ex,
|
||||
}
|
||||
}
|
||||
if err := db.BatchInsertBlock(ctx, conversationID, msgs, updateKeyMsg, msgList[0].Seq); err != nil {
|
||||
return err
|
||||
}
|
||||
//return db.msgCache.DelMessageBySeqs(ctx, conversationID, seqs)
|
||||
return nil
|
||||
return db.BatchInsertBlock(ctx, conversationID, msgs, updateKeyMsg, msgList[0].Seq)
|
||||
}
|
||||
|
||||
func (db *msgTransferDatabase) BatchInsertBlock(ctx context.Context, conversationID string, fields []any, key int8, firstSeq int64) error {
|
||||
@@ -226,7 +219,7 @@ func (db *msgTransferDatabase) BatchInsertBlock(ctx context.Context, conversatio
|
||||
}
|
||||
|
||||
func (db *msgTransferDatabase) DeleteMessagesFromCache(ctx context.Context, conversationID string, seqs []int64) error {
|
||||
return db.msgCache.DelMessageBySeqs(ctx, conversationID, seqs)
|
||||
return db.msg.DeleteMessagesFromCache(ctx, conversationID, seqs)
|
||||
}
|
||||
|
||||
func (db *msgTransferDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, userHasReadMap map[string]int64, err error) {
|
||||
@@ -245,22 +238,20 @@ func (db *msgTransferDatabase) BatchInsertChat2Cache(ctx context.Context, conver
|
||||
isNew = currentMaxSeq == 0
|
||||
lastMaxSeq := currentMaxSeq
|
||||
userSeqMap := make(map[string]int64)
|
||||
seqs := make([]int64, 0, lenList)
|
||||
for _, m := range msgs {
|
||||
currentMaxSeq++
|
||||
m.Seq = currentMaxSeq
|
||||
userSeqMap[m.SendID] = m.Seq
|
||||
seqs = append(seqs, m.Seq)
|
||||
}
|
||||
msgToDB := func(msg *sdkws.MsgData) *model.MsgInfoModel {
|
||||
return &model.MsgInfoModel{
|
||||
Msg: convert.MsgPb2DB(msg),
|
||||
}
|
||||
|
||||
failedNum, err := db.msg.SetMessagesToCache(ctx, conversationID, msgs)
|
||||
if err != nil {
|
||||
prommetrics.MsgInsertRedisFailedCounter.Add(float64(failedNum))
|
||||
log.ZError(ctx, "setMessageToCache error", err, "len", len(msgs), "conversationID", conversationID)
|
||||
} else {
|
||||
prommetrics.MsgInsertRedisSuccessCounter.Inc()
|
||||
}
|
||||
if err := db.msgCache.SetMessageBySeqs(ctx, conversationID, datautil.Slice(msgs, msgToDB)); err != nil {
|
||||
return 0, false, nil, err
|
||||
}
|
||||
return lastMaxSeq, isNew, userSeqMap, nil
|
||||
return lastMaxSeq, isNew, userSeqMap, errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (db *msgTransferDatabase) SetHasReadSeqs(ctx context.Context, conversationID string, userSeqMap map[string]int64) error {
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/s3"
|
||||
"github.com/openimsdk/tools/s3/cont"
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -39,10 +40,11 @@ type S3Database interface {
|
||||
SetObject(ctx context.Context, info *model.Object) error
|
||||
StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error)
|
||||
FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error)
|
||||
FindExpirationObject(ctx context.Context, engine string, expiration time.Time, needDelType []string, count int64) ([]*model.Object, error)
|
||||
DeleteSpecifiedData(ctx context.Context, engine string, name []string) error
|
||||
FindByExpires(ctx context.Context, duration time.Time, pagination pagination.Pagination) (total int64, objects []*model.Object, err error)
|
||||
DeleteObject(ctx context.Context, name string) error
|
||||
DeleteSpecifiedData(ctx context.Context, engine string, name string) error
|
||||
FindNotDelByS3(ctx context.Context, key string, duration time.Time) (int64, error)
|
||||
DelS3Key(ctx context.Context, engine string, keys ...string) error
|
||||
GetKeyCount(ctx context.Context, engine string, key string) (int64, error)
|
||||
}
|
||||
|
||||
func NewS3Database(rdb redis.UniversalClient, s3 s3.Interface, obj database.ObjectInfo) S3Database {
|
||||
@@ -118,19 +120,22 @@ func (s *s3Database) StatObject(ctx context.Context, name string) (*s3.ObjectInf
|
||||
func (s *s3Database) FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error) {
|
||||
return s.s3.FormData(ctx, name, size, contentType, duration)
|
||||
}
|
||||
func (s *s3Database) FindByExpires(ctx context.Context, duration time.Time, pagination pagination.Pagination) (total int64, objects []*model.Object, err error) {
|
||||
|
||||
func (s *s3Database) FindExpirationObject(ctx context.Context, engine string, expiration time.Time, needDelType []string, count int64) ([]*model.Object, error) {
|
||||
return s.db.FindExpirationObject(ctx, engine, expiration, needDelType, count)
|
||||
return s.db.FindByExpires(ctx, duration, pagination)
|
||||
}
|
||||
|
||||
func (s *s3Database) GetKeyCount(ctx context.Context, engine string, key string) (int64, error) {
|
||||
return s.db.GetKeyCount(ctx, engine, key)
|
||||
func (s *s3Database) DeleteObject(ctx context.Context, name string) error {
|
||||
return s.s3.DeleteObject(ctx, name)
|
||||
}
|
||||
|
||||
func (s *s3Database) DeleteSpecifiedData(ctx context.Context, engine string, name []string) error {
|
||||
func (s *s3Database) DeleteSpecifiedData(ctx context.Context, engine string, name string) error {
|
||||
return s.db.Delete(ctx, engine, name)
|
||||
}
|
||||
|
||||
func (s *s3Database) FindNotDelByS3(ctx context.Context, key string, duration time.Time) (int64, error) {
|
||||
return s.db.FindNotDelByS3(ctx, key, duration)
|
||||
}
|
||||
|
||||
func (s *s3Database) DelS3Key(ctx context.Context, engine string, keys ...string) error {
|
||||
return s.s3cache.DelS3Key(ctx, engine, keys...)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StreamMsgDatabase interface {
|
||||
CreateStreamMsg(ctx context.Context, model *model.StreamMsg) error
|
||||
AppendStreamMsg(ctx context.Context, clientMsgID string, startIndex int, packets []string, end bool, deadlineTime time.Time) error
|
||||
GetStreamMsg(ctx context.Context, clientMsgID string) (*model.StreamMsg, error)
|
||||
}
|
||||
|
||||
func NewStreamMsgDatabase(db database.StreamMsg) StreamMsgDatabase {
|
||||
return &streamMsgDatabase{db: db}
|
||||
}
|
||||
|
||||
type streamMsgDatabase struct {
|
||||
db database.StreamMsg
|
||||
}
|
||||
|
||||
func (m *streamMsgDatabase) CreateStreamMsg(ctx context.Context, model *model.StreamMsg) error {
|
||||
return m.db.CreateStreamMsg(ctx, model)
|
||||
}
|
||||
|
||||
func (m *streamMsgDatabase) AppendStreamMsg(ctx context.Context, clientMsgID string, startIndex int, packets []string, end bool, deadlineTime time.Time) error {
|
||||
return m.db.AppendStreamMsg(ctx, clientMsgID, startIndex, packets, end, deadlineTime)
|
||||
}
|
||||
|
||||
func (m *streamMsgDatabase) GetStreamMsg(ctx context.Context, clientMsgID string) (*model.StreamMsg, error) {
|
||||
return m.db.GetStreamMsg(ctx, clientMsgID)
|
||||
}
|
||||
@@ -16,7 +16,6 @@ package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
)
|
||||
@@ -42,5 +41,4 @@ type Conversation interface {
|
||||
GetConversationIDsNeedDestruct(ctx context.Context) ([]*model.Conversation, error)
|
||||
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
|
||||
FindConversationUserVersion(ctx context.Context, userID string, version uint, limit int) (*model.VersionLog, error)
|
||||
FindRandConversation(ctx context.Context, ts int64, limit int) ([]*model.Conversation, error)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,9 @@ package mgo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
@@ -228,35 +227,3 @@ func (c *ConversationMgo) GetConversationNotReceiveMessageUserIDs(ctx context.Co
|
||||
func (c *ConversationMgo) FindConversationUserVersion(ctx context.Context, userID string, version uint, limit int) (*model.VersionLog, error) {
|
||||
return c.version.FindChangeLog(ctx, userID, version, limit)
|
||||
}
|
||||
|
||||
func (c *ConversationMgo) FindRandConversation(ctx context.Context, ts int64, limit int) ([]*model.Conversation, error) {
|
||||
pipeline := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
"is_msg_destruct": true,
|
||||
"msg_destruct_time": bson.M{"$ne": 0},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$addFields": bson.M{
|
||||
"next_msg_destruct_timestamp": bson.M{
|
||||
"$add": []any{
|
||||
bson.M{
|
||||
"$toLong": "$latest_msg_destruct_time",
|
||||
}, "$msg_destruct_time"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$match": bson.M{
|
||||
"next_msg_destruct_timestamp": bson.M{"$lt": ts},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$sample": bson.M{
|
||||
"size": limit,
|
||||
},
|
||||
},
|
||||
}
|
||||
return mongoutil.Aggregate[*model.Conversation](ctx, c.coll, pipeline)
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ type GroupMemberMgo struct {
|
||||
}
|
||||
|
||||
func (g *GroupMemberMgo) memberSort() any {
|
||||
return bson.D{{Key: "role_level", Value: -1}, {Key: "create_time", Value: 1}}
|
||||
return bson.D{{"role_level", -1}, {"create_time", 1}}
|
||||
}
|
||||
|
||||
func (g *GroupMemberMgo) Create(ctx context.Context, groupMembers []*model.GroupMember) (err error) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user