Compare commits

...

31 Commits

Author SHA1 Message Date
Monet Lee 840ddc15fe chore: revert tool pkg version. (#2476)
* feat: update go mod pkg to latest.

* revert tool pkg version.
2024-08-02 12:13:13 +00:00
Monet Lee c45967079e feat: update go mod pkg to latest. (#2475) 2024-08-02 18:30:17 +08:00
chao 84049a1f55 fix: the local cache obtained can be modified (#2473)
* fix: GroupApplicationAcceptedNotification

* fix: GroupApplicationAcceptedNotification

* fix: NotificationUserInfoUpdate

* cicd: robot automated Change

* fix: component

* fix: getConversationInfo

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* fix: minio config url recognition error

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* mage

* optimization version log

* optimization version log

* sync

* sync

* sync

* group sync

* sync option

* sync option

* refactor: replace `friend` package with `realtion`.

* refactor: update lastest commit to relation.

* sync option

* sync option

* sync option

* sync

* sync

* go.mod

* seq

* update: go mod

* refactor: change incremental to full

* feat: get full friend user ids

* feat: api and config

* seq

* group version

* merge

* seq

* seq

* seq

* fix: sort by id avoid unstable sort friends.

* group

* group

* group

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* user version

* seq

* seq

* seq user

* user online

* implement minio expire delete.

* user online

* config

* fix

* fix

* implement minio expire delete logic.

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* feat: implement scheduled delete outdated object in minio.

* update gomake version

* update gomake version

* implement FindExpires pagination.

* remove unnesseary incr.

* fix uncorrect args call.

* online push

* online push

* online push

* resolving conflicts

* resolving conflicts

* test

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* rpc prommetrics

* rpc prommetrics

* online status

* online status

* online status

* online status

* sub

* conversation version incremental

* merge seq

* merge online

* merge online

* merge online

* merge seq

* GetOwnerConversation

* fix: change incremental syncer router name.

* rockscache batch get

* rockscache seq batch get

* fix: GetMsgDocModelByIndex bug

* update go.mod

* update go.mod

* merge

* feat: prometheus

* feat: prometheus

* group member sort

* sub

* sub

* fix: seq conversion bug

* fix: redis pipe exec

* sort version

* sort version

* sort version

* remove old version online subscription

* remove old version online subscription

* version log index

* version log index

* batch push

* batch push

* seq void filling

* fix: batchGetMaxSeq

* fix: batchGetMaxSeq

* cache db error log

* 111

* fix bug

* fix: ImportFriends

* add online cache

* add some logs

* add some logs

* fix: onlineUserIDs

* add logs

* test

* test

* test

* test

* add log

* feat: solve the problem that modifying the cached data affects other

* feat: solve the problem that modifying the cached data affects other

* feat: search messages to filter out notifications

---------

Co-authored-by: withchao <withchao@users.noreply.github.com>
Co-authored-by: Monet Lee <monet_lee@163.com>
Co-authored-by: OpenIM-Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: icey-yu <1186114839@qq.com>
2024-08-02 08:58:04 +00:00
Monet Lee 51e170ade1 feat: implement scheduled destruct msgs feature in cron task. (#2466)
* update protocol in go mod.

* add debug log in writePongMsg.

* update log level.

* add Warn log in writePongMsg.

* add debug log.

* feat: update webhookBeforeMemberJoinGroup to batch method.

* feat: update version field implement.

* update webhook implement contents.

* update method field and contents.

* update callbackCommand field.

* fix: add correct fields.

* update struct tags.

* refactor: rename friend module to relation.

* feat: implement scheduled destruct msgs feature in cron task.

* update log contents.

* update func name and comments.

* update waitgroup to errgroup.

* update errgroup wait.

* remove unnecessary contents.

* update clearMsg logic.
2024-08-01 08:12:41 +00:00
chao 375f63a447 fix: online status renewal (#2468)
* fix: GroupApplicationAcceptedNotification

* fix: GroupApplicationAcceptedNotification

* fix: NotificationUserInfoUpdate

* cicd: robot automated Change

* fix: component

* fix: getConversationInfo

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* fix: minio config url recognition error

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* mage

* optimization version log

* optimization version log

* sync

* sync

* sync

* group sync

* sync option

* sync option

* refactor: replace `friend` package with `realtion`.

* refactor: update lastest commit to relation.

* sync option

* sync option

* sync option

* sync

* sync

* go.mod

* seq

* update: go mod

* refactor: change incremental to full

* feat: get full friend user ids

* feat: api and config

* seq

* group version

* merge

* seq

* seq

* seq

* fix: sort by id avoid unstable sort friends.

* group

* group

* group

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* user version

* seq

* seq

* seq user

* user online

* implement minio expire delete.

* user online

* config

* fix

* fix

* implement minio expire delete logic.

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* feat: implement scheduled delete outdated object in minio.

* update gomake version

* update gomake version

* implement FindExpires pagination.

* remove unnesseary incr.

* fix uncorrect args call.

* online push

* online push

* online push

* resolving conflicts

* resolving conflicts

* test

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* rpc prommetrics

* rpc prommetrics

* online status

* online status

* online status

* online status

* sub

* conversation version incremental

* merge seq

* merge online

* merge online

* merge online

* merge seq

* GetOwnerConversation

* fix: change incremental syncer router name.

* rockscache batch get

* rockscache seq batch get

* fix: GetMsgDocModelByIndex bug

* update go.mod

* update go.mod

* merge

* feat: prometheus

* feat: prometheus

* group member sort

* sub

* sub

* fix: seq conversion bug

* fix: redis pipe exec

* sort version

* sort version

* sort version

* remove old version online subscription

* remove old version online subscription

* version log index

* version log index

* batch push

* batch push

* seq void filling

* fix: batchGetMaxSeq

* fix: batchGetMaxSeq

* cache db error log

* 111

* fix bug

* fix: ImportFriends

* add online cache

* add some logs

* add some logs

* fix: onlineUserIDs

* add logs

* test

* test

* test

* test

---------

Co-authored-by: withchao <withchao@users.noreply.github.com>
Co-authored-by: Monet Lee <monet_lee@163.com>
Co-authored-by: OpenIM-Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: icey-yu <1186114839@qq.com>
2024-08-01 07:11:17 +00:00
Monet Lee 5dac91569d refactor: rename friend module to relation. (#2463)
* update protocol in go mod.

* add debug log in writePongMsg.

* update log level.

* add Warn log in writePongMsg.

* add debug log.

* feat: update webhookBeforeMemberJoinGroup to batch method.

* feat: update version field implement.

* update webhook implement contents.

* update method field and contents.

* update callbackCommand field.

* fix: add correct fields.

* update struct tags.

* refactor: rename friend module to relation.
2024-07-31 10:12:19 +00:00
chao 9cfbc3aaff fix: return value (#2462)
* fix: GroupApplicationAcceptedNotification

* fix: GroupApplicationAcceptedNotification

* fix: NotificationUserInfoUpdate

* cicd: robot automated Change

* fix: component

* fix: getConversationInfo

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* fix: minio config url recognition error

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* mage

* optimization version log

* optimization version log

* sync

* sync

* sync

* group sync

* sync option

* sync option

* refactor: replace `friend` package with `realtion`.

* refactor: update lastest commit to relation.

* sync option

* sync option

* sync option

* sync

* sync

* go.mod

* seq

* update: go mod

* refactor: change incremental to full

* feat: get full friend user ids

* feat: api and config

* seq

* group version

* merge

* seq

* seq

* seq

* fix: sort by id avoid unstable sort friends.

* group

* group

* group

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* user version

* seq

* seq

* seq user

* user online

* implement minio expire delete.

* user online

* config

* fix

* fix

* implement minio expire delete logic.

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* feat: implement scheduled delete outdated object in minio.

* update gomake version

* update gomake version

* implement FindExpires pagination.

* remove unnesseary incr.

* fix uncorrect args call.

* online push

* online push

* online push

* resolving conflicts

* resolving conflicts

* test

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* rpc prommetrics

* rpc prommetrics

* online status

* online status

* online status

* online status

* sub

* conversation version incremental

* merge seq

* merge online

* merge online

* merge online

* merge seq

* GetOwnerConversation

* fix: change incremental syncer router name.

* rockscache batch get

* rockscache seq batch get

* fix: GetMsgDocModelByIndex bug

* update go.mod

* update go.mod

* merge

* feat: prometheus

* feat: prometheus

* group member sort

* sub

* sub

* fix: seq conversion bug

* fix: redis pipe exec

* sort version

* sort version

* sort version

* remove old version online subscription

* remove old version online subscription

* version log index

* version log index

* batch push

* batch push

* seq void filling

* fix: batchGetMaxSeq

* fix: batchGetMaxSeq

* cache db error log

* 111

* fix bug

* fix: ImportFriends

* add online cache

* add some logs

* add some logs

---------

Co-authored-by: withchao <withchao@users.noreply.github.com>
Co-authored-by: Monet Lee <monet_lee@163.com>
Co-authored-by: OpenIM-Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: icey-yu <1186114839@qq.com>
2024-07-31 06:21:19 +00:00
chao d2b02dbabe feat: add some logs (#2461)
* fix: GroupApplicationAcceptedNotification

* fix: GroupApplicationAcceptedNotification

* fix: NotificationUserInfoUpdate

* cicd: robot automated Change

* fix: component

* fix: getConversationInfo

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* fix: minio config url recognition error

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* mage

* optimization version log

* optimization version log

* sync

* sync

* sync

* group sync

* sync option

* sync option

* refactor: replace `friend` package with `realtion`.

* refactor: update lastest commit to relation.

* sync option

* sync option

* sync option

* sync

* sync

* go.mod

* seq

* update: go mod

* refactor: change incremental to full

* feat: get full friend user ids

* feat: api and config

* seq

* group version

* merge

* seq

* seq

* seq

* fix: sort by id avoid unstable sort friends.

* group

* group

* group

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* user version

* seq

* seq

* seq user

* user online

* implement minio expire delete.

* user online

* config

* fix

* fix

* implement minio expire delete logic.

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* feat: implement scheduled delete outdated object in minio.

* update gomake version

* update gomake version

* implement FindExpires pagination.

* remove unnesseary incr.

* fix uncorrect args call.

* online push

* online push

* online push

* resolving conflicts

* resolving conflicts

* test

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* rpc prommetrics

* rpc prommetrics

* online status

* online status

* online status

* online status

* sub

* conversation version incremental

* merge seq

* merge online

* merge online

* merge online

* merge seq

* GetOwnerConversation

* fix: change incremental syncer router name.

* rockscache batch get

* rockscache seq batch get

* fix: GetMsgDocModelByIndex bug

* update go.mod

* update go.mod

* merge

* feat: prometheus

* feat: prometheus

* group member sort

* sub

* sub

* fix: seq conversion bug

* fix: redis pipe exec

* sort version

* sort version

* sort version

* remove old version online subscription

* remove old version online subscription

* version log index

* version log index

* batch push

* batch push

* seq void filling

* fix: batchGetMaxSeq

* fix: batchGetMaxSeq

* cache db error log

* 111

* fix bug

* fix: ImportFriends

* add online cache

* add some logs

---------

Co-authored-by: withchao <withchao@users.noreply.github.com>
Co-authored-by: Monet Lee <monet_lee@163.com>
Co-authored-by: OpenIM-Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: icey-yu <1186114839@qq.com>
2024-07-31 02:50:55 +00:00
Monet Lee fb689618d8 feat: update webhookBeforeMemberJoinGroup to batch method. (#2459)
* update protocol in go mod.

* add debug log in writePongMsg.

* update log level.

* add Warn log in writePongMsg.

* add debug log.

* feat: update webhookBeforeMemberJoinGroup to batch method.

* feat: update version field implement.

* update webhook implement contents.

* update method field and contents.

* update callbackCommand field.

* fix: add correct fields.

* update struct tags.
2024-07-30 10:09:52 +00:00
chao ed0ab58a9e fix ImportFriends (#2458)
* fix: GroupApplicationAcceptedNotification

* fix: GroupApplicationAcceptedNotification

* fix: NotificationUserInfoUpdate

* cicd: robot automated Change

* fix: component

* fix: getConversationInfo

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* fix: minio config url recognition error

* update gomake version

* update gomake version

* fix: seq conversion bug

* fix: redis pipe exec

* fix: ImportFriends

---------

Co-authored-by: withchao <withchao@users.noreply.github.com>
2024-07-29 08:53:26 +00:00
icey-yu 231aac2b8a fix: search log can return platform (#2456)
* fix: search log can return platform

* fix: change platform type to string
2024-07-29 08:37:22 +00:00
printlin b0cc4373a5 fix: #2410 BeforeMemberJoinGroup callback member error (#2423) 2024-07-29 02:08:28 +00:00
Monet Lee ef46abd193 chore: add Warn log in writePongMsg. (#2452)
* update protocol in go mod.

* add debug log in writePongMsg.

* update log level.

* add Warn log in writePongMsg.

* add debug log.
2024-07-28 03:18:23 +00:00
printlin 220a01d7f8 fix: fill notification offlinePush by config (#2422)
* fix: fill notification offlinePush by config

* fix: fill notification OfflinePush by config
2024-07-26 10:24:25 +00:00
blooming ff66e97221 fix: rm e2e in ci (#2449) 2024-07-26 18:20:54 +08:00
blooming e9b3a1952f cicd: add e2e in ci & before build docker image (#2346)
* cicd: add e2e in ci & before build docker image

* cicd: fix env minio addr

* cicd: fix build image timing
2024-07-26 08:36:11 +00:00
skiffer-git 7c3f6db0e3 Merge branch 'coderwander-main1' 2024-07-26 16:33:51 +08:00
skiffer-git caef9a1941 Merge branch 'main' of https://github.com/coderwander/open-im-server into coderwander-main1 2024-07-26 16:33:45 +08:00
skiffer-git 6c0c83eb3b Delete config/templates/env.template 2024-07-26 16:32:36 +08:00
skiffer-git 0a7992faab Update env.template 2024-07-26 16:30:58 +08:00
skiffer-git dd5c7e43d5 Merge branch 'coderwander-main' 2024-07-26 16:24:19 +08:00
skiffer-git a837fecda3 merge: fix some typos in comments 2024-07-26 16:23:45 +08:00
skiffer-git 69296539e2 Merge branch 'main' of https://github.com/openimsdk/open-im-server 2024-07-26 16:18:11 +08:00
chao 5c52840d67 fix: user seq, asynchronous friend notification, message search (#2447)
* fix: GroupApplicationAcceptedNotification

* fix: GroupApplicationAcceptedNotification

* fix: NotificationUserInfoUpdate

* cicd: robot automated Change

* fix: component

* fix: getConversationInfo

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* feat: cron task

* fix: minio config url recognition error

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* new mongo

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* friend incr sync

* mage

* optimization version log

* optimization version log

* sync

* sync

* sync

* group sync

* sync option

* sync option

* refactor: replace `friend` package with `realtion`.

* refactor: update lastest commit to relation.

* sync option

* sync option

* sync option

* sync

* sync

* go.mod

* seq

* update: go mod

* refactor: change incremental to full

* feat: get full friend user ids

* feat: api and config

* seq

* group version

* merge

* seq

* seq

* seq

* fix: sort by id avoid unstable sort friends.

* group

* group

* group

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* fix: sort by id avoid unstable sort friends.

* user version

* seq

* seq

* seq user

* user online

* implement minio expire delete.

* user online

* config

* fix

* fix

* implement minio expire delete logic.

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* online cache

* feat: implement scheduled delete outdated object in minio.

* update gomake version

* update gomake version

* implement FindExpires pagination.

* remove unnesseary incr.

* fix uncorrect args call.

* online push

* online push

* online push

* resolving conflicts

* resolving conflicts

* test

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* api prommetrics

* rpc prommetrics

* rpc prommetrics

* online status

* online status

* online status

* online status

* sub

* conversation version incremental

* merge seq

* merge online

* merge online

* merge online

* merge seq

* GetOwnerConversation

* fix: change incremental syncer router name.

* rockscache batch get

* rockscache seq batch get

* fix: GetMsgDocModelByIndex bug

* update go.mod

* update go.mod

* merge

* feat: prometheus

* feat: prometheus

* group member sort

* sub

* sub

* fix: seq conversion bug

* fix: redis pipe exec

* sort version

* sort version

* sort version

* remove old version online subscription

* remove old version online subscription

* version log index

* version log index

* batch push

* batch push

* seq void filling

* fix: batchGetMaxSeq

* fix: batchGetMaxSeq

* cache db error log

* 111

* fix bug

---------

Co-authored-by: withchao <withchao@users.noreply.github.com>
Co-authored-by: Monet Lee <monet_lee@163.com>
Co-authored-by: OpenIM-Gordon <46924906+FGadvancer@users.noreply.github.com>
Co-authored-by: icey-yu <1186114839@qq.com>
2024-07-26 07:53:25 +00:00
Monet Lee c3c9969f2f chore: add debug log in writePongMsg (#2446)
* update protocol in go mod.

* add debug log in writePongMsg.

* update log level.
2024-07-26 07:52:37 +00:00
icey-yu a8b84911a4 fix: display is read (#2444) 2024-07-26 06:40:36 +00:00
skiffer-git a321303b1b Merge branch 'main' of https://github.com/openimsdk/open-im-server 2024-06-03 18:48:04 +08:00
skiffer-git eb766ebd94 Merge branch 'main' of https://github.com/openimsdk/open-im-server 2024-05-30 14:21:55 +08:00
skiffer-git 6ab1244ad8 merge 2024-05-23 10:19:54 +08:00
skiffer-git 6a721f2eab Merge branch 'main' into main 2024-04-28 11:56:58 +08:00
coderwander 381fd1beeb chore: fix some typos in comments
Signed-off-by: coderwander <770732124@qq.com>
2024-04-16 11:30:20 +08:00
79 changed files with 1358 additions and 1707 deletions
-1
View File
@@ -1,4 +1,3 @@
MONGO_IMAGE=mongo:6.0.2 MONGO_IMAGE=mongo:6.0.2
REDIS_IMAGE=redis:7.0.0 REDIS_IMAGE=redis:7.0.0
ZOOKEEPER_IMAGE=bitnami/zookeeper:3.8 ZOOKEEPER_IMAGE=bitnami/zookeeper:3.8
+127 -91
View File
@@ -19,8 +19,27 @@ on:
branches: branches:
- main - main
- release-* - release-*
paths-ignore:
- "docs/**"
- "README.md"
- "README_zh-CN.md"
- "**.md"
- "docs/**"
- "CONTRIBUTING.md"
tags: tags:
- v* - v*
pull_request:
types: [closed]
branches:
- main
- release-*
paths-ignore:
- "docs/**"
- "README.md"
- "README_zh-CN.md"
- "**.md"
- "docs/**"
- "CONTRIBUTING.md"
workflow_dispatch: workflow_dispatch:
env: env:
@@ -29,22 +48,112 @@ env:
jobs: jobs:
build-dockerhub: build-dockerhub:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true)
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.merged == false) }}
steps: steps:
- name: Checkout - name: Checkout main repository
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
path: main-repo
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
# docker.io/openim/openim-server:latest - name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: ./main-repo
load: true
tags: "openim/openim-server:local"
- name: Checkout compose repository
uses: actions/checkout@v4
with:
repository: "openimsdk/openim-docker"
path: "compose-repo"
- name: Get Internal IP Address
id: get-ip
run: |
IP=$(hostname -I | awk '{print $1}')
echo "The IP Address is: $IP"
echo "::set-output name=ip::$IP"
- name: Update .env to use the local image
run: |
sed -i 's|OPENIM_SERVER_IMAGE=.*|OPENIM_SERVER_IMAGE=openim/openim-server:local|' ${{ github.workspace }}/compose-repo/.env
sed -i 's|MINIO_EXTERNAL_ADDRESS=.*|MINIO_EXTERNAL_ADDRESS=http://${{ steps.get-ip.outputs.ip }}:10005|' ${{ github.workspace }}/compose-repo/.env
- name: Start services using Docker Compose
run: |
cd ${{ github.workspace }}/compose-repo
docker compose up -d
sleep 30
- name: Check openim-server health
run: |
timeout=300
interval=30
elapsed=0
while [[ $elapsed -le $timeout ]]; do
if ! docker exec openim-server mage check; then
echo "openim-server is not ready, waiting..."
sleep $interval
elapsed=$(($elapsed + $interval))
else
echo "Health check successful"
exit 0
fi
done
echo "Health check failed after 5 minutes"
exit 1
- name: Check openim-chat health
if: success()
run: |
if ! docker exec openim-chat mage check; then
echo "openim-chat check failed"
exit 1
else
echo "Health check successful"
exit 0
fi
# - name: Checkout e2e
# if: success()
# uses: actions/checkout@v4
# with:
# repository: "openimsdk/test-e2e"
# path: e2e-repo
# - name: Set up Python 3.9
# uses: actions/setup-python@v4
# with:
# python-version: '3.9'
# - name: Install dependencies
# run: |
# sudo apt-get update
# sudo apt-get install -y xvfb libxi6 libgconf-2-4
# cd ${{ github.workspace }}/e2e-repo
# pip install -r requirements.txt
# - name: Run tests
# run: |
# cd ${{ github.workspace }}/e2e-repo
# xvfb-run --auto-servernum --server-args='-screen 0 1920x1080x24' pytest -v -s ./script
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
if: success()
id: meta id: meta
uses: docker/metadata-action@v5.5.1 uses: docker/metadata-action@v5.5.1
with: with:
images: openim/openim-server images: |
openim/openim-server
ghcr.io/openimsdk/openim-server
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server
# generate Docker tags based on the following events/attributes # generate Docker tags based on the following events/attributes
tags: | tags: |
type=ref,event=tag type=ref,event=tag
@@ -58,105 +167,32 @@ jobs:
type=sha type=sha
- name: Log in to Docker Hub - name: Log in to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v2
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
# linux/ppc64le,linux/s390x
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-aliyun:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server:latest
- name: Extract metadata (tags, labels) for Docker
id: meta2
uses: docker/metadata-action@v5.5.1
with:
images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server
# generate Docker tags based on the following events/attributes
tags: |
type=ref,event=tag
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern=v{{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Log in to AliYun Docker Hub
uses: docker/login-action@v3
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ALIREGISTRY_USERNAME }}
password: ${{ secrets.ALIREGISTRY_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
# linux/ppc64le,linux/s390x
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta2.outputs.tags }}
labels: ${{ steps.meta2.outputs.labels }}
build-ghcr:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# ghcr.io/openimsdk/openim-server:latest
- name: Extract metadata (tags, labels) for Docker
id: meta3
uses: docker/metadata-action@v5.5.1
with:
images: ghcr.io/openimsdk/openim-server
# generate Docker tags based on the following events/attributes
tags: |
type=ref,event=tag
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern=v{{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Log in to GitHub Container Registry - name: Log in to GitHub Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v2
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Aliyun Container Registry
uses: docker/login-action@v2
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ALIREGISTRY_USERNAME }}
password: ${{ secrets.ALIREGISTRY_TOKEN }}
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: . context: ./main-repo
push: true
# linux/ppc64le,linux/s390x # linux/ppc64le,linux/s390x
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }}
tags: ${{ steps.meta3.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}
labels: ${{ steps.meta3.outputs.labels }}
-53
View File
@@ -1,53 +0,0 @@
# Copyright © 2023 OpenIM open source community. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Github Rebot for Link check error
# Every Monday at 12:30 p.m
on:
schedule:
- cron: '30 12 * * 1'
jobs:
linkChecker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Link Checker
id: lychee
uses: lycheeverse/lychee-action@v1.9.3
with:
# For parameter description, see https://github.com/lycheeverse/lychee#commandline-parameters
# Actions Link address -> https://github.com/lycheeverse/lychee-action
# -E, --exclude-all-private Exclude all private IPs from checking.
# -i, --insecure Proceed for server connections considered insecure (invalid TLS)
# -n, --no-progress Do not show progress bar.
# -t, --timeout <timeout> Website timeout in seconds from connect to response finished [default:20]
# --max-concurrency <max-concurrency> Maximum number of concurrent network requests [default: 128]
# -a --accept <accept> Comma-separated list of accepted status codes for valid links
# docs/.vitepress/dist the site directory to check
# ./*.md all markdown files in the root directory
args: --verbose -E -i --no-progress --exclude-path './CHANGELOG' './**/*.md'
env:
GITHUB_TOKEN: ${{secrets.BOT_GITHUB_TOKEN}}
- name: Create Issue From File
if: env.lychee_exit_code != 0
uses: peter-evans/create-issue-from-file@v5
with:
title: Bug reports for links in OpenIM docs
content-filepath: ./lychee/out.md
labels: kind/documentation, triage/unresolved, report
token: ${{ secrets.BOT_GITHUB_TOKEN }}
+47 -103
View File
@@ -71,6 +71,18 @@ jobs:
run: sudo bash bootstrap.sh run: sudo bash bootstrap.sh
timeout-minutes: 20 timeout-minutes: 20
# - name: Get Internal IP Address
# id: get-ip
# run: |
# IP=$(hostname -I | awk '{print $1}')
# echo "The IP Address is: $IP"
# echo "::set-output name=ip::$IP"
# - name: Update .env
# run: |
# sed -i 's|externalAddress:.*|externalAddress: "http://${{ steps.get-ip.outputs.ip }}:10005"|' config/minio.yml
# cat config/minio.yml
- name: Build, Start, Check Services and Print Logs for Linux - name: Build, Start, Check Services and Print Logs for Linux
run: | run: |
sudo mage sudo mage
@@ -84,108 +96,40 @@ jobs:
sudo mage start sudo mage start
sudo mage check sudo mage check
- name: Checkout chat repository
uses: actions/checkout@v4
with:
repository: 'openimsdk/chat'
path: 'chat-repo'
# build-mac: - name: Build and Start Chat Services
# name: Execute OpenIM Script On macOS run: |
# runs-on: macos-latest cd ${{ github.workspace }}/chat-repo
# permissions: sudo mage
# contents: write sudo mage start
# pull-requests: write sudo mage check
# environment:
# name: openim # - name: Checkout e2e repository
# strategy: # uses: actions/checkout@v4
# matrix: # with:
# arch: [arm64, armv7, amd64] # repository: "openimsdk/test-e2e"
# # path: e2e-repo
# steps:
# - uses: actions/checkout@v3
# - name: Set up Go # - name: Set up Python 3.9
# uses: actions/setup-go@v4 # uses: actions/setup-python@v4
# with: # with:
# go-version: '1.21' # python-version: '3.9'
# - name: Install dependencies
# while ! docker system info > /dev/null 2>&1; do # run: |
# echo "Waiting for Docker to start..." # sudo apt-get update
# sleep 10 # Increased delay to ensure Docker starts properly # sudo apt-get install -y xvfb libxi6 libgconf-2-4
# done # cd ${{ github.workspace }}/e2e-repo
# pip install -r requirements.txt
# - name: Install Docker
# run: | # - name: Run tests
# brew install docker # run: |
# brew install docker-compose # cd ${{ github.workspace }}/e2e-repo
# sleep 10 # xvfb-run --auto-servernum --server-args='-screen 0 1920x1080x24' pytest -v -s ./script
# docker-compose up -d
# sleep 30
# timeout-minutes: 20
#
# - name: init
# run: sudo bash bootstrap.sh
# timeout-minutes: 20
# - name: Build, Start, Check Services and Print Logs for Linux
# run: |
# sudo mage
# sudo mage start
# sudo mage check
# - name: Restart Services and Print Logs
# run: |
# sudo mage stop
# sudo mage start
# sudo mage check
# build-windows:
# name: Execute OpenIM Script On Windows
# runs-on: windows-latest
# permissions:
# contents: write
# pull-requests: write
# environment:
# name: openim
# strategy:
# matrix:
# arch: [arm64, armv7, amd64]
#
# steps:
# - uses: actions/checkout@v3
# - name: Set up Go
# uses: actions/setup-go@v4
# with:
# go-version: '1.21'
# - name: Set up Docker for Windows
# run: |
# $images = @("zookeeper", "redis", "kafka")
# foreach ($image in $images) {
# $tag = "$image:latest"
# docker pull $tag | Out-Null
# if ($LASTEXITCODE -ne 0) {
# Write-Host "Skipping $image as it is not available for Windows"
# } else {
# Write-Host "Successfully pulled $image"
# }
# }
# docker compose up -d
# Start-Sleep -Seconds 30
# timeout-minutes: 20
# shell: pwsh
# - name: init
# run: bootstrap.bat
# timeout-minutes: 20
# - name: Build, Start, Check Services and Print Logs for Linux
# run: |
# mage
# mage start
# mage check
# - name: Restart Services and Print Logs
# run: |
# mage stop
# mage start
# mage check
-48
View File
@@ -1,48 +0,0 @@
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Mark stale issues and pull requests
on:
schedule:
- cron: '0 8 * * 1'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.BOT_GITHUB_TOKEN }}
days-before-stale: 60
days-before-close: 305
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message: 'This issue is stale because it has been open 60 days with no activity.'
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity. You can reopen it if you want.'
stale-pr-label: lifecycle/stale
stale-issue-label: lifecycle/stale
exempt-issue-labels: 'openim'
exempt-pr-labels: 'openim'
exempt-draft-pr: true
-56
View File
@@ -1,56 +0,0 @@
# Version logging for OpenIM
> **Note**:
> Deprecated version logging for OpenIM, please refer to [CHANGELOG.md](../CHANGELOG.md)
<!-- BEGIN MUNGE: GENERATED_TOC -->
- [Version logging for OpenIM](#version-logging-for-openim)
- [Unreleased](#unreleased)
- [v1.0.7 - 2021-12-17](#v107---2021-12-17)
- [v1.0.6 - 2021-12-10](#v106---2021-12-10)
- [v1.0.5 - 2021-12-03](#v105---2021-12-03)
- [v1.0.4 - 2021-11-25](#v104---2021-11-25)
- [v1.0.3 - 2021-11-12](#v103---2021-11-12)
- [v1.0.1 - 2021-11-04](#v101---2021-11-04)
- [v1.0.0 - 2021-10-28](#v100---2021-10-28)
- [Reverts](#reverts)
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v1.0.7"></a>
## [v1.0.7] - 2021-12-17
<a name="v1.0.6"></a>
## [v1.0.6] - 2021-12-10
<a name="v1.0.5"></a>
## [v1.0.5] - 2021-12-03
<a name="v1.0.4"></a>
## [v1.0.4] - 2021-11-25
<a name="v1.0.3"></a>
## [v1.0.3] - 2021-11-12
<a name="v1.0.1"></a>
## [v1.0.1] - 2021-11-04
<a name="v1.0.0"></a>
## v1.0.0 - 2021-10-28
### Reverts
- friend modify
- update
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v1.0.7...HEAD
[v1.0.7]: https://github.com/openimsdk/open-im-server/compare/v1.0.6...v1.0.7
[v1.0.6]: https://github.com/openimsdk/open-im-server/compare/v1.0.5...v1.0.6
[v1.0.5]: https://github.com/openimsdk/open-im-server/compare/v1.0.4...v1.0.5
[v1.0.4]: https://github.com/openimsdk/open-im-server/compare/v1.0.3...v1.0.4
[v1.0.3]: https://github.com/openimsdk/open-im-server/compare/v1.0.1...v1.0.3
[v1.0.1]: https://github.com/openimsdk/open-im-server/compare/v1.0.0...v1.0.1
-87
View File
@@ -1,87 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v2.0.10"></a>
## [v2.0.10] - 2022-05-13
<a name="v2.0.9"></a>
## [v2.0.9] - 2022-04-29
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.8"></a>
## [v2.0.8] - 2022-04-24
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.7"></a>
## [v2.0.7] - 2022-04-08
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.6"></a>
## [v2.0.6] - 2022-04-01
### Pull Requests
- Merge branch 'tuoyun'
<a name="v2.0.5"></a>
## [v2.0.5] - 2022-03-24
<a name="v2.04"></a>
## [v2.04] - 2022-03-18
<a name="v2.0.3"></a>
## [v2.0.3] - 2022-03-11
<a name="v2.0.2"></a>
## [v2.0.2] - 2022-03-04
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.1"></a>
## [v2.0.1] - 2022-02-25
<a name="v2.0.0"></a>
## v2.0.0 - 2022-02-23
### Reverts
- friend modify
- update
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v2.0.10...HEAD
[v2.0.10]: https://github.com/openimsdk/open-im-server/compare/v2.0.9...v2.0.10
[v2.0.9]: https://github.com/openimsdk/open-im-server/compare/v2.0.8...v2.0.9
[v2.0.8]: https://github.com/openimsdk/open-im-server/compare/v2.0.7...v2.0.8
[v2.0.7]: https://github.com/openimsdk/open-im-server/compare/v2.0.6...v2.0.7
[v2.0.6]: https://github.com/openimsdk/open-im-server/compare/v2.0.5...v2.0.6
[v2.0.5]: https://github.com/openimsdk/open-im-server/compare/v2.04...v2.0.5
[v2.04]: https://github.com/openimsdk/open-im-server/compare/v2.0.3...v2.04
[v2.0.3]: https://github.com/openimsdk/open-im-server/compare/v2.0.2...v2.0.3
[v2.0.2]: https://github.com/openimsdk/open-im-server/compare/v2.0.1...v2.0.2
[v2.0.1]: https://github.com/openimsdk/open-im-server/compare/v2.0.0...v2.0.1
-50
View File
@@ -1,50 +0,0 @@
# Version logging for OpenIM:v2.1
> **Note**:
> Deprecated version logging for OpenIM, please refer to [CHANGELOG.md](../CHANGELOG.md)
<!-- BEGIN MUNGE: GENERATED_TOC -->
- [Version logging for OpenIM:v2.1](#version-logging-for-openimv21)
- [Unreleased](#unreleased)
- [v2.1.0 - 2022-06-17](#v210---2022-06-17)
- [Reverts](#reverts)
- [Pull Requests](#pull-requests)
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v2.1.0"></a>
## v2.1.0 - 2022-06-17
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
- friend modify
- update
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v2.1.0...HEAD
-50
View File
@@ -1,50 +0,0 @@
# Version logging for OpenIM:v2.2
> **Note**:
> Deprecated version logging for OpenIM, please refer to [CHANGELOG.md](../CHANGELOG.md)
<!-- BEGIN MUNGE: GENERATED_TOC -->
- [Version logging for OpenIM:v2.2](#version-logging-for-openimv22)
- [Unreleased](#unreleased)
- [v2.2.0 - 2022-07-01](#v220---2022-07-01)
- [Reverts](#reverts)
- [Pull Requests](#pull-requests)
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v2.2.0"></a>
## v2.2.0 - 2022-07-01
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
- friend modify
- update
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v2.2.0...HEAD
-70
View File
@@ -1,70 +0,0 @@
# Version logging for OpenIM:v2.3
> **Note**:
> Deprecated version logging for OpenIM, please refer to [CHANGELOG.md](../CHANGELOG.md)
<!-- BEGIN MUNGE: GENERATED_TOC -->
- [Version logging for OpenIM:v2.3](#version-logging-for-openimv23)
- [Unreleased](#unreleased)
- [v2.3.3 - 2022-09-18](#v233---2022-09-18)
- [v2.3.2 - 2022-09-09](#v232---2022-09-09)
- [v2.3.0-rc2 - 2022-07-29](#v230-rc2---2022-07-29)
- [v2.3.0-rc1 - 2022-07-25](#v230-rc1---2022-07-25)
- [v2.3.0-rc0 - 2022-07-15](#v230-rc0---2022-07-15)
- [Reverts](#reverts)
- [Pull Requests](#pull-requests)
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v2.3.3"></a>
## [v2.3.3] - 2022-09-18
<a name="v2.3.2"></a>
## [v2.3.2] - 2022-09-09
<a name="v2.3.0-rc2"></a>
## [v2.3.0-rc2] - 2022-07-29
<a name="v2.3.0-rc1"></a>
## [v2.3.0-rc1] - 2022-07-25
<a name="v2.3.0-rc0"></a>
## v2.3.0-rc0 - 2022-07-15
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
- friend modify
- update
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v2.3.3...HEAD
[v2.3.3]: https://github.com/openimsdk/open-im-server/compare/v2.3.2...v2.3.3
[v2.3.2]: https://github.com/openimsdk/open-im-server/compare/v2.3.0-rc2...v2.3.2
[v2.3.0-rc2]: https://github.com/openimsdk/open-im-server/compare/v2.3.0-rc1...v2.3.0-rc2
[v2.3.0-rc1]: https://github.com/openimsdk/open-im-server/compare/v2.3.0-rc0...v2.3.0-rc1
-52
View File
@@ -1,52 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
- [Version logging for OpenIM](#version-logging-for-openim)
- [Unreleased](#unreleased)
- [v2.9.0+1.839643f - 2023-07-07](#v2901839643f---2023-07-07)
- [v2.9.0+2.35f07fe - 2023-07-06](#v290235f07fe---2023-07-06)
- [v2.9.0+1.b5072b1 - 2023-07-05](#v2901b5072b1---2023-07-05)
- [v2.9.0+3.2667a3a - 2023-07-05](#v29032667a3a---2023-07-05)
- [v2.9.0+7.04818ca - 2023-07-05](#v290704818ca---2023-07-05)
- [v2.9.0 - 2023-07-04](#v290---2023-07-04)
- [Reverts](#reverts)
- [Pull Requests](#pull-requests)
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v2.9.0+1.839643f"></a>
## [v2.9.0+1.839643f] - 2023-07-07
<a name="v2.9.0+2.35f07fe"></a>
## [v2.9.0+2.35f07fe] - 2023-07-06
<a name="v2.9.0+1.b5072b1"></a>
## [v2.9.0+1.b5072b1] - 2023-07-05
<a name="v2.9.0+3.2667a3a"></a>
## [v2.9.0+3.2667a3a] - 2023-07-05
<a name="v2.9.0+7.04818ca"></a>
## [v2.9.0+7.04818ca] - 2023-07-05
<a name="v2.9.0"></a>
## v2.9.0 - 2023-07-04
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v2.9.0+1.839643f...HEAD
[v2.9.0+1.839643f]: https://github.com/openimsdk/open-im-server/compare/v2.9.0+2.35f07fe...v2.9.0+1.839643f
[v2.9.0+2.35f07fe]: https://github.com/openimsdk/open-im-server/compare/v2.9.0+1.b5072b1...v2.9.0+2.35f07fe
[v2.9.0+1.b5072b1]: https://github.com/openimsdk/open-im-server/compare/v2.9.0+3.2667a3a...v2.9.0+1.b5072b1
[v2.9.0+3.2667a3a]: https://github.com/openimsdk/open-im-server/compare/v2.9.0+7.04818ca...v2.9.0+3.2667a3a
[v2.9.0+7.04818ca]: https://github.com/openimsdk/open-im-server/compare/v2.9.0...v2.9.0+7.04818ca
-188
View File
@@ -1,188 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
- [Version logging for OpenIM](#version-logging-for-openim)
- [Unreleased](#unreleased)
- [v2.9.0 - 2023-07-04](#v290---2023-07-04)
- [Reverts](#reverts)
- [Pull Requests](#pull-requests)
- [v2.3.3 - 2022-09-18](#v233---2022-09-18)
- [v2.3.2 - 2022-09-09](#v232---2022-09-09)
- [v2.3.0-rc2 - 2022-07-29](#v230-rc2---2022-07-29)
- [v2.3.0-rc1 - 2022-07-25](#v230-rc1---2022-07-25)
- [v2.3.0-rc0 - 2022-07-15](#v230-rc0---2022-07-15)
- [v2.2.0 - 2022-07-01](#v220---2022-07-01)
- [v2.1.0 - 2022-06-17](#v210---2022-06-17)
- [Pull Requests](#pull-requests-1)
- [v2.0.10 - 2022-05-13](#v2010---2022-05-13)
- [v2.0.9 - 2022-04-29](#v209---2022-04-29)
- [Reverts](#reverts-1)
- [Pull Requests](#pull-requests-2)
- [v2.0.7 - 2022-04-08](#v207---2022-04-08)
- [Pull Requests](#pull-requests-3)
- [v2.0.6 - 2022-04-01](#v206---2022-04-01)
- [Pull Requests](#pull-requests-4)
- [v2.0.5 - 2022-03-24](#v205---2022-03-24)
- [v2.04 - 2022-03-18](#v204---2022-03-18)
- [v2.0.3 - 2022-03-11](#v203---2022-03-11)
- [v2.0.2 - 2022-03-04](#v202---2022-03-04)
- [Pull Requests](#pull-requests-5)
- [v2.0.1 - 2022-02-25](#v201---2022-02-25)
- [v2.0.0 - 2022-02-23](#v200---2022-02-23)
- [v1.0.7 - 2021-12-17](#v107---2021-12-17)
- [v1.0.6 - 2021-12-10](#v106---2021-12-10)
- [v1.0.5 - 2021-12-03](#v105---2021-12-03)
- [v1.0.4 - 2021-11-25](#v104---2021-11-25)
- [v1.0.3 - 2021-11-12](#v103---2021-11-12)
- [v1.0.1 - 2021-11-04](#v101---2021-11-04)
- [v1.0.0 - 2021-10-28](#v100---2021-10-28)
- [Reverts](#reverts-2)
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v2.9.0"></a>
## [v2.9.0] - 2023-07-04
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
<a name="v2.3.3"></a>
## [v2.3.3] - 2022-09-18
<a name="v2.3.2"></a>
## [v2.3.2] - 2022-09-09
<a name="v2.3.0-rc2"></a>
## [v2.3.0-rc2] - 2022-07-29
<a name="v2.3.0-rc1"></a>
## [v2.3.0-rc1] - 2022-07-25
<a name="v2.3.0-rc0"></a>
## [v2.3.0-rc0] - 2022-07-15
<a name="v2.2.0"></a>
## [v2.2.0] - 2022-07-01
<a name="v2.1.0"></a>
## [v2.1.0] - 2022-06-17
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.10"></a>
## [v2.0.10] - 2022-05-13
<a name="v2.0.9"></a>
## [v2.0.9] - 2022-04-29
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.7"></a>
## [v2.0.7] - 2022-04-08
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.6"></a>
## [v2.0.6] - 2022-04-01
### Pull Requests
- Merge branch 'tuoyun'
<a name="v2.0.5"></a>
## [v2.0.5] - 2022-03-24
<a name="v2.04"></a>
## [v2.04] - 2022-03-18
<a name="v2.0.3"></a>
## [v2.0.3] - 2022-03-11
<a name="v2.0.2"></a>
## [v2.0.2] - 2022-03-04
### Pull Requests
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
- Merge branch 'tuoyun'
<a name="v2.0.1"></a>
## [v2.0.1] - 2022-02-25
<a name="v2.0.0"></a>
## [v2.0.0] - 2022-02-23
<a name="v1.0.7"></a>
## [v1.0.7] - 2021-12-17
<a name="v1.0.6"></a>
## [v1.0.6] - 2021-12-10
<a name="v1.0.5"></a>
## [v1.0.5] - 2021-12-03
<a name="v1.0.4"></a>
## [v1.0.4] - 2021-11-25
<a name="v1.0.3"></a>
## [v1.0.3] - 2021-11-12
<a name="v1.0.1"></a>
## [v1.0.1] - 2021-11-04
<a name="v1.0.0"></a>
## v1.0.0 - 2021-10-28
### Reverts
- friend modify
- update
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v2.9.0...HEAD
[v2.9.0]: https://github.com/openimsdk/open-im-server/compare/v2.3.3...v2.9.0
[v2.3.3]: https://github.com/openimsdk/open-im-server/compare/v2.3.2...v2.3.3
[v2.3.2]: https://github.com/openimsdk/open-im-server/compare/v2.3.0-rc2...v2.3.2
[v2.3.0-rc2]: https://github.com/openimsdk/open-im-server/compare/v2.3.0-rc1...v2.3.0-rc2
[v2.3.0-rc1]: https://github.com/openimsdk/open-im-server/compare/v2.3.0-rc0...v2.3.0-rc1
[v2.3.0-rc0]: https://github.com/openimsdk/open-im-server/compare/v2.2.0...v2.3.0-rc0
[v2.2.0]: https://github.com/openimsdk/open-im-server/compare/v2.1.0...v2.2.0
[v2.1.0]: https://github.com/openimsdk/open-im-server/compare/v2.0.10...v2.1.0
[v2.0.10]: https://github.com/openimsdk/open-im-server/compare/v2.0.9...v2.0.10
[v2.0.9]: https://github.com/openimsdk/open-im-server/compare/v2.0.7...v2.0.9
[v2.0.7]: https://github.com/openimsdk/open-im-server/compare/v2.0.6...v2.0.7
[v2.0.6]: https://github.com/openimsdk/open-im-server/compare/v2.0.5...v2.0.6
[v2.0.5]: https://github.com/openimsdk/open-im-server/compare/v2.04...v2.0.5
[v2.04]: https://github.com/openimsdk/open-im-server/compare/v2.0.3...v2.04
[v2.0.3]: https://github.com/openimsdk/open-im-server/compare/v2.0.2...v2.0.3
[v2.0.2]: https://github.com/openimsdk/open-im-server/compare/v2.0.1...v2.0.2
[v2.0.1]: https://github.com/openimsdk/open-im-server/compare/v2.0.0...v2.0.1
[v2.0.0]: https://github.com/openimsdk/open-im-server/compare/v1.0.7...v2.0.0
[v1.0.7]: https://github.com/openimsdk/open-im-server/compare/v1.0.6...v1.0.7
[v1.0.6]: https://github.com/openimsdk/open-im-server/compare/v1.0.5...v1.0.6
[v1.0.5]: https://github.com/openimsdk/open-im-server/compare/v1.0.4...v1.0.5
[v1.0.4]: https://github.com/openimsdk/open-im-server/compare/v1.0.3...v1.0.4
[v1.0.3]: https://github.com/openimsdk/open-im-server/compare/v1.0.1...v1.0.3
[v1.0.1]: https://github.com/openimsdk/open-im-server/compare/v1.0.0...v1.0.1
-20
View File
@@ -1,20 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v3.1.0"></a>
## v3.1.0 - 2023-07-28
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.1.0...HEAD
-32
View File
@@ -1,32 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v3.2.2-alpha.0"></a>
## [v3.2.2-alpha.0] - 2023-08-25
<a name="v3.2.0"></a>
## [v3.2.0] - 2023-08-19
<a name="v3.2.0-rc.0"></a>
## [v3.2.0-rc.0] - 2023-08-17
<a name="v3.2.0-alpha.0"></a>
## v3.2.0-alpha.0 - 2023-08-16
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.2.2-alpha.0...HEAD
[v3.2.2-alpha.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.0...v3.2.2-alpha.0
[v3.2.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.0-rc.0...v3.2.0
[v3.2.0-rc.0]: https://github.com/openimsdk/open-im-server/compare/v3.2.0-alpha.0...v3.2.0-rc.0
-40
View File
@@ -1,40 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v3.3.1"></a>
## [v3.3.1] - 2023-09-13
<a name="v3.3.1-beta.0"></a>
## [v3.3.1-beta.0] - 2023-09-11
<a name="v3.3.0-rc.1"></a>
## [v3.3.0-rc.1] - 2023-09-11
<a name="v3.3.0-rc.12"></a>
## [v3.3.0-rc.12] - 2023-09-11
<a name="v3.3.0"></a>
## [v3.3.0] - 2023-09-09
<a name="v3.3.0-rc.0"></a>
## v3.3.0-rc.0 - 2023-09-07
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.3.1...HEAD
[v3.3.1]: https://github.com/openimsdk/open-im-server/compare/v3.3.1-beta.0...v3.3.1
[v3.3.1-beta.0]: https://github.com/openimsdk/open-im-server/compare/v3.3.0-rc.1...v3.3.1-beta.0
[v3.3.0-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.3.0-rc.12...v3.3.0-rc.1
[v3.3.0-rc.12]: https://github.com/openimsdk/open-im-server/compare/v3.3.0...v3.3.0-rc.12
[v3.3.0]: https://github.com/openimsdk/open-im-server/compare/v3.3.0-rc.0...v3.3.0
-32
View File
@@ -1,32 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v3.4.2"></a>
## [v3.4.2] - 2023-12-14
<a name="v3.4.0"></a>
## [v3.4.0] - 2023-11-10
<a name="v3.4.0-rc.1"></a>
## [v3.4.0-rc.1] - 2023-11-09
<a name="v3.4.0-rc.0"></a>
## v3.4.0-rc.0 - 2023-11-09
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.4.2...HEAD
[v3.4.2]: https://github.com/openimsdk/open-im-server/compare/v3.4.0...v3.4.2
[v3.4.0]: https://github.com/openimsdk/open-im-server/compare/v3.4.0-rc.1...v3.4.0
[v3.4.0-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.4.0-rc.0...v3.4.0-rc.1
-84
View File
@@ -1,84 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v3.5.1-alpha.2"></a>
## [v3.5.1-alpha.2] - 2024-01-26
<a name="v3.5.1-rc.1"></a>
## [v3.5.1-rc.1] - 2024-01-23
<a name="v3.5.1-alpha.1"></a>
## [v3.5.1-alpha.1] - 2024-01-09
<a name="v3.5.0"></a>
## [v3.5.0] - 2024-01-02
<a name="v3.5.1"></a>
## [v3.5.1] - 2024-01-02
<a name="v3.5.1-bate.1"></a>
## [v3.5.1-bate.1] - 2024-01-02
<a name="v3.5.1-rc.0"></a>
## [v3.5.1-rc.0] - 2023-12-30
<a name="v3.5.0-rc.8"></a>
## [v3.5.0-rc.8] - 2023-12-28
<a name="v3.5.0-rc.7"></a>
## [v3.5.0-rc.7] - 2023-12-18
<a name="v3.5.0-rc.6"></a>
## [v3.5.0-rc.6] - 2023-12-15
<a name="v3.5.0-rc.5"></a>
## [v3.5.0-rc.5] - 2023-12-15
<a name="v3.5.0-rc.4"></a>
## [v3.5.0-rc.4] - 2023-12-14
<a name="v3.5.0-rc.3"></a>
## [v3.5.0-rc.3] - 2023-12-14
<a name="v3.5.0-rc.2"></a>
## [v3.5.0-rc.2] - 2023-12-14
<a name="v3.5.0-rc.1"></a>
## [v3.5.0-rc.1] - 2023-12-14
<a name="v3.5.0-rc.0"></a>
## [v3.5.0-rc.0] - 2023-12-14
<a name="v3.5.0-beta.1"></a>
## v3.5.0-beta.1 - 2023-11-29
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-alpha.2...HEAD
[v3.5.1-alpha.2]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-rc.1...v3.5.1-alpha.2
[v3.5.1-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-alpha.1...v3.5.1-rc.1
[v3.5.1-alpha.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.0...v3.5.1-alpha.1
[v3.5.0]: https://github.com/openimsdk/open-im-server/compare/v3.5.1...v3.5.0
[v3.5.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-bate.1...v3.5.1
[v3.5.1-bate.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.1-rc.0...v3.5.1-bate.1
[v3.5.1-rc.0]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.8...v3.5.1-rc.0
[v3.5.0-rc.8]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.7...v3.5.0-rc.8
[v3.5.0-rc.7]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.6...v3.5.0-rc.7
[v3.5.0-rc.6]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.5...v3.5.0-rc.6
[v3.5.0-rc.5]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.4...v3.5.0-rc.5
[v3.5.0-rc.4]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.3...v3.5.0-rc.4
[v3.5.0-rc.3]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.2...v3.5.0-rc.3
[v3.5.0-rc.2]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.1...v3.5.0-rc.2
[v3.5.0-rc.1]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-rc.0...v3.5.0-rc.1
[v3.5.0-rc.0]: https://github.com/openimsdk/open-im-server/compare/v3.5.0-beta.1...v3.5.0-rc.0
-20
View File
@@ -1,20 +0,0 @@
# Version logging for OpenIM
<!-- BEGIN MUNGE: GENERATED_TOC -->
<!-- END MUNGE: GENERATED_TOC -->
<a name="unreleased"></a>
## [Unreleased]
<a name="v3.6.0"></a>
## v3.6.0 - 2024-03-07
### Reverts
- update etcd to v3.5.2 ([#206](https://github.com/openimsdk/open-im-server/issues/206))
### Pull Requests
- Merge branch 'tuoyun'
[Unreleased]: https://github.com/openimsdk/open-im-server/compare/v3.6.0...HEAD
-173
View File
@@ -1,173 +0,0 @@
# Changelog
- [Changelog](#changelog)
- [OpenIM versioning policy](#openim-versioning-policy)
- [command](#command)
- [install](#install)
- [User](#user)
- [create next tag](#create-next-tag)
- [Release version logs](#release-version-logs)
- [Introduction](#introduction)
- [Naming Format](#naming-format)
- [Examples](#examples)
- [Version Modifiers](#version-modifiers)
- [Versioning Strategy](#versioning-strategy)
All notable changes to this project will be documented in this file.
+ [https://github.com/openimsdk/open-im-server/releases](https://github.com/openimsdk/open-im-server/releases)
## OpenIM versioning policy
+ [OpenIM Version](../docs/contrib/version.md)
## command
To use git-chglog you need to configure:
1. CHANGELOG templates
2. git-chglog configuration
### install
```bash
$ go get github.com/git-chglog/git-chglog/cmd/git-chglog
```
## User
```bash
$ git-chglog --init
```
**Options**
- What is the URL of your repository?: https://github.com/openimsdk/open-im-server
- What is your favorite style?: github
- Choose the format of your favorite commit message: <type>(<scope>): <subject> -- feat(core): Add new feature
- What is your favorite template style?: standard
- Do you include Merge Commit in CHANGELOG?: n
- Do you include Revert Commit in CHANGELOG?: y
- In which directory do you output configuration files and templates?: .chglog
```bash
git-chglog --tag-filter-pattern 'v2.0.*' -o CHANGELOG-2.0.md
```
**Other uses:**
```bash
$ git-chglog
If <tag query> is not specified, it corresponds to all tags.
This is the simplest example.
$ git-chglog 1.0.0..2.0.0
The above is a command to generate CHANGELOG including commit of 1.0.0 to 2.0.0.
$ git-chglog 1.0.0
The above is a command to generate CHANGELOG including commit of only 1.0.0.
$ git-chglog $(git describe --tags $(git rev-list --tags --max-count=1))
The above is a command to generate CHANGELOG with the commit included in the latest tag.
$ git-chglog --output CHANGELOG.md
The above is a command to output to CHANGELOG.md instead of standard output.
$ git-chglog --config custom/dir/config.yml
The above is a command that uses a configuration file placed other than ".chglog/config.yml".
```
## create next tag
```bash
$ git-chglog --next-tag 2.0.0 -o CHANGELOG.md
$ git commit -am "release 2.0.0"
$ git tag 2.0.0
```
| Query | Description | Example |
| -------------- | ---------------------------------------------- | --------------------------- |
| `<old>..<new>` | Commit contained in `<new>` tags from `<old>`. | `$ git-chglog 1.0.0..2.0.0` |
| `<name>..` | Commit from the `<name>` to the latest tag. | `$ git-chglog 1.0.0..` |
| `..<name>` | Commit from the oldest tag to `<name>`. | `$ git-chglog ..2.0.0` |
| `<name>` | Commit contained in `<name>`. | `$ git-chglog 1.0.0` |
## Release version logs
+ [OpenIM CHANGELOG-V1.0](CHANGELOG-1.0.md)
+ [OpenIM CHANGELOG-V2.0](CHANGELOG-2.0.md)
+ [OpenIM CHANGELOG-V2.1](CHANGELOG-2.1.md)
+ [OpenIM CHANGELOG-V2.2](CHANGELOG-2.2.md)
+ [OpenIM CHANGELOG-V2.3](CHANGELOG-2.3.md)
+ [OpenIM CHANGELOG-V2.9](CHANGELOG-2.9.md)
+ [OpenIM CHANGELOG-V3.0](CHANGELOG-3.0.md)
+ [OpenIM CHANGELOG-V3.1](CHANGELOG-3.1.md)
+ [OpenIM CHANGELOG-V3.2](CHANGELOG-3.2.md)
+ [OpenIM CHANGELOG-V3.3](CHANGELOG-3.3.md)
## Introduction
In both the open-source and closed-source software development communities, it is important to follow a consistent and understandable versioning scheme for software projects. This ensures clear communication of changes, compatibility, and stability across different releases. One widely adopted naming convention is the Semantic Versioning 2.0.0.
## Naming Format
The most common format for version numbers is as follows:
```bash
major.minor[.patch[.build]]
```
Let's take a closer look at each component:
1. **Major Version**: This is the first number in the versioning scheme and indicates significant changes that may not be backward compatible (specific to each project).
2. **Minor Version**: The second number signifies the addition of new features while maintaining backward compatibility.
3. **Patch Version**: The third number represents bug fixes or code optimizations without introducing new features. It is generally backward compatible.
4. **Build Version**: Typically an automatically generated number that increments with each code commit.
## Examples
Here are a few examples to illustrate the versioning scheme:
1. `1.0`
2. `2.14.0.1478`
3. `3.2.1 build-354`
## Version Modifiers
Apart from the version numbers, there are also version modifiers used to indicate specific stages or statuses of a release. Some commonly used version modifiers include:
- **alpha**: An internal testing version with numerous known bugs. It is primarily used for communication among developers.
- **beta**: A testing version released to enthusiastic users for feedback and bug detection.
- **rc (release candidate)**: The final testing version before the official release.
- **ga (general availability)**: The initial stable release for public distribution.
- **r/release** (or no modifier at all): The final released version intended for general users.
- **lts (long-term support)**: Designates a version that will receive extended maintenance and bug fixes for a specified number of years.
## Versioning Strategy
To effectively manage version numbers, the following strategies are commonly employed:
- The initial version of a project can be either `0.1` or `1.0`.
- When fixing bugs, the patch version is incremented by 1.
- When adding new features, the minor version is incremented by 1, and the patch version is reset to 0.
- In the case of significant modifications, the major version is incremented by 1.
- The build version is usually automatically generated by the compilation process and follows a defined format. It does not require manual control.
By adhering to these strategies and guidelines, developers can maintain consistency and clarity in versioning their software projects. This enables users and collaborators to understand the nature of changes between different releases and ensure compatibility with their systems.
(Note: Markdown formatting has been used to structure this article. Markdown is a lightweight markup language used to format text on platforms like GitHub.)
------
**Note**: The above article is based on the given content and aims to provide a Markdown-formatted English article explaining the naming conventions for software project versions, specifically focusing on the Semantic Versioning 2.0.0.
+1 -1
View File
@@ -129,7 +129,7 @@ REDIS_PORT=${REDIS_PORT}
# Default: REDIS_PASSWORD=openIM123 # Default: REDIS_PASSWORD=openIM123
REDIS_PASSWORD=${REDIS_PASSWORD} REDIS_PASSWORD=${REDIS_PASSWORD}
# Kakfa username to authenticate with the Kafka service. # Kafka username to authenticate with the Kafka service.
# KAFKA_USERNAME=${KAFKA_USERNAME} # KAFKA_USERNAME=${KAFKA_USERNAME}
# Port on which Kafka distributed streaming platform is running. # Port on which Kafka distributed streaming platform is running.
+2 -1
View File
@@ -12,7 +12,7 @@ require (
github.com/gorilla/websocket v1.5.1 github.com/gorilla/websocket v1.5.1
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/openimsdk/protocol v0.0.69-alpha.41 github.com/openimsdk/protocol v0.0.69
github.com/openimsdk/tools v0.0.49-alpha.55 github.com/openimsdk/tools v0.0.49-alpha.55
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.18.0 github.com/prometheus/client_golang v1.18.0
@@ -74,6 +74,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic v1.9.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chai2010/webp v1.1.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/clbanning/mxj v1.8.4 // indirect github.com/clbanning/mxj v1.8.4 // indirect
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
+4 -2
View File
@@ -71,6 +71,8 @@ github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZX
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
@@ -319,8 +321,8 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y=
github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI=
github.com/openimsdk/protocol v0.0.69-alpha.41 h1:9hoQ6UHMBq+g58KXir90EpnnvwJ1bvDPixPSaODo4nY= github.com/openimsdk/protocol v0.0.69 h1:dVi8meSg8kmUzSH1XQab4MjihqKkkcCAmt1BYXPJuXo=
github.com/openimsdk/protocol v0.0.69-alpha.41/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= github.com/openimsdk/protocol v0.0.69/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8=
github.com/openimsdk/tools v0.0.49-alpha.55 h1:KPgC53oqiwZYssLKljhtXbWXifMlTj2SSQEusj4Uf4k= github.com/openimsdk/tools v0.0.49-alpha.55 h1:KPgC53oqiwZYssLKljhtXbWXifMlTj2SSQEusj4Uf4k=
github.com/openimsdk/tools v0.0.49-alpha.55/go.mod h1:h1cYmfyaVtgFbKmb1Cfsl8XwUOMTt8ubVUQrdGtsUh4= github.com/openimsdk/tools v0.0.49-alpha.55/go.mod h1:h1cYmfyaVtgFbKmb1Cfsl8XwUOMTt8ubVUQrdGtsUh4=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
+9 -3
View File
@@ -107,7 +107,6 @@ func (c *Client) pingHandler(appData string) error {
} }
log.ZDebug(c.ctx, "ping Handler Success.", "appData", appData) log.ZDebug(c.ctx, "ping Handler Success.", "appData", appData)
return c.writePongMsg(appData) return c.writePongMsg(appData)
} }
@@ -392,7 +391,9 @@ func (c *Client) writePingMsg() error {
} }
func (c *Client) writePongMsg(appData string) error { func (c *Client) writePongMsg(appData string) error {
log.ZDebug(c.ctx, "write Pong Msg in Server", "appData", appData)
if c.closed.Load() { if c.closed.Load() {
log.ZWarn(c.ctx, "is closed in server", nil, "appdata", appData, "closed err", c.closedErr)
return nil return nil
} }
@@ -401,8 +402,13 @@ func (c *Client) writePongMsg(appData string) error {
err := c.conn.SetWriteDeadline(writeWait) err := c.conn.SetWriteDeadline(writeWait)
if err != nil { if err != nil {
return err log.ZWarn(c.ctx, "SetWriteDeadline in Server have error", errs.Wrap(err), "writeWait", writeWait, "appData", appData)
return errs.Wrap(err)
}
err = c.conn.WriteMessage(PongMessage, []byte(appData))
if err != nil {
log.ZWarn(c.ctx, "Write Message have error", errs.Wrap(err), "Pong msg", PongMessage)
} }
return c.conn.WriteMessage(PongMessage, []byte(appData)) return errs.Wrap(err)
} }
+7 -2
View File
@@ -4,13 +4,16 @@ import (
"context" "context"
"crypto/md5" "crypto/md5"
"encoding/binary" "encoding/binary"
"fmt"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
pbuser "github.com/openimsdk/protocol/user" pbuser "github.com/openimsdk/protocol/user"
"github.com/openimsdk/tools/log" "github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/mcontext" "github.com/openimsdk/tools/mcontext"
"github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/datautil"
"math/rand" "math/rand"
"os"
"strconv" "strconv"
"sync/atomic"
"time" "time"
) )
@@ -78,8 +81,10 @@ func (ws *WsServer) ChangeOnlineStatus(concurrent int) {
} }
} }
opIdCtx := mcontext.SetOperationID(context.Background(), "r"+strconv.FormatUint(rNum, 10)) var count atomic.Int64
operationIDPrefix := fmt.Sprintf("p_%d_", os.Getpid())
doRequest := func(req *pbuser.SetUserOnlineStatusReq) { doRequest := func(req *pbuser.SetUserOnlineStatusReq) {
opIdCtx := mcontext.SetOperationID(context.Background(), operationIDPrefix+strconv.FormatInt(count.Add(1), 10))
ctx, cancel := context.WithTimeout(opIdCtx, time.Second*5) ctx, cancel := context.WithTimeout(opIdCtx, time.Second*5)
defer cancel() defer cancel()
if _, err := ws.userClient.Client.SetUserOnlineStatus(ctx, req); err != nil { if _, err := ws.userClient.Client.SetUserOnlineStatus(ctx, req); err != nil {
@@ -102,7 +107,7 @@ func (ws *WsServer) ChangeOnlineStatus(concurrent int) {
case now := <-renewalTicker.C: case now := <-renewalTicker.C:
deadline := now.Add(-cachekey.OnlineExpire / 3) deadline := now.Add(-cachekey.OnlineExpire / 3)
users := ws.clients.GetAllUserStatus(deadline, now) users := ws.clients.GetAllUserStatus(deadline, now)
log.ZDebug(context.Background(), "renewal ticker", "deadline", deadline, "nowtime", now, "num", len(users)) log.ZDebug(context.Background(), "renewal ticker", "deadline", deadline, "nowtime", now, "num", len(users), "users", users)
pushUserState(users...) pushUserState(users...)
case state := <-ws.clients.UserState(): case state := <-ws.clients.UserState():
log.ZDebug(context.Background(), "OnlineCache user online change", "userID", state.UserID, "online", state.Online, "offline", state.Offline) log.ZDebug(context.Background(), "OnlineCache user online change", "userID", state.UserID, "online", state.Online, "offline", state.Offline)
+3 -3
View File
@@ -162,12 +162,12 @@ func (u *userMap) DeleteClients(userID string, clients []*Client) (isDeleteUser
return true return true
} }
func (u *userMap) GetAllUserStatus(deadline time.Time, nowtime time.Time) []UserState { func (u *userMap) GetAllUserStatus(deadline time.Time, nowtime time.Time) (result []UserState) {
u.lock.RLock() u.lock.RLock()
defer u.lock.RUnlock() defer u.lock.RUnlock()
result := make([]UserState, 0, len(u.data)) result = make([]UserState, 0, len(u.data))
for userID, userPlatform := range u.data { for userID, userPlatform := range u.data {
if userPlatform.Time.Before(deadline) { if deadline.Before(userPlatform.Time) {
continue continue
} }
userPlatform.Time = nowtime userPlatform.Time = nowtime
+2 -1
View File
@@ -198,10 +198,11 @@ func (c *ConsumerHandler) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws.
offlineUserIDs = append(offlineUserIDs, userID) offlineUserIDs = append(offlineUserIDs, userID)
} }
} }
log.ZDebug(ctx, "GetConnsAndOnlinePush online cache", "sendID", msg.SendID, "recvID", msg.RecvID, "groupID", msg.GroupID, "sessionType", msg.SessionType, "clientMsgID", msg.ClientMsgID, "serverMsgID", msg.ServerMsgID, "offlineUserIDs", offlineUserIDs, "onlineUserIDs", onlineUserIDs)
var result []*msggateway.SingleMsgToUserResults var result []*msggateway.SingleMsgToUserResults
if len(onlineUserIDs) > 0 { if len(onlineUserIDs) > 0 {
var err error var err error
result, err = c.onlinePusher.GetConnsAndOnlinePush(ctx, msg, pushToUserIDs) result, err = c.onlinePusher.GetConnsAndOnlinePush(ctx, msg, onlineUserIDs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+73 -16
View File
@@ -16,13 +16,16 @@ package conversation
import ( import (
"context" "context"
"sort"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" "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/localcache"
"github.com/openimsdk/tools/db/redisutil" "github.com/openimsdk/tools/db/redisutil"
"sort"
"github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs" "github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
@@ -40,10 +43,11 @@ import (
) )
type conversationServer struct { type conversationServer struct {
msgRpcClient *rpcclient.MessageRpcClient msgRpcClient *rpcclient.MessageRpcClient
user *rpcclient.UserRpcClient user *rpcclient.UserRpcClient
groupRpcClient *rpcclient.GroupRpcClient groupRpcClient *rpcclient.GroupRpcClient
conversationDatabase controller.ConversationDatabase conversationDatabase controller.ConversationDatabase
conversationNotificationSender *ConversationNotificationSender conversationNotificationSender *ConversationNotificationSender
config *Config config *Config
} }
@@ -204,11 +208,11 @@ func (c *conversationServer) getConversations(ctx context.Context, ownerUserID s
} }
func (c *conversationServer) SetConversation(ctx context.Context, req *pbconversation.SetConversationReq) (*pbconversation.SetConversationResp, error) { func (c *conversationServer) SetConversation(ctx context.Context, req *pbconversation.SetConversationReq) (*pbconversation.SetConversationResp, error) {
var conversation tablerelation.Conversation var conversation dbModel.Conversation
if err := datautil.CopyStructFields(&conversation, req.Conversation); err != nil { if err := datautil.CopyStructFields(&conversation, req.Conversation); err != nil {
return nil, err return nil, err
} }
err := c.conversationDatabase.SetUserConversations(ctx, req.Conversation.OwnerUserID, []*tablerelation.Conversation{&conversation}) err := c.conversationDatabase.SetUserConversations(ctx, req.Conversation.OwnerUserID, []*dbModel.Conversation{&conversation})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -232,7 +236,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
} }
} }
var unequal int var unequal int
var conv tablerelation.Conversation var conv dbModel.Conversation
if len(req.UserIDs) == 1 { if len(req.UserIDs) == 1 {
cs, err := c.conversationDatabase.FindConversations(ctx, req.UserIDs[0], []string{req.Conversation.ConversationID}) cs, err := c.conversationDatabase.FindConversations(ctx, req.UserIDs[0], []string{req.Conversation.ConversationID})
if err != nil { if err != nil {
@@ -243,7 +247,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
} }
conv = *cs[0] conv = *cs[0]
} }
var conversation tablerelation.Conversation var conversation dbModel.Conversation
conversation.ConversationID = req.Conversation.ConversationID conversation.ConversationID = req.Conversation.ConversationID
conversation.ConversationType = req.Conversation.ConversationType conversation.ConversationType = req.Conversation.ConversationType
conversation.UserID = req.Conversation.UserID conversation.UserID = req.Conversation.UserID
@@ -292,7 +296,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
} }
} }
if req.Conversation.IsPrivateChat != nil && req.Conversation.ConversationType != constant.ReadGroupChatType { if req.Conversation.IsPrivateChat != nil && req.Conversation.ConversationType != constant.ReadGroupChatType {
var conversations []*tablerelation.Conversation var conversations []*dbModel.Conversation
for _, ownerUserID := range req.UserIDs { for _, ownerUserID := range req.UserIDs {
conversation2 := conversation conversation2 := conversation
conversation2.OwnerUserID = ownerUserID conversation2.OwnerUserID = ownerUserID
@@ -340,12 +344,12 @@ func (c *conversationServer) CreateSingleChatConversations(ctx context.Context,
) (*pbconversation.CreateSingleChatConversationsResp, error) { ) (*pbconversation.CreateSingleChatConversationsResp, error) {
switch req.ConversationType { switch req.ConversationType {
case constant.SingleChatType: case constant.SingleChatType:
var conversation tablerelation.Conversation var conversation dbModel.Conversation
conversation.ConversationID = req.ConversationID conversation.ConversationID = req.ConversationID
conversation.ConversationType = req.ConversationType conversation.ConversationType = req.ConversationType
conversation.OwnerUserID = req.SendID conversation.OwnerUserID = req.SendID
conversation.UserID = req.RecvID conversation.UserID = req.RecvID
err := c.conversationDatabase.CreateConversation(ctx, []*tablerelation.Conversation{&conversation}) err := c.conversationDatabase.CreateConversation(ctx, []*dbModel.Conversation{&conversation})
if err != nil { if err != nil {
log.ZWarn(ctx, "create conversation failed", err, "conversation", conversation) log.ZWarn(ctx, "create conversation failed", err, "conversation", conversation)
} }
@@ -353,17 +357,17 @@ func (c *conversationServer) CreateSingleChatConversations(ctx context.Context,
conversation2 := conversation conversation2 := conversation
conversation2.OwnerUserID = req.RecvID conversation2.OwnerUserID = req.RecvID
conversation2.UserID = req.SendID conversation2.UserID = req.SendID
err = c.conversationDatabase.CreateConversation(ctx, []*tablerelation.Conversation{&conversation2}) err = c.conversationDatabase.CreateConversation(ctx, []*dbModel.Conversation{&conversation2})
if err != nil { if err != nil {
log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation) log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation)
} }
case constant.NotificationChatType: case constant.NotificationChatType:
var conversation tablerelation.Conversation var conversation dbModel.Conversation
conversation.ConversationID = req.ConversationID conversation.ConversationID = req.ConversationID
conversation.ConversationType = req.ConversationType conversation.ConversationType = req.ConversationType
conversation.OwnerUserID = req.RecvID conversation.OwnerUserID = req.RecvID
conversation.UserID = req.SendID conversation.UserID = req.SendID
err := c.conversationDatabase.CreateConversation(ctx, []*tablerelation.Conversation{&conversation}) err := c.conversationDatabase.CreateConversation(ctx, []*dbModel.Conversation{&conversation})
if err != nil { if err != nil {
log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation) log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation)
} }
@@ -584,6 +588,9 @@ func (c *conversationServer) UpdateConversation(ctx context.Context, req *pbconv
if req.MaxSeq != nil { if req.MaxSeq != nil {
m["max_seq"] = req.MaxSeq.Value m["max_seq"] = req.MaxSeq.Value
} }
if req.LatestMsgDestructTime != nil {
m["latest_msg_destruct_time"] = time.UnixMilli(req.LatestMsgDestructTime.Value)
}
if len(m) > 0 { if len(m) > 0 {
if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.UserIDs, req.ConversationID, m); err != nil { if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.UserIDs, req.ConversationID, m); err != nil {
return nil, err return nil, err
@@ -602,3 +609,53 @@ func (c *conversationServer) GetOwnerConversation(ctx context.Context, req *pbco
Conversations: convert.ConversationsDB2Pb(conversations), Conversations: convert.ConversationsDB2Pb(conversations),
}, nil }, nil
} }
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)
return nil, err
}
const batchNum = 100
if num == 0 {
return nil, errs.New("Need Destruct Msg is nil").Wrap()
}
maxPage := (num + batchNum - 1) / batchNum
temp := make([]*model.Conversation, 0, maxPage*batchNum)
for pageNumber := 0; pageNumber < int(maxPage); pageNumber++ {
pagination := &sdkws.RequestPagination{
PageNumber: int32(pageNumber),
ShowNumber: batchNum,
}
conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
if err != nil {
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
continue
}
log.ZDebug(ctx, "PageConversationIDs success", "pageNumber", pageNumber, "conversationIDsNum", len(conversationIDs), "conversationIDs", conversationIDs)
if len(conversationIDs) == 0 {
continue
}
conversations, err := c.conversationDatabase.GetConversationsByConversationID(ctx, conversationIDs)
if err != nil {
log.ZError(ctx, "GetConversationsByConversationID failed", err, "conversationIDs", conversationIDs)
continue
}
for _, conversation := range conversations {
if conversation.IsMsgDestruct && conversation.MsgDestructTime != 0 && ((time.Now().UnixMilli() > (conversation.MsgDestructTime + conversation.LatestMsgDestructTime.UnixMilli() + 8*60*60)) || // 8*60*60 is UTC+8
conversation.LatestMsgDestructTime.IsZero()) {
temp = append(temp, conversation)
}
}
}
return &pbconversation.GetConversationsNeedDestructMsgsResp{Conversations: convert.ConversationsDB2Pb(temp)}, nil
}
+40 -18
View File
@@ -16,6 +16,8 @@ package group
import ( import (
"context" "context"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/apistruct" "github.com/openimsdk/open-im-server/v3/pkg/apistruct"
"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
@@ -27,7 +29,6 @@ import (
"github.com/openimsdk/tools/log" "github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/mcontext" "github.com/openimsdk/tools/mcontext"
"github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/datautil"
"time"
) )
// CallbackBeforeCreateGroup callback before create group. // CallbackBeforeCreateGroup callback before create group.
@@ -100,27 +101,45 @@ func (s *groupServer) webhookAfterCreateGroup(ctx context.Context, after *config
s.webhookClient.AsyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, &callbackstruct.CallbackAfterCreateGroupResp{}, after) s.webhookClient.AsyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, &callbackstruct.CallbackAfterCreateGroupResp{}, after)
} }
func (s *groupServer) webhookBeforeMemberJoinGroup(ctx context.Context, before *config.BeforeConfig, groupMember *model.GroupMember, groupEx string) error { func (s *groupServer) webhookBeforeMembersJoinGroup(ctx context.Context, before *config.BeforeConfig, groupMembers []*model.GroupMember, groupID string, groupEx string) error {
return webhook.WithCondition(ctx, before, func(ctx context.Context) error { return webhook.WithCondition(ctx, before, func(ctx context.Context) error {
cbReq := &callbackstruct.CallbackBeforeMemberJoinGroupReq{ groupMembersMap := datautil.SliceToMap(groupMembers, func(e *model.GroupMember) string {
CallbackCommand: callbackstruct.CallbackBeforeMemberJoinGroupCommand, return e.UserID
GroupID: groupMember.GroupID, })
UserID: groupMember.UserID, var groupMembersCallback []*callbackstruct.CallbackGroupMember
Ex: groupMember.Ex,
for _, member := range groupMembers {
groupMembersCallback = append(groupMembersCallback, &callbackstruct.CallbackGroupMember{
UserID: member.UserID,
Ex: member.Ex,
})
}
cbReq := &callbackstruct.CallbackBeforeMembersJoinGroupReq{
CallbackCommand: callbackstruct.CallbackBeforeMembersJoinGroupCommand,
GroupID: groupID,
MembersList: groupMembersCallback,
GroupEx: groupEx, GroupEx: groupEx,
} }
resp := &callbackstruct.CallbackBeforeMemberJoinGroupResp{} resp := &callbackstruct.CallbackBeforeMembersJoinGroupResp{}
if err := s.webhookClient.SyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, resp, before); err != nil { if err := s.webhookClient.SyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, resp, before); err != nil {
return err return err
} }
if resp.MuteEndTime != nil { for _, memberCallbackResp := range resp.MemberCallbackList {
groupMember.MuteEndTime = time.UnixMilli(*resp.MuteEndTime) if _, ok := groupMembersMap[(*memberCallbackResp.UserID)]; ok {
if memberCallbackResp.MuteEndTime != nil {
groupMembersMap[(*memberCallbackResp.UserID)].MuteEndTime = time.UnixMilli(*memberCallbackResp.MuteEndTime)
}
datautil.NotNilReplace(&groupMembersMap[(*memberCallbackResp.UserID)].FaceURL, memberCallbackResp.FaceURL)
datautil.NotNilReplace(&groupMembersMap[(*memberCallbackResp.UserID)].Ex, memberCallbackResp.Ex)
datautil.NotNilReplace(&groupMembersMap[(*memberCallbackResp.UserID)].Nickname, memberCallbackResp.Nickname)
datautil.NotNilReplace(&groupMembersMap[(*memberCallbackResp.UserID)].RoleLevel, memberCallbackResp.RoleLevel)
}
} }
datautil.NotNilReplace(&groupMember.FaceURL, resp.FaceURL)
datautil.NotNilReplace(&groupMember.Ex, resp.Ex)
datautil.NotNilReplace(&groupMember.Nickname, resp.Nickname)
datautil.NotNilReplace(&groupMember.RoleLevel, resp.RoleLevel)
return nil return nil
}) })
} }
@@ -244,10 +263,13 @@ func (s *groupServer) webhookBeforeInviteUserToGroup(ctx context.Context, before
return err return err
} }
if len(resp.RefusedMembersAccount) > 0 { // Handle the scenario where certain members are refused
// Handle the scenario where certain members are refused // You might want to update the req.Members list or handle it as per your business logic
// You might want to update the req.Members list or handle it as per your business logic
} // if len(resp.RefusedMembersAccount) > 0 {
// implement members are refused
// }
return nil return nil
}) })
} }
+23 -23
View File
@@ -246,7 +246,7 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
return nil, err return nil, err
} }
joinGroup := func(userID string, roleLevel int32) error { joinGroupFunc := func(userID string, roleLevel int32) {
groupMember := &model.GroupMember{ groupMember := &model.GroupMember{
GroupID: group.GroupID, GroupID: group.GroupID,
UserID: userID, UserID: userID,
@@ -258,25 +258,23 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
MuteEndTime: time.UnixMilli(0), MuteEndTime: time.UnixMilli(0),
} }
if err := s.webhookBeforeMemberJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, groupMember, group.Ex); err != nil && err != servererrs.ErrCallbackContinue {
return err
}
groupMembers = append(groupMembers, groupMember) groupMembers = append(groupMembers, groupMember)
return nil
} }
if err := joinGroup(req.OwnerUserID, constant.GroupOwner); err != nil {
joinGroupFunc(req.OwnerUserID, constant.GroupOwner)
for _, userID := range req.AdminUserIDs {
joinGroupFunc(userID, constant.GroupAdmin)
}
for _, userID := range req.MemberUserIDs {
joinGroupFunc(userID, constant.GroupOrdinaryUsers)
}
if err := s.webhookBeforeMembersJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, groupMembers, group.GroupID, group.Ex); err != nil && err != servererrs.ErrCallbackContinue {
return nil, err return nil, err
} }
for _, userID := range req.AdminUserIDs {
if err := joinGroup(userID, constant.GroupAdmin); err != nil {
return nil, err
}
}
for _, userID := range req.MemberUserIDs {
if err := joinGroup(userID, constant.GroupOrdinaryUsers); err != nil {
return nil, err
}
}
if err := s.db.CreateGroup(ctx, []*model.Group{group}, groupMembers); err != nil { if err := s.db.CreateGroup(ctx, []*model.Group{group}, groupMembers); err != nil {
return nil, err return nil, err
} }
@@ -442,12 +440,13 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
MuteEndTime: time.UnixMilli(0), MuteEndTime: time.UnixMilli(0),
} }
if err := s.webhookBeforeMemberJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, groupMember, group.Ex); err != nil && err != servererrs.ErrCallbackContinue {
return nil, err
}
groupMembers = append(groupMembers, member) groupMembers = append(groupMembers, member)
} }
if err := s.webhookBeforeMembersJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, groupMembers, group.GroupID, group.Ex); err != nil && err != servererrs.ErrCallbackContinue {
return nil, err
}
if err := s.db.CreateGroup(ctx, nil, groupMembers); err != nil { if err := s.db.CreateGroup(ctx, nil, groupMembers); err != nil {
return nil, err return nil, err
} }
@@ -811,9 +810,9 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
MuteEndTime: time.Unix(0, 0), MuteEndTime: time.Unix(0, 0),
InviterUserID: groupRequest.InviterUserID, InviterUserID: groupRequest.InviterUserID,
OperatorUserID: mcontext.GetOpUserID(ctx), OperatorUserID: mcontext.GetOpUserID(ctx),
Ex: groupRequest.Ex,
} }
if err := s.webhookBeforeMemberJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, member, group.Ex); err != nil && err != servererrs.ErrCallbackContinue {
if err := s.webhookBeforeMembersJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, []*model.GroupMember{member}, group.GroupID, group.Ex); err != nil && err != servererrs.ErrCallbackContinue {
return nil, err return nil, err
} }
} }
@@ -882,7 +881,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
MuteEndTime: time.UnixMilli(0), MuteEndTime: time.UnixMilli(0),
} }
if err := s.webhookBeforeMemberJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, groupMember, group.Ex); err != nil && err != servererrs.ErrCallbackContinue { if err := s.webhookBeforeMembersJoinGroup(ctx, &s.config.WebhooksConfig.BeforeMemberJoinGroup, []*model.GroupMember{groupMember}, group.GroupID, group.Ex); err != nil && err != servererrs.ErrCallbackContinue {
return nil, err return nil, err
} }
@@ -898,6 +897,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
return &pbgroup.JoinGroupResp{}, nil return &pbgroup.JoinGroupResp{}, nil
} }
groupRequest := model.GroupRequest{ groupRequest := model.GroupRequest{
UserID: req.InviterUserID, UserID: req.InviterUserID,
ReqMsg: req.ReqMessage, ReqMsg: req.ReqMessage,
+3 -42
View File
@@ -17,6 +17,7 @@ package group
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
@@ -126,25 +127,8 @@ func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID stri
if len(ownerUserIDs) > 0 { if len(ownerUserIDs) > 0 {
ownerUserID = ownerUserIDs[0] ownerUserID = ownerUserIDs[0]
} }
return &sdkws.GroupInfo{
GroupID: gm.GroupID, return convert.Db2PbGroupInfo(gm, ownerUserID, num), nil
GroupName: gm.GroupName,
Notification: gm.Notification,
Introduction: gm.Introduction,
FaceURL: gm.FaceURL,
OwnerUserID: ownerUserID,
CreateTime: gm.CreateTime.UnixMilli(),
MemberCount: num,
Ex: gm.Ex,
Status: gm.Status,
CreatorUserID: gm.CreatorUserID,
GroupType: gm.GroupType,
NeedVerification: gm.NeedVerification,
LookMemberInfo: gm.LookMemberInfo,
ApplyMemberFriend: gm.ApplyMemberFriend,
NotificationUpdateTime: gm.NotificationUpdateTime.UnixMilli(),
NotificationUserID: gm.NotificationUserID,
}, nil
} }
func (g *GroupNotificationSender) 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) {
@@ -198,29 +182,6 @@ func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Contex
return datautil.Slice(members, fn), nil return datautil.Slice(members, fn), nil
} }
//nolint:unused
func (g *GroupNotificationSender) groupDB2PB(group *model.Group, ownerUserID string, memberCount uint32) *sdkws.GroupInfo {
return &sdkws.GroupInfo{
GroupID: group.GroupID,
GroupName: group.GroupName,
Notification: group.Notification,
Introduction: group.Introduction,
FaceURL: group.FaceURL,
OwnerUserID: ownerUserID,
CreateTime: group.CreateTime.UnixMilli(),
MemberCount: memberCount,
Ex: group.Ex,
Status: group.Status,
CreatorUserID: group.CreatorUserID,
GroupType: group.GroupType,
NeedVerification: group.NeedVerification,
LookMemberInfo: group.LookMemberInfo,
ApplyMemberFriend: group.ApplyMemberFriend,
NotificationUpdateTime: group.NotificationUpdateTime.UnixMilli(),
NotificationUserID: group.NotificationUserID,
}
}
func (g *GroupNotificationSender) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo { func (g *GroupNotificationSender) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
return &sdkws.GroupMemberFullInfo{ return &sdkws.GroupMemberFullInfo{
GroupID: member.GroupID, GroupID: member.GroupID,
+66 -19
View File
@@ -2,16 +2,22 @@ package msg
import ( import (
"context" "context"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/protocol/conversation" "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/msg"
"github.com/openimsdk/protocol/wrapperspb" "github.com/openimsdk/protocol/wrapperspb"
"github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log" "github.com/openimsdk/tools/log"
"strings" "github.com/openimsdk/tools/mcontext"
"time" "github.com/openimsdk/tools/utils/idutil"
"github.com/openimsdk/tools/utils/stringutil"
"golang.org/x/sync/errgroup"
) )
// hard delete in Database.
func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.ClearMsgResp, err error) { 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 { if err := authverify.CheckAdmin(ctx, m.config.Share.IMAdminUserID); err != nil {
return nil, err return nil, err
@@ -25,18 +31,6 @@ func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.
start = time.Now() start = time.Now()
) )
clearMsg := func(ctx context.Context) (bool, error) { clearMsg := func(ctx context.Context) (bool, error) {
conversationSeqs := make(map[string]struct{})
defer func() {
req := &conversation.UpdateConversationReq{
MsgDestructTime: wrapperspb.Int64(time.Now().UnixMilli()),
}
for conversationID := range conversationSeqs {
req.ConversationID = conversationID
if err := m.Conversation.UpdateConversations(ctx, req); err != nil {
log.ZError(ctx, "update conversation max seq failed", err, "conversationID", conversationID, "msgDestructTime", req.MsgDestructTime)
}
}
}()
msgs, err := m.MsgDatabase.GetBeforeMsg(ctx, req.Timestamp, 100) msgs, err := m.MsgDatabase.GetBeforeMsg(ctx, req.Timestamp, 100)
if err != nil { if err != nil {
return false, err return false, err
@@ -44,6 +38,7 @@ func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.
if len(msgs) == 0 { if len(msgs) == 0 {
return false, nil return false, nil
} }
for _, msg := range msgs { for _, msg := range msgs {
index, err := m.MsgDatabase.DeleteDocMsgBefore(ctx, req.Timestamp, msg) index, err := m.MsgDatabase.DeleteDocMsgBefore(ctx, req.Timestamp, msg)
if err != nil { if err != nil {
@@ -52,15 +47,14 @@ func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.
if len(index) == 0 { if len(index) == 0 {
return false, errs.ErrInternalServer.WrapMsg("delete doc msg failed") return false, errs.ErrInternalServer.WrapMsg("delete doc msg failed")
} }
docNum++ docNum++
msgNum += len(index) msgNum += len(index)
conversationID := msg.DocID[:strings.LastIndex(msg.DocID, ":")]
if _, ok := conversationSeqs[conversationID]; !ok {
conversationSeqs[conversationID] = struct{}{}
}
} }
return true, nil return true, nil
} }
for { for {
keep, err := clearMsg(ctx) keep, err := clearMsg(ctx)
if err != nil { if err != nil {
@@ -71,7 +65,60 @@ func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.
log.ZInfo(ctx, "clear msg success", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start)) log.ZInfo(ctx, "clear msg success", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start))
break break
} }
log.ZInfo(ctx, "clearing message", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start)) log.ZInfo(ctx, "clearing message", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start))
} }
return &msg.ClearMsgResp{}, nil return &msg.ClearMsgResp{}, 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 nil, nil
}
+5
View File
@@ -16,6 +16,7 @@ package msg
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
@@ -50,6 +51,7 @@ type (
ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data. ConversationLocalCache *rpccache.ConversationLocalCache // Local cache for conversation data.
Handlers MessageInterceptorChain // Chain of handlers for processing messages. Handlers MessageInterceptorChain // Chain of handlers for processing messages.
notificationSender *rpcclient.NotificationSender // RPC client for sending notifications. notificationSender *rpcclient.NotificationSender // RPC client for sending notifications.
msgNotificationSender *MsgNotificationSender // RPC client for sending msg notifications.
config *Config // Global configuration settings. config *Config // Global configuration settings.
webhookClient *webhook.Client webhookClient *webhook.Client
} }
@@ -117,7 +119,10 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
} }
s.notificationSender = rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithLocalSendMsg(s.SendMsg)) s.notificationSender = rpcclient.NewNotificationSender(&config.NotificationConfig, rpcclient.WithLocalSendMsg(s.SendMsg))
s.msgNotificationSender = NewMsgNotificationSender(config, rpcclient.WithLocalSendMsg(s.SendMsg))
msg.RegisterMsgServer(server, s) msg.RegisterMsgServer(server, s)
return nil return nil
} }
+2 -2
View File
@@ -111,7 +111,7 @@ func (m *msgServer) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqReq) (*sd
func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq) (resp *msg.SearchMessageResp, err error) { func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq) (resp *msg.SearchMessageResp, err error) {
var chatLogs []*sdkws.MsgData var chatLogs []*sdkws.MsgData
var total int32 var total int64
resp = &msg.SearchMessageResp{} resp = &msg.SearchMessageResp{}
if total, chatLogs, err = m.MsgDatabase.SearchMessage(ctx, req); err != nil { if total, chatLogs, err = m.MsgDatabase.SearchMessage(ctx, req); err != nil {
return nil, err return nil, err
@@ -194,7 +194,7 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
} }
resp.ChatLogs = append(resp.ChatLogs, pbchatLog) resp.ChatLogs = append(resp.ChatLogs, pbchatLog)
} }
resp.ChatLogsNum = total resp.ChatLogsNum = int32(total)
return resp, nil return resp, nil
} }
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package friend package relation
import ( import (
"context" "context"
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package friend package relation
import ( import (
"context" "context"
@@ -12,11 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package friend package relation
import ( import (
"context" "context"
"github.com/openimsdk/tools/mq/memamq"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
@@ -49,6 +51,7 @@ type friendServer struct {
RegisterCenter discovery.SvcDiscoveryRegistry RegisterCenter discovery.SvcDiscoveryRegistry
config *Config config *Config
webhookClient *webhook.Client webhookClient *webhook.Client
queue *memamq.MemoryQueue
} }
type Config struct { type Config struct {
@@ -118,8 +121,8 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
conversationRpcClient: rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation), conversationRpcClient: rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation),
config: config, config: config,
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL), webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
queue: memamq.NewMemoryQueue(128, 1024*8),
}) })
return nil return nil
} }
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package friend package relation
import ( import (
"context" "context"
@@ -1,9 +1,10 @@
package friend package relation
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/util/hashutil" "github.com/openimsdk/open-im-server/v3/pkg/util/hashutil"
"github.com/openimsdk/protocol/sdkws" "github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/log"
"slices" "slices"
"github.com/openimsdk/open-im-server/v3/internal/rpc/incrversion" "github.com/openimsdk/open-im-server/v3/internal/rpc/incrversion"
@@ -17,14 +18,23 @@ func (s *friendServer) NotificationUserInfoUpdate(ctx context.Context, req *rela
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, userID := range userIDs { if len(userIDs) > 0 {
if err := s.db.OwnerIncrVersion(ctx, userID, []string{req.UserID}, model.VersionStateUpdate); err != nil { friendUserIDs := []string{req.UserID}
return nil, err noCancelCtx := context.WithoutCancel(ctx)
err := s.queue.PushCtx(ctx, func() {
for _, userID := range userIDs {
if err := s.db.OwnerIncrVersion(noCancelCtx, userID, friendUserIDs, model.VersionStateUpdate); err != nil {
log.ZError(ctx, "OwnerIncrVersion", err, "userID", userID, "friendUserIDs", friendUserIDs)
}
}
for _, userID := range userIDs {
s.notificationSender.FriendInfoUpdatedNotification(noCancelCtx, req.UserID, userID)
}
})
if err != nil {
log.ZError(ctx, "NotificationUserInfoUpdate timeout", err, "userID", req.UserID)
} }
} }
for _, userID := range userIDs {
s.notificationSender.FriendInfoUpdatedNotification(ctx, req.UserID, userID)
}
return &relation.NotificationUserInfoUpdateResp{}, nil return &relation.NotificationUserInfoUpdateResp{}, nil
} }
+1 -2
View File
@@ -26,7 +26,6 @@ import (
"github.com/openimsdk/protocol/third" "github.com/openimsdk/protocol/third"
"github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/datautil"
"github.com/openimsdk/tools/utils/stringutil"
) )
func genLogID() string { func genLogID() string {
@@ -111,7 +110,7 @@ func dbToPbLogInfos(logs []*relationtb.Log) []*third.LogInfo {
return &third.LogInfo{ return &third.LogInfo{
Filename: log.FileName, Filename: log.FileName,
UserID: log.UserID, UserID: log.UserID,
Platform: stringutil.StringToInt32(log.Platform), Platform: log.Platform,
Url: log.Url, Url: log.Url,
CreateTime: log.CreateTime.UnixMilli(), CreateTime: log.CreateTime.UnixMilli(),
LogID: log.LogID, LogID: log.LogID,
+3 -3
View File
@@ -17,7 +17,7 @@ package user
import ( import (
"context" "context"
"errors" "errors"
"github.com/openimsdk/open-im-server/v3/internal/rpc/friend" "github.com/openimsdk/open-im-server/v3/internal/rpc/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
@@ -54,7 +54,7 @@ import (
type userServer struct { type userServer struct {
online cache.OnlineCache online cache.OnlineCache
db controller.UserDatabase db controller.UserDatabase
friendNotificationSender *friend.FriendNotificationSender friendNotificationSender *relation.FriendNotificationSender
userNotificationSender *UserNotificationSender userNotificationSender *UserNotificationSender
friendRpcClient *rpcclient.FriendRpcClient friendRpcClient *rpcclient.FriendRpcClient
groupRpcClient *rpcclient.GroupRpcClient groupRpcClient *rpcclient.GroupRpcClient
@@ -105,7 +105,7 @@ func Start(ctx context.Context, config *Config, client registry.SvcDiscoveryRegi
RegisterCenter: client, RegisterCenter: client,
friendRpcClient: &friendRpcClient, friendRpcClient: &friendRpcClient,
groupRpcClient: &groupRpcClient, groupRpcClient: &groupRpcClient,
friendNotificationSender: friend.NewFriendNotificationSender(&config.NotificationConfig, &msgRpcClient, friend.WithDBFunc(database.FindWithError)), friendNotificationSender: relation.NewFriendNotificationSender(&config.NotificationConfig, &msgRpcClient, relation.WithDBFunc(database.FindWithError)),
userNotificationSender: NewUserNotificationSender(config, &msgRpcClient, WithUserFunc(database.FindWithError)), userNotificationSender: NewUserNotificationSender(config, &msgRpcClient, WithUserFunc(database.FindWithError)),
config: config, config: config,
webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL), webhookClient: webhook.NewWebhookClient(config.WebhooksConfig.URL),
+53 -14
View File
@@ -17,16 +17,19 @@ package tools
import ( import (
"context" "context"
"fmt" "fmt"
"os"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" 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/msg"
"github.com/openimsdk/protocol/third" "github.com/openimsdk/protocol/third"
"github.com/openimsdk/tools/mcontext" "github.com/openimsdk/tools/mcontext"
"github.com/openimsdk/tools/mw" "github.com/openimsdk/tools/mw"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
"os"
"time"
"github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log" "github.com/openimsdk/tools/log"
@@ -50,34 +53,69 @@ func Start(ctx context.Context, config *CronTaskConfig) error {
} }
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
ctx = mcontext.SetOpUserID(ctx, config.Share.IMAdminUserID[0]) ctx = mcontext.SetOpUserID(ctx, config.Share.IMAdminUserID[0])
conn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
msgConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg)
if err != nil { if err != nil {
return err return err
} }
cli := msg.NewMsgClient(conn)
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
}
msgClient := msg.NewMsgClient(msgConn)
conversationClient := pbconversation.NewConversationClient(conversationConn)
thirdClient := third.NewThirdClient(thirdConn)
crontab := cron.New() crontab := cron.New()
clearFunc := func() {
// scheduled hard delete outdated Msgs in specific time.
clearMsgFunc := func() {
now := time.Now() now := time.Now()
deltime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.RetainChatRecords)) deltime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.RetainChatRecords))
ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deltime.UnixMilli())) ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deltime.UnixMilli()))
log.ZInfo(ctx, "clear chat records", "deltime", deltime, "timestamp", deltime.UnixMilli()) log.ZInfo(ctx, "clear chat records", "deltime", deltime, "timestamp", deltime.UnixMilli())
if _, err := cli.ClearMsg(ctx, &msg.ClearMsgReq{Timestamp: deltime.UnixMilli()}); err != nil { 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)) log.ZError(ctx, "cron clear chat records failed", err, "deltime", deltime, "cont", time.Since(now))
return return
} }
log.ZInfo(ctx, "cron clear chat records success", "deltime", deltime, "cont", time.Since(now)) log.ZInfo(ctx, "cron clear chat records success", "deltime", deltime, "cont", time.Since(now))
} }
if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, clearFunc); err != nil { if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, clearMsgFunc); err != nil {
return errs.Wrap(err) return errs.Wrap(err)
} }
tConn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Third) // scheduled soft delete outdated Msgs in specific time when user set `is_msg_destruct` feature.
if err != nil { msgDestructFunc := func() {
return err now := time.Now()
} ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), now.UnixMilli()))
thirdClient := third.NewThirdClient(tConn) log.ZInfo(ctx, "msg destruct cron start", "now", now)
deleteFunc := func() { 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.ZInfo(ctx, "msg destruct cron task completed", "cont", time.Since(now))
}
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() now := time.Now()
deleteTime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.FileExpireTime)) deleteTime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.FileExpireTime))
ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deleteTime.UnixMilli())) ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deleteTime.UnixMilli()))
@@ -88,9 +126,10 @@ func Start(ctx context.Context, config *CronTaskConfig) error {
} }
log.ZInfo(ctx, "cron deleteoutDatedData success", "deltime", deleteTime, "cont", time.Since(now)) log.ZInfo(ctx, "cron deleteoutDatedData success", "deltime", deleteTime, "cont", time.Since(now))
} }
if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, deleteFunc); err != nil { if _, err := crontab.AddFunc(config.CronTask.CronExecuteTime, deleteObjectFunc); err != nil {
return errs.Wrap(err) return errs.Wrap(err)
} }
log.ZInfo(ctx, "start cron task", "CronExecuteTime", config.CronTask.CronExecuteTime) log.ZInfo(ctx, "start cron task", "CronExecuteTime", config.CronTask.CronExecuteTime)
crontab.Start() crontab.Start()
<-ctx.Done() <-ctx.Done()
+1 -1
View File
@@ -56,7 +56,7 @@ const (
CallbackBeforeUpdateUserInfoCommand = "callbackBeforeUpdateUserInfoCommand" CallbackBeforeUpdateUserInfoCommand = "callbackBeforeUpdateUserInfoCommand"
CallbackBeforeCreateGroupCommand = "callbackBeforeCreateGroupCommand" CallbackBeforeCreateGroupCommand = "callbackBeforeCreateGroupCommand"
CallbackAfterCreateGroupCommand = "callbackAfterCreateGroupCommand" CallbackAfterCreateGroupCommand = "callbackAfterCreateGroupCommand"
CallbackBeforeMemberJoinGroupCommand = "callbackBeforeMemberJoinGroupCommand" CallbackBeforeMembersJoinGroupCommand = "callbackBeforeMembersJoinGroupCommand"
CallbackBeforeSetGroupMemberInfoCommand = "callbackBeforeSetGroupMemberInfoCommand" CallbackBeforeSetGroupMemberInfoCommand = "callbackBeforeSetGroupMemberInfoCommand"
CallbackAfterSetGroupMemberInfoCommand = "callbackAfterSetGroupMemberInfoCommand" CallbackAfterSetGroupMemberInfoCommand = "callbackAfterSetGroupMemberInfoCommand"
) )
+17 -8
View File
@@ -59,16 +59,20 @@ type CallbackAfterCreateGroupResp struct {
CommonCallbackResp CommonCallbackResp
} }
type CallbackBeforeMemberJoinGroupReq struct { type CallbackGroupMember struct {
CallbackCommand `json:"callbackCommand"` UserID string `json:"userID"`
GroupID string `json:"groupID"` Ex string `json:"ex"`
UserID string `json:"userID"`
Ex string `json:"ex"`
GroupEx string `json:"groupEx"`
} }
type CallbackBeforeMemberJoinGroupResp struct { type CallbackBeforeMembersJoinGroupReq struct {
CommonCallbackResp CallbackCommand `json:"callbackCommand"`
GroupID string `json:"groupID"`
MembersList []*CallbackGroupMember `json:"memberList"`
GroupEx string `json:"groupEx"`
}
type MemberJoinGroupCallBack struct {
UserID *string `json:"userID"`
Nickname *string `json:"nickname"` Nickname *string `json:"nickname"`
FaceURL *string `json:"faceURL"` FaceURL *string `json:"faceURL"`
RoleLevel *int32 `json:"roleLevel"` RoleLevel *int32 `json:"roleLevel"`
@@ -76,6 +80,11 @@ type CallbackBeforeMemberJoinGroupResp struct {
Ex *string `json:"ex"` Ex *string `json:"ex"`
} }
type CallbackBeforeMembersJoinGroupResp struct {
CommonCallbackResp
MemberCallbackList []*MemberJoinGroupCallBack `json:"memberCallbackList"`
}
type CallbackBeforeSetGroupMemberInfoReq struct { type CallbackBeforeSetGroupMemberInfoReq struct {
CallbackCommand `json:"callbackCommand"` CallbackCommand `json:"callbackCommand"`
GroupID string `json:"groupID"` GroupID string `json:"groupID"`
+3 -2
View File
@@ -16,8 +16,9 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/api" "github.com/openimsdk/open-im-server/v3/internal/api"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -38,7 +39,7 @@ func NewApiCmd() *ApiCmd {
DiscoveryConfigFilename: &apiConfig.Discovery, DiscoveryConfigFilename: &apiConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+3 -2
View File
@@ -16,9 +16,10 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/rpc/auth" "github.com/openimsdk/open-im-server/v3/internal/rpc/auth"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -40,7 +41,7 @@ func NewAuthRpcCmd() *AuthRpcCmd {
DiscoveryConfigFilename: &authConfig.Discovery, DiscoveryConfigFilename: &authConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+3 -2
View File
@@ -16,9 +16,10 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/rpc/conversation" "github.com/openimsdk/open-im-server/v3/internal/rpc/conversation"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -43,7 +44,7 @@ func NewConversationRpcCmd() *ConversationRpcCmd {
DiscoveryConfigFilename: &conversationConfig.Discovery, DiscoveryConfigFilename: &conversationConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+3 -2
View File
@@ -16,8 +16,9 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/tools" "github.com/openimsdk/open-im-server/v3/internal/tools"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -38,7 +39,7 @@ func NewCronTaskCmd() *CronTaskCmd {
DiscoveryConfigFilename: &cronTaskConfig.Discovery, DiscoveryConfigFilename: &cronTaskConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+20 -19
View File
@@ -16,35 +16,36 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/rpc/friend"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/internal/rpc/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
type FriendRpcCmd struct { type FriendRpcCmd struct {
*RootCmd *RootCmd
ctx context.Context ctx context.Context
configMap map[string]any configMap map[string]any
friendConfig *friend.Config relationConfig *relation.Config
} }
func NewFriendRpcCmd() *FriendRpcCmd { func NewFriendRpcCmd() *FriendRpcCmd {
var friendConfig friend.Config var relationConfig relation.Config
ret := &FriendRpcCmd{friendConfig: &friendConfig} ret := &FriendRpcCmd{relationConfig: &relationConfig}
ret.configMap = map[string]any{ ret.configMap = map[string]any{
OpenIMRPCFriendCfgFileName: &friendConfig.RpcConfig, OpenIMRPCFriendCfgFileName: &relationConfig.RpcConfig,
RedisConfigFileName: &friendConfig.RedisConfig, RedisConfigFileName: &relationConfig.RedisConfig,
MongodbConfigFileName: &friendConfig.MongodbConfig, MongodbConfigFileName: &relationConfig.MongodbConfig,
ShareFileName: &friendConfig.Share, ShareFileName: &relationConfig.Share,
NotificationFileName: &friendConfig.NotificationConfig, NotificationFileName: &relationConfig.NotificationConfig,
WebhooksConfigFileName: &friendConfig.WebhooksConfig, WebhooksConfigFileName: &relationConfig.WebhooksConfig,
LocalCacheConfigFileName: &friendConfig.LocalCacheConfig, LocalCacheConfigFileName: &relationConfig.LocalCacheConfig,
DiscoveryConfigFilename: &friendConfig.Discovery, DiscoveryConfigFilename: &relationConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
@@ -56,7 +57,7 @@ func (a *FriendRpcCmd) Exec() error {
} }
func (a *FriendRpcCmd) runE() error { func (a *FriendRpcCmd) runE() error {
return startrpc.Start(a.ctx, &a.friendConfig.Discovery, &a.friendConfig.RpcConfig.Prometheus, a.friendConfig.RpcConfig.RPC.ListenIP, return startrpc.Start(a.ctx, &a.relationConfig.Discovery, &a.relationConfig.RpcConfig.Prometheus, a.relationConfig.RpcConfig.RPC.ListenIP,
a.friendConfig.RpcConfig.RPC.RegisterIP, a.friendConfig.RpcConfig.RPC.Ports, a.relationConfig.RpcConfig.RPC.RegisterIP, a.relationConfig.RpcConfig.RPC.Ports,
a.Index(), a.friendConfig.Share.RpcRegisterName.Friend, &a.friendConfig.Share, a.friendConfig, friend.Start) a.Index(), a.relationConfig.Share.RpcRegisterName.Friend, &a.relationConfig.Share, a.relationConfig, relation.Start)
} }
+3 -2
View File
@@ -16,10 +16,11 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/rpc/group" "github.com/openimsdk/open-im-server/v3/internal/rpc/group"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -45,7 +46,7 @@ func NewGroupRpcCmd() *GroupRpcCmd {
DiscoveryConfigFilename: &groupConfig.Discovery, DiscoveryConfigFilename: &groupConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+3 -2
View File
@@ -16,9 +16,10 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/rpc/msg" "github.com/openimsdk/open-im-server/v3/internal/rpc/msg"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -45,7 +46,7 @@ func NewMsgRpcCmd() *MsgRpcCmd {
DiscoveryConfigFilename: &msgConfig.Discovery, DiscoveryConfigFilename: &msgConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+2 -2
View File
@@ -16,9 +16,9 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/internal/msggateway" "github.com/openimsdk/open-im-server/v3/internal/msggateway"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@@ -42,7 +42,7 @@ func NewMsgGatewayCmd() *MsgGatewayCmd {
DiscoveryConfigFilename: &msgGatewayConfig.Discovery, DiscoveryConfigFilename: &msgGatewayConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+3 -2
View File
@@ -16,8 +16,9 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/msgtransfer" "github.com/openimsdk/open-im-server/v3/internal/msgtransfer"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -42,7 +43,7 @@ func NewMsgTransferCmd() *MsgTransferCmd {
DiscoveryConfigFilename: &msgTransferConfig.Discovery, DiscoveryConfigFilename: &msgTransferConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+3 -2
View File
@@ -16,9 +16,10 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/push" "github.com/openimsdk/open-im-server/v3/internal/push"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -45,7 +46,7 @@ func NewPushRpcCmd() *PushRpcCmd {
DiscoveryConfigFilename: &pushConfig.Discovery, DiscoveryConfigFilename: &pushConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
ret.pushConfig.FcmConfigPath = ret.ConfigPath() ret.pushConfig.FcmConfigPath = ret.ConfigPath()
return ret.runE() return ret.runE()
+3 -2
View File
@@ -19,6 +19,7 @@ import (
"path/filepath" "path/filepath"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log" "github.com/openimsdk/tools/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@@ -138,13 +139,13 @@ func (r *RootCmd) initializeLogger(cmdOpts *CmdOpts) error {
r.log.StorageLocation, r.log.StorageLocation,
r.log.RemainRotationCount, r.log.RemainRotationCount,
r.log.RotationTime, r.log.RotationTime,
config.Version, version.Version,
r.log.IsSimplify, r.log.IsSimplify,
) )
if err != nil { if err != nil {
return errs.Wrap(err) return errs.Wrap(err)
} }
return errs.Wrap(log.InitConsoleLogger(r.processName, r.log.RemainLogLevel, r.log.IsJson, config.Version)) return errs.Wrap(log.InitConsoleLogger(r.processName, r.log.RemainLogLevel, r.log.IsJson, version.Version))
} }
+3 -2
View File
@@ -16,9 +16,10 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/rpc/third" "github.com/openimsdk/open-im-server/v3/internal/rpc/third"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -44,7 +45,7 @@ func NewThirdRpcCmd() *ThirdRpcCmd {
DiscoveryConfigFilename: &thirdConfig.Discovery, DiscoveryConfigFilename: &thirdConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
+3 -2
View File
@@ -16,9 +16,10 @@ package cmd
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/internal/rpc/user" "github.com/openimsdk/open-im-server/v3/internal/rpc/user"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/startrpc" "github.com/openimsdk/open-im-server/v3/pkg/common/startrpc"
"github.com/openimsdk/open-im-server/v3/version"
"github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/system/program"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -45,7 +46,7 @@ func NewUserRpcCmd() *UserRpcCmd {
DiscoveryConfigFilename: &userConfig.Discovery, DiscoveryConfigFilename: &userConfig.Discovery,
} }
ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap))
ret.ctx = context.WithValue(context.Background(), "version", config.Version) ret.ctx = context.WithValue(context.Background(), "version", version.Version)
ret.Command.RunE = func(cmd *cobra.Command, args []string) error { ret.Command.RunE = func(cmd *cobra.Command, args []string) error {
return ret.runE() return ret.runE()
} }
-4
View File
@@ -15,7 +15,6 @@
package config package config
import ( import (
_ "embed"
"os" "os"
"path/filepath" "path/filepath"
@@ -26,9 +25,6 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
//go:embed version
var Version string
const ( const (
FileName = "config.yaml" FileName = "config.yaml"
NotificationFileName = "notification.yaml" NotificationFileName = "notification.yaml"
-1
View File
@@ -1 +0,0 @@
3.7.0
+2 -2
View File
@@ -22,7 +22,7 @@ import (
func ConversationDB2Pb(conversationDB *model.Conversation) *conversation.Conversation { func ConversationDB2Pb(conversationDB *model.Conversation) *conversation.Conversation {
conversationPB := &conversation.Conversation{} conversationPB := &conversation.Conversation{}
conversationPB.LatestMsgDestructTime = conversationDB.LatestMsgDestructTime.Unix() conversationPB.LatestMsgDestructTime = conversationDB.LatestMsgDestructTime.UnixMilli()
if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil { if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil {
return nil return nil
} }
@@ -35,7 +35,7 @@ func ConversationsDB2Pb(conversationsDB []*model.Conversation) (conversationsPB
if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil { if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil {
continue continue
} }
conversationPB.LatestMsgDestructTime = conversationDB.LatestMsgDestructTime.Unix() conversationPB.LatestMsgDestructTime = conversationDB.LatestMsgDestructTime.UnixMilli()
conversationsPB = append(conversationsPB, conversationPB) conversationsPB = append(conversationsPB, conversationPB)
} }
return conversationsPB return conversationsPB
+1 -1
View File
@@ -45,7 +45,7 @@ func TestName(t *testing.T) {
} }
seqUser := NewSeqUserCacheRedis(rdb, mgoSeqUser) seqUser := NewSeqUserCacheRedis(rdb, mgoSeqUser)
res, err := seqUser.GetReadSeqs(ctx, "2110910952", []string{"sg_2920732023", "sg_345762580"}) res, err := seqUser.GetUserReadSeqs(ctx, "2110910952", []string{"sg_2920732023", "sg_345762580"})
if err != nil { if err != nil {
panic(err) panic(err)
} }
+5 -1
View File
@@ -5,6 +5,7 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
"github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"strconv" "strconv"
"time" "time"
@@ -82,8 +83,11 @@ func (s *userOnline) SetUserOnline(ctx context.Context, userID string, online, o
argv = append(argv, platformID) argv = append(argv, platformID)
} }
keys := []string{s.getUserOnlineKey(userID), userID, s.channelName} keys := []string{s.getUserOnlineKey(userID), userID, s.channelName}
if err := s.rdb.Eval(ctx, script, keys, argv).Err(); err != nil { status, err := s.rdb.Eval(ctx, script, keys, argv).Result()
if err != nil {
log.ZError(ctx, "redis SetUserOnline", err, "userID", userID, "online", online, "offline", offline)
return err return err
} }
log.ZDebug(ctx, "redis SetUserOnline", "userID", userID, "online", online, "offline", offline, "status", status)
return nil return nil
} }
+32
View File
@@ -4,7 +4,10 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
mgo2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log" "log"
"strconv" "strconv"
"sync/atomic" "sync/atomic"
@@ -77,3 +80,32 @@ func TestRecvOnline(t *testing.T) {
fmt.Printf("Received message from channel %s: %s\n", msg.Channel, msg.Payload) fmt.Printf("Received message from channel %s: %s\n", msg.Channel, msg.Payload)
} }
} }
func TestName1(t *testing.T) {
opt := &redis.Options{
Addr: "172.16.8.48:16379",
Password: "openIM123",
DB: 0,
}
rdb := redis.NewClient(opt)
mgo, err := mongo.Connect(context.Background(),
options.Client().
ApplyURI("mongodb://openIM:openIM123@172.16.8.48:37017/openim_v3?maxPoolSize=100").
SetConnectTimeout(5*time.Second))
if err != nil {
panic(err)
}
model, err := mgo2.NewSeqUserMongo(mgo.Database("openim_v3"))
if err != nil {
panic(err)
}
seq := NewSeqUserCacheRedis(rdb, model)
res, err := seq.GetUserReadSeqs(context.Background(), "2110910952", []string{"sg_345762580", "2000", "3000"})
if err != nil {
panic(err)
}
t.Log(res)
}
+39 -26
View File
@@ -152,42 +152,55 @@ func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string,
return f.tx.Transaction(ctx, func(ctx context.Context) error { return f.tx.Transaction(ctx, func(ctx context.Context) error {
cache := f.cache.CloneFriendCache() cache := f.cache.CloneFriendCache()
// user find friends // user find friends
fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs) myFriends, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
addOwners, err := f.friend.FindReversalFriends(ctx, ownerUserID, friendUserIDs)
if err != nil { if err != nil {
return err return err
} }
opUserID := mcontext.GetOperationID(ctx) opUserID := mcontext.GetOperationID(ctx)
for _, v := range friendUserIDs { friends := make([]*model.Friend, 0, len(friendUserIDs)*2)
fs1 = append(fs1, &model.Friend{OwnerUserID: ownerUserID, FriendUserID: v, AddSource: addSource, OperatorUserID: opUserID}) myFriendsSet := datautil.SliceSetAny(myFriends, func(friend *model.Friend) string {
} return friend.FriendUserID
fs11 := datautil.DistinctAny(fs1, func(e *model.Friend) string {
return e.FriendUserID
}) })
addOwnersSet := datautil.SliceSetAny(addOwners, func(friend *model.Friend) string {
err = f.friend.Create(ctx, fs11) return friend.OwnerUserID
if err != nil {
return err
}
fs2, err := f.friend.FindReversalFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
var newFriendIDs []string
for _, v := range friendUserIDs {
fs2 = append(fs2, &model.Friend{OwnerUserID: v, FriendUserID: ownerUserID, AddSource: addSource, OperatorUserID: opUserID})
newFriendIDs = append(newFriendIDs, v)
}
fs22 := datautil.DistinctAny(fs2, func(e *model.Friend) string {
return e.OwnerUserID
}) })
err = f.friend.Create(ctx, fs22) newMyFriendIDs := make([]string, 0, len(friendUserIDs))
newMyOwnerIDs := make([]string, 0, len(friendUserIDs))
for _, userID := range friendUserIDs {
if ownerUserID == userID {
continue
}
if _, ok := myFriendsSet[userID]; !ok {
myFriendsSet[userID] = struct{}{}
newMyFriendIDs = append(newMyFriendIDs, userID)
friends = append(friends, &model.Friend{OwnerUserID: ownerUserID, FriendUserID: userID, AddSource: addSource, OperatorUserID: opUserID})
}
if _, ok := addOwnersSet[userID]; !ok {
addOwnersSet[userID] = struct{}{}
newMyOwnerIDs = append(newMyOwnerIDs, userID)
friends = append(friends, &model.Friend{OwnerUserID: userID, FriendUserID: ownerUserID, AddSource: addSource, OperatorUserID: opUserID})
}
}
if len(friends) == 0 {
return nil
}
err = f.friend.Create(ctx, friends)
if err != nil { if err != nil {
return err return err
} }
newFriendIDs = append(newFriendIDs, ownerUserID) if len(newMyFriendIDs) > 0 {
cache = cache.DelFriendIDs(newFriendIDs...).DelMaxFriendVersion(newFriendIDs...) cache = cache.DelFriendIDs(newMyFriendIDs...)
cache = cache.DelFriends(ownerUserID, newMyFriendIDs).DelMaxFriendVersion(newMyFriendIDs...)
}
if len(newMyOwnerIDs) > 0 {
cache = cache.DelFriendIDs(newMyOwnerIDs...)
cache = cache.DelOwner(ownerUserID, newMyOwnerIDs).DelMaxFriendVersion(newMyOwnerIDs...)
}
return cache.ChainExecDel(ctx) return cache.ChainExecDel(ctx)
}) })
} }
+3 -3
View File
@@ -84,7 +84,7 @@ type CommonMsgDatabase interface {
//GetConversationMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache 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 SetSendMsgStatus(ctx context.Context, id string, status int32) error
GetSendMsgStatus(ctx context.Context, id string) (int32, error) GetSendMsgStatus(ctx context.Context, id string) (int32, error)
SearchMessage(ctx context.Context, req *pbmsg.SearchMessageReq) (total int32, msgData []*sdkws.MsgData, err error) SearchMessage(ctx context.Context, req *pbmsg.SearchMessageReq) (total int64, msgData []*sdkws.MsgData, err error)
FindOneByDocIDs(ctx context.Context, docIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error) FindOneByDocIDs(ctx context.Context, docIDs []string, seqs map[string]int64) (map[string]*sdkws.MsgData, error)
// to mq // to mq
@@ -721,7 +721,7 @@ func (db *commonMsgDatabase) deleteMsgRecursion(ctx context.Context, conversatio
} }
log.ZDebug(ctx, "doc info", "conversationID", conversationID, "index", index, "docID", msgDocModel.DocID, "len", len(msgDocModel.Msg)) log.ZDebug(ctx, "doc info", "conversationID", conversationID, "index", index, "docID", msgDocModel.DocID, "len", len(msgDocModel.Msg))
if int64(len(msgDocModel.Msg)) > db.msgTable.GetSingleGocMsgNum() { if int64(len(msgDocModel.Msg)) > db.msgTable.GetSingleGocMsgNum() {
log.ZWarn(ctx, "msgs too large", nil, "lenth", len(msgDocModel.Msg), "docID:", msgDocModel.DocID) 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() { 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) log.ZDebug(ctx, "doc is full and all msg is expired", "docID", msgDocModel.DocID)
@@ -878,7 +878,7 @@ func (db *commonMsgDatabase) RangeGroupSendCount(
return db.msgDocDatabase.RangeGroupSendCount(ctx, start, end, ase, pageNumber, showNumber) return db.msgDocDatabase.RangeGroupSendCount(ctx, start, end, ase, pageNumber, showNumber)
} }
func (db *commonMsgDatabase) SearchMessage(ctx context.Context, req *pbmsg.SearchMessageReq) (total int32, msgData []*sdkws.MsgData, err error) { func (db *commonMsgDatabase) SearchMessage(ctx context.Context, req *pbmsg.SearchMessageReq) (total int64, msgData []*sdkws.MsgData, err error) {
var totalMsgs []*sdkws.MsgData var totalMsgs []*sdkws.MsgData
total, msgs, err := db.msgDocDatabase.SearchMessage(ctx, req) total, msgs, err := db.msgDocDatabase.SearchMessage(ctx, req)
if err != nil { if err != nil {
+383 -87
View File
@@ -278,124 +278,420 @@ func (m *MsgMgo) MarkSingleChatMsgsAsRead(ctx context.Context, userID string, do
return nil return nil
} }
func (m *MsgMgo) SearchMessage(ctx context.Context, req *msg.SearchMessageReq) (int32, []*model.MsgInfoModel, error) { //func (m *MsgMgo) searchCount(ctx context.Context, filter any) (int64, error) {
where := make(bson.A, 0, 6) //
// return nil, nil
//}
//func (m *MsgMgo) searchMessage(ctx context.Context, filter any, nextID primitive.ObjectID, content bool, limit int) (int64, []*model.MsgInfoModel, primitive.ObjectID, error) {
// var pipeline bson.A
// if !nextID.IsZero() {
// pipeline = append(pipeline, bson.M{"$match": bson.M{"_id": bson.M{"$gt": nextID}}})
// }
// pipeline = append(pipeline,
// bson.M{"$match": filter},
// bson.M{"$limit": limit},
// bson.M{"$unwind": "$msgs"},
// bson.M{"$match": filter},
// bson.M{
// "$group": bson.M{
// "_id": "$_id",
// "doc_id": bson.M{
// "$first": "$doc_id",
// },
// "msgs": bson.M{"$push": "$msgs"},
// },
// },
// )
// if !content {
// pipeline = append(pipeline,
// bson.M{
// "$project": bson.M{
// "_id": 1,
// "count": bson.M{"$size": "$msgs"},
// },
// },
// )
// type result struct {
// ID primitive.ObjectID `bson:"_id"`
// Count int64 `bson:"count"`
// }
// res, err := mongoutil.Aggregate[result](ctx, m.coll, pipeline)
// if err != nil {
// return 0, nil, primitive.ObjectID{}, err
// }
// if len(res) == 0 {
// return 0, nil, primitive.ObjectID{}, nil
// }
// var count int64
// for _, r := range res {
// count += r.Count
// }
// return count, nil, res[len(res)-1].ID, nil
// }
// type result struct {
// ID primitive.ObjectID `bson:"_id"`
// Msg []*model.MsgInfoModel `bson:"msgs"`
// }
// res, err := mongoutil.Aggregate[result](ctx, m.coll, pipeline)
// if err != nil {
// return 0, nil, primitive.ObjectID{}, err
// }
// if len(res) == 0 {
// return 0, nil, primitive.ObjectID{}, err
// }
// var count int
// for _, r := range res {
// count += len(r.Msg)
// }
// msgs := make([]*model.MsgInfoModel, 0, count)
// for _, r := range res {
// msgs = append(msgs, r.Msg...)
// }
// return int64(count), msgs, res[len(res)-1].ID, nil
//}
/*
db.msg3.aggregate(
[
{
"$match": {
"doc_id": "si_7009965934_8710838466:0"
},
}
]
)
*/
type searchMessageIndex struct {
ID primitive.ObjectID `bson:"_id"`
Index []int64 `bson:"index"`
}
func (m *MsgMgo) searchMessageIndex(ctx context.Context, filter any, nextID primitive.ObjectID, limit int) ([]searchMessageIndex, error) {
var pipeline bson.A
if !nextID.IsZero() {
pipeline = append(pipeline, bson.M{"$match": bson.M{"_id": bson.M{"$gt": nextID}}})
}
coarseFilter := bson.M{
"$or": bson.A{
bson.M{
"doc_id": primitive.Regex{Pattern: "^sg_"},
},
bson.M{
"doc_id": primitive.Regex{Pattern: "^si_"},
},
},
}
pipeline = append(pipeline,
bson.M{"$sort": bson.M{"_id": 1}},
bson.M{"$match": coarseFilter},
bson.M{"$match": filter},
bson.M{"$limit": limit},
bson.M{
"$project": bson.M{
"_id": 1,
"msgs": bson.M{
"$map": bson.M{
"input": "$msgs",
"as": "msg",
"in": bson.M{
"$mergeObjects": bson.A{
"$$msg",
bson.M{
"_search_temp_index": bson.M{
"$indexOfArray": bson.A{
"$msgs", "$$msg",
},
},
},
},
},
},
},
},
},
bson.M{"$unwind": "$msgs"},
bson.M{"$match": filter},
bson.M{
"$project": bson.M{
"_id": 1,
"msgs._search_temp_index": 1,
},
},
bson.M{
"$group": bson.M{
"_id": "$_id",
"index": bson.M{"$push": "$msgs._search_temp_index"},
},
},
bson.M{"$sort": bson.M{"_id": 1}},
)
return mongoutil.Aggregate[searchMessageIndex](ctx, m.coll, pipeline)
}
func (m *MsgMgo) searchMessage(ctx context.Context, req *msg.SearchMessageReq) (int64, []searchMessageIndex, error) {
filter := bson.M{}
if req.RecvID != "" { if req.RecvID != "" {
where = append(where, bson.M{"msgs.msg.recv_id": req.RecvID}) filter["$or"] = bson.A{
bson.M{"msgs.msg.recv_id": req.RecvID},
bson.M{"msgs.msg.group_id": req.RecvID},
}
} }
if req.SendID != "" { if req.SendID != "" {
where = append(where, bson.M{"msgs.msg.send_id": req.SendID}) filter["msgs.msg.send_id"] = req.SendID
} }
if req.ContentType != 0 { if req.ContentType != 0 {
where = append(where, bson.M{"msgs.msg.content_type": req.ContentType}) filter["msgs.msg.content_type"] = req.ContentType
} }
if req.SessionType != 0 { if req.SessionType != 0 {
where = append(where, bson.M{"msgs.msg.session_type": req.SessionType}) filter["msgs.msg.session_type"] = req.SessionType
} }
if req.SendTime != "" { if req.SendTime != "" {
sendTime, err := time.Parse(time.DateOnly, req.SendTime) sendTime, err := time.Parse(time.DateOnly, req.SendTime)
if err != nil { if err != nil {
return 0, nil, errs.ErrArgs.WrapMsg("invalid sendTime", "req", req.SendTime, "format", time.DateOnly, "cause", err.Error()) return 0, nil, errs.ErrArgs.WrapMsg("invalid sendTime", "req", req.SendTime, "format", time.DateOnly, "cause", err.Error())
} }
where = append(where, filter["$and"] = bson.A{
bson.M{ bson.M{"msgs.msg.send_time": bson.M{
"msgs.msg.send_time": bson.M{ "$gte": sendTime.UnixMilli(),
"$gte": sendTime.UnixMilli(), }},
},
},
bson.M{ bson.M{
"msgs.msg.send_time": bson.M{ "msgs.msg.send_time": bson.M{
"$lt": sendTime.Add(time.Hour * 24).UnixMilli(), "$lt": sendTime.Add(time.Hour * 24).UnixMilli(),
}, },
}, },
) }
} }
var (
nextID primitive.ObjectID
count int
dataRange []searchMessageIndex
skip = int((req.Pagination.GetPageNumber() - 1) * req.Pagination.GetShowNumber())
)
_, _ = dataRange, skip
const maxDoc = 50
data := make([]searchMessageIndex, 0, req.Pagination.GetShowNumber())
push := cap(data)
for i := 0; ; i++ {
res, err := m.searchMessageIndex(ctx, filter, nextID, maxDoc)
if err != nil {
return 0, nil, err
}
if len(res) > 0 {
nextID = res[len(res)-1].ID
}
for _, r := range res {
var dataIndex []int64
for _, index := range r.Index {
if push > 0 && count >= skip {
dataIndex = append(dataIndex, index)
push--
}
count++
}
if len(dataIndex) > 0 {
data = append(data, searchMessageIndex{
ID: r.ID,
Index: dataIndex,
})
}
}
if push <= 0 {
push--
}
if len(res) < maxDoc || push < -10 {
return int64(count), data, nil
}
}
}
func (m *MsgMgo) getDocRange(ctx context.Context, id primitive.ObjectID, index []int64) ([]*model.MsgInfoModel, error) {
if len(index) == 0 {
return nil, nil
}
pipeline := bson.A{ pipeline := bson.A{
bson.M{ bson.M{"$match": bson.M{"_id": id}},
"$unwind": "$msgs", bson.M{"$project": "$msgs"},
},
} }
if len(where) > 0 {
pipeline = append(pipeline, bson.M{
"$match": bson.M{"$and": where},
})
}
pipeline = append(pipeline,
bson.M{
"$project": bson.M{
"_id": 0,
"msg": "$msgs.msg",
},
},
bson.M{
"$count": "count",
},
)
count, err := mongoutil.Aggregate[int32](ctx, m.coll, pipeline)
if err != nil {
return 0, nil, err
}
if len(count) == 0 || count[0] == 0 {
return 0, nil, nil
}
pipeline = pipeline[:len(pipeline)-1]
pipeline = append(pipeline,
bson.M{
"$skip": (req.Pagination.GetPageNumber() - 1) * req.Pagination.GetShowNumber(),
},
bson.M{
"$limit": req.Pagination.GetShowNumber(),
},
)
msgs, err := mongoutil.Aggregate[*model.MsgInfoModel](ctx, m.coll, pipeline) msgs, err := mongoutil.Aggregate[*model.MsgInfoModel](ctx, m.coll, pipeline)
if err != nil {
return nil, err
}
return msgs, nil
}
func (m *MsgMgo) SearchMessage(ctx context.Context, req *msg.SearchMessageReq) (int64, []*model.MsgInfoModel, error) {
count, data, err := m.searchMessage(ctx, req)
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
} }
for i := range msgs { var msgs []*model.MsgInfoModel
msgInfo := msgs[i] if len(data) > 0 {
if msgInfo == nil || msgInfo.Msg == nil { var n int
continue for _, d := range data {
n += len(d.Index)
} }
if msgInfo.Revoke != nil { msgs = make([]*model.MsgInfoModel, 0, n)
revokeContent := sdkws.MessageRevokedContent{ }
RevokerID: msgInfo.Revoke.UserID, for _, val := range data {
RevokerRole: msgInfo.Revoke.Role, res, err := mongoutil.FindOne[*model.MsgDocModel](ctx, m.coll, bson.M{"_id": val.ID})
ClientMsgID: msgInfo.Msg.ClientMsgID, if err != nil {
RevokerNickname: msgInfo.Revoke.Nickname, return 0, nil, err
RevokeTime: msgInfo.Revoke.Time, }
SourceMessageSendTime: msgInfo.Msg.SendTime, for _, i := range val.Index {
SourceMessageSendID: msgInfo.Msg.SendID, if i >= int64(len(res.Msg)) {
SourceMessageSenderNickname: msgInfo.Msg.SenderNickname, continue
SessionType: msgInfo.Msg.SessionType,
Seq: msgInfo.Msg.Seq,
Ex: msgInfo.Msg.Ex,
} }
data, err := jsonutil.JsonMarshal(&revokeContent) msgs = append(msgs, res.Msg[i])
if err != nil {
return 0, nil, errs.WrapMsg(err, "json.Marshal revokeContent")
}
elem := sdkws.NotificationElem{Detail: string(data)}
content, err := jsonutil.JsonMarshal(&elem)
if err != nil {
return 0, nil, errs.WrapMsg(err, "json.Marshal elem")
}
msgInfo.Msg.ContentType = constant.MsgRevokeNotification
msgInfo.Msg.Content = string(content)
} }
} }
//start := (req.Pagination.PageNumber - 1) * req.Pagination.ShowNumber return count, msgs, nil
//n := int32(len(msgs))
//if start >= n {
// return n, []*relation.MsgInfoModel{}, nil
//}
//if start+req.Pagination.ShowNumber < n {
// msgs = msgs[start : start+req.Pagination.ShowNumber]
//} else {
// msgs = msgs[start:]
//}
return count[0], msgs, nil
} }
//func (m *MsgMgo) SearchMessage(ctx context.Context, req *msg.SearchMessageReq) (int32, []*model.MsgInfoModel, error) {
// where := make(bson.A, 0, 6)
// if req.RecvID != "" {
// if req.SessionType == constant.ReadGroupChatType {
// where = append(where, bson.M{
// "$or": bson.A{
// bson.M{"doc_id": "^n_" + req.RecvID + ":"},
// bson.M{"doc_id": "^sg_" + req.RecvID + ":"},
// },
// })
// } else {
// where = append(where, bson.M{"msgs.msg.recv_id": req.RecvID})
// }
// }
// if req.SendID != "" {
// where = append(where, bson.M{"msgs.msg.send_id": req.SendID})
// }
// if req.ContentType != 0 {
// where = append(where, bson.M{"msgs.msg.content_type": req.ContentType})
// }
// if req.SessionType != 0 {
// where = append(where, bson.M{"msgs.msg.session_type": req.SessionType})
// }
// if req.SendTime != "" {
// sendTime, err := time.Parse(time.DateOnly, req.SendTime)
// if err != nil {
// return 0, nil, errs.ErrArgs.WrapMsg("invalid sendTime", "req", req.SendTime, "format", time.DateOnly, "cause", err.Error())
// }
// where = append(where,
// bson.M{
// "msgs.msg.send_time": bson.M{
// "$gte": sendTime.UnixMilli(),
// },
// },
// bson.M{
// "msgs.msg.send_time": bson.M{
// "$lt": sendTime.Add(time.Hour * 24).UnixMilli(),
// },
// },
// )
// }
// opt := options.Find().SetLimit(100)
// res, err := mongoutil.Find[model.MsgDocModel](ctx, m.coll, bson.M{"$and": where}, opt)
// if err != nil {
// return 0, nil, err
// }
// _ = res
// fmt.Println()
//
// return 0, nil, nil
// pipeline := bson.A{
// bson.M{
// "$unwind": "$msgs",
// },
// }
// if len(where) > 0 {
// pipeline = append(pipeline, bson.M{
// "$match": bson.M{"$and": where},
// })
// }
// pipeline = append(pipeline,
// bson.M{
// "$project": bson.M{
// "_id": 0,
// "msg": "$msgs.msg",
// },
// },
// bson.M{
// "$count": "count",
// },
// )
// //count, err := mongoutil.Aggregate[int32](ctx, m.coll, pipeline)
// //if err != nil {
// // return 0, nil, err
// //}
// //if len(count) == 0 || count[0] == 0 {
// // return 0, nil, nil
// //}
// count := []int32{0}
// pipeline = pipeline[:len(pipeline)-1]
// pipeline = append(pipeline,
// bson.M{
// "$skip": (req.Pagination.GetPageNumber() - 1) * req.Pagination.GetShowNumber(),
// },
// bson.M{
// "$limit": req.Pagination.GetShowNumber(),
// },
// )
// msgs, err := mongoutil.Aggregate[*model.MsgInfoModel](ctx, m.coll, pipeline)
// if err != nil {
// return 0, nil, err
// }
// for i := range msgs {
// msgInfo := msgs[i]
// if msgInfo == nil || msgInfo.Msg == nil {
// continue
// }
// if msgInfo.Revoke != nil {
// revokeContent := sdkws.MessageRevokedContent{
// RevokerID: msgInfo.Revoke.UserID,
// RevokerRole: msgInfo.Revoke.Role,
// ClientMsgID: msgInfo.Msg.ClientMsgID,
// RevokerNickname: msgInfo.Revoke.Nickname,
// RevokeTime: msgInfo.Revoke.Time,
// SourceMessageSendTime: msgInfo.Msg.SendTime,
// SourceMessageSendID: msgInfo.Msg.SendID,
// SourceMessageSenderNickname: msgInfo.Msg.SenderNickname,
// SessionType: msgInfo.Msg.SessionType,
// Seq: msgInfo.Msg.Seq,
// Ex: msgInfo.Msg.Ex,
// }
// data, err := jsonutil.JsonMarshal(&revokeContent)
// if err != nil {
// return 0, nil, errs.WrapMsg(err, "json.Marshal revokeContent")
// }
// elem := sdkws.NotificationElem{Detail: string(data)}
// content, err := jsonutil.JsonMarshal(&elem)
// if err != nil {
// return 0, nil, errs.WrapMsg(err, "json.Marshal elem")
// }
// msgInfo.Msg.ContentType = constant.MsgRevokeNotification
// msgInfo.Msg.Content = string(content)
// }
// }
// //start := (req.Pagination.PageNumber - 1) * req.Pagination.ShowNumber
// //n := int32(len(msgs))
// //if start >= n {
// // return n, []*relation.MsgInfoModel{}, nil
// //}
// //if start+req.Pagination.ShowNumber < n {
// // msgs = msgs[start : start+req.Pagination.ShowNumber]
// //} else {
// // msgs = msgs[start:]
// //}
// return count[0], msgs, nil
//}
func (m *MsgMgo) 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 (m *MsgMgo) 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) {
var sort int var sort int
if ase { if ase {
@@ -0,0 +1,75 @@
package mgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
"github.com/openimsdk/protocol/msg"
"github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/tools/db/mongoutil"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"math/rand"
"strconv"
"testing"
"time"
)
func TestName1(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*300)
defer cancel()
cli := Result(mongo.Connect(ctx, options.Client().ApplyURI("mongodb://openIM:openIM123@172.16.8.48:37017/openim_v3?maxPoolSize=100").SetConnectTimeout(5*time.Second)))
v := &MsgMgo{
coll: cli.Database("openim_v3").Collection("msg3"),
}
req := &msg.SearchMessageReq{
//RecvID: "3187706596",
//SendID: "7009965934",
ContentType: 101,
//SendTime: "2024-05-06",
//SessionType: 3,
Pagination: &sdkws.RequestPagination{
PageNumber: 1,
ShowNumber: 10,
},
}
total, res, err := v.SearchMessage(ctx, req)
if err != nil {
panic(err)
}
for i, re := range res {
t.Logf("%d => %d | %+v", i+1, re.Msg.Seq, re.Msg.Content)
}
t.Log(total)
}
func TestName10(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
cli := Result(mongo.Connect(ctx, options.Client().ApplyURI("mongodb://openIM:openIM123@172.16.8.48:37017/openim_v3?maxPoolSize=100").SetConnectTimeout(5*time.Second)))
v := &MsgMgo{
coll: cli.Database("openim_v3").Collection("msg3"),
}
opt := options.Find().SetLimit(1000)
res, err := mongoutil.Find[model.MsgDocModel](ctx, v.coll, bson.M{}, opt)
if err != nil {
panic(err)
}
ctx = context.Background()
for i := 0; i < 100000; i++ {
for j := range res {
res[j].DocID = strconv.FormatUint(rand.Uint64(), 10) + ":0"
}
if err := mongoutil.InsertMany(ctx, v.coll, res); err != nil {
panic(err)
}
t.Log("====>", time.Now(), i)
}
}
@@ -26,7 +26,7 @@ func Mongodb() *mongo.Database {
func TestUserSeq(t *testing.T) { func TestUserSeq(t *testing.T) {
uSeq := Result(NewSeqUserMongo(Mongodb())).(*seqUserMongo) uSeq := Result(NewSeqUserMongo(Mongodb())).(*seqUserMongo)
t.Log(uSeq.SetMinSeq(context.Background(), "1000", "2000", 4)) t.Log(uSeq.SetUserMinSeq(context.Background(), "1000", "2000", 4))
} }
func TestConversationSeq(t *testing.T) { func TestConversationSeq(t *testing.T) {
@@ -35,3 +35,8 @@ func TestConversationSeq(t *testing.T) {
t.Log(cSeq.Malloc(context.Background(), "2000", 10)) t.Log(cSeq.Malloc(context.Background(), "2000", 10))
t.Log(cSeq.GetMaxSeq(context.Background(), "2000")) t.Log(cSeq.GetMaxSeq(context.Background(), "2000"))
} }
func TestUserGetUserReadSeqs(t *testing.T) {
uSeq := Result(NewSeqUserMongo(Mongodb())).(*seqUserMongo)
t.Log(uSeq.GetUserReadSeqs(context.Background(), "2110910952", []string{"sg_345762580", "2000", "3000"}))
}
@@ -88,6 +88,14 @@ func (s *seqUserMongo) GetUserReadSeq(ctx context.Context, conversationID string
return s.getSeq(ctx, conversationID, userID, "read_seq") return s.getSeq(ctx, conversationID, userID, "read_seq")
} }
func (s *seqUserMongo) notFoundSet0(seq map[string]int64, conversationIDs []string) {
for _, conversationID := range conversationIDs {
if _, ok := seq[conversationID]; !ok {
seq[conversationID] = 0
}
}
}
func (s *seqUserMongo) GetUserReadSeqs(ctx context.Context, userID string, conversationID []string) (map[string]int64, error) { func (s *seqUserMongo) GetUserReadSeqs(ctx context.Context, userID string, conversationID []string) (map[string]int64, error) {
if len(conversationID) == 0 { if len(conversationID) == 0 {
return map[string]int64{}, nil return map[string]int64{}, nil
@@ -102,6 +110,7 @@ func (s *seqUserMongo) GetUserReadSeqs(ctx context.Context, userID string, conve
for _, seq := range seqs { for _, seq := range seqs {
res[seq.ConversationID] = seq.ReadSeq res[seq.ConversationID] = seq.ReadSeq
} }
s.notFoundSet0(res, conversationID)
return res, nil return res, nil
} }
+1 -1
View File
@@ -37,7 +37,7 @@ type Msg interface {
GetMsgDocModelByIndex(ctx context.Context, conversationID string, index, sort int64) (*model.MsgDocModel, error) GetMsgDocModelByIndex(ctx context.Context, conversationID string, index, sort int64) (*model.MsgDocModel, error)
DeleteMsgsInOneDocByIndex(ctx context.Context, docID string, indexes []int) error DeleteMsgsInOneDocByIndex(ctx context.Context, docID string, indexes []int) error
MarkSingleChatMsgsAsRead(ctx context.Context, userID string, docID string, indexes []int64) error MarkSingleChatMsgsAsRead(ctx context.Context, userID string, docID string, indexes []int64) error
SearchMessage(ctx context.Context, req *msg.SearchMessageReq) (int32, []*model.MsgInfoModel, error) SearchMessage(ctx context.Context, req *msg.SearchMessageReq) (int64, []*model.MsgInfoModel, error)
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) 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) 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) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string)
+43
View File
@@ -14,6 +14,11 @@
package rpccache package rpccache
import (
"github.com/openimsdk/tools/errs"
"google.golang.org/protobuf/proto"
)
func newListMap[V comparable](values []V, err error) (*listMap[V], error) { func newListMap[V comparable](values []V, err error) (*listMap[V], error) {
if err != nil { if err != nil {
return nil, err return nil, err
@@ -32,3 +37,41 @@ type listMap[V comparable] struct {
List []V List []V
Map map[V]struct{} Map map[V]struct{}
} }
func respProtoMarshal(resp proto.Message, err error) ([]byte, error) {
if err != nil {
return nil, err
}
return proto.Marshal(resp)
}
func cacheUnmarshal[V any](resp []byte, err error) (*V, error) {
if err != nil {
return nil, err
}
var val V
if err := proto.Unmarshal(resp, any(&val).(proto.Message)); err != nil {
return nil, errs.WrapMsg(err, "local cache proto.Unmarshal error")
}
return &val, nil
}
type cacheProto[V any] struct{}
func (cacheProto[V]) Marshal(resp *V, err error) ([]byte, error) {
if err != nil {
return nil, err
}
return proto.Marshal(any(resp).(proto.Message))
}
func (cacheProto[V]) Unmarshal(resp []byte, err error) (*V, error) {
if err != nil {
return nil, err
}
var val V
if err := proto.Unmarshal(resp, any(&val).(proto.Message)); err != nil {
return nil, errs.WrapMsg(err, "local cache proto.Unmarshal error")
}
return &val, nil
}
+38 -17
View File
@@ -23,6 +23,7 @@ import (
pbconversation "github.com/openimsdk/protocol/conversation" pbconversation "github.com/openimsdk/protocol/conversation"
"github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log" "github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/utils/datautil"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@@ -36,7 +37,7 @@ func NewConversationLocalCache(client rpcclient.ConversationRpcClient, localCach
log.ZDebug(context.Background(), "ConversationLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable()) log.ZDebug(context.Background(), "ConversationLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable())
x := &ConversationLocalCache{ x := &ConversationLocalCache{
client: client, client: client,
local: localcache.New[any]( local: localcache.New[[]byte](
localcache.WithLocalSlotNum(lc.SlotNum), localcache.WithLocalSlotNum(lc.SlotNum),
localcache.WithLocalSlotSize(lc.SlotSize), localcache.WithLocalSlotSize(lc.SlotSize),
localcache.WithLinkSlotNum(lc.SlotNum), localcache.WithLinkSlotNum(lc.SlotNum),
@@ -52,21 +53,30 @@ func NewConversationLocalCache(client rpcclient.ConversationRpcClient, localCach
type ConversationLocalCache struct { type ConversationLocalCache struct {
client rpcclient.ConversationRpcClient client rpcclient.ConversationRpcClient
local localcache.Cache[any] local localcache.Cache[[]byte]
} }
func (c *ConversationLocalCache) GetConversationIDs(ctx context.Context, ownerUserID string) (val []string, err error) { func (c *ConversationLocalCache) GetConversationIDs(ctx context.Context, ownerUserID string) (val []string, err error) {
log.ZDebug(ctx, "ConversationLocalCache GetConversationIDs req", "ownerUserID", ownerUserID) resp, err := c.getConversationIDs(ctx, ownerUserID)
if err != nil {
return nil, err
}
return resp.ConversationIDs, nil
}
func (c *ConversationLocalCache) getConversationIDs(ctx context.Context, ownerUserID string) (val *pbconversation.GetConversationIDsResp, err error) {
log.ZDebug(ctx, "ConversationLocalCache getConversationIDs req", "ownerUserID", ownerUserID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "ConversationLocalCache GetConversationIDs return", "value", val) log.ZDebug(ctx, "ConversationLocalCache getConversationIDs return", "ownerUserID", ownerUserID, "value", val)
} else { } else {
log.ZError(ctx, "ConversationLocalCache GetConversationIDs return", err) log.ZError(ctx, "ConversationLocalCache getConversationIDs return", err, "ownerUserID", ownerUserID)
} }
}() }()
return localcache.AnyValue[[]string](c.local.Get(ctx, cachekey.GetConversationIDsKey(ownerUserID), func(ctx context.Context) (any, error) { var cache cacheProto[pbconversation.GetConversationIDsResp]
log.ZDebug(ctx, "ConversationLocalCache GetConversationIDs rpc", "ownerUserID", ownerUserID) return cache.Unmarshal(c.local.Get(ctx, cachekey.GetConversationIDsKey(ownerUserID), func(ctx context.Context) ([]byte, error) {
return c.client.GetConversationIDs(ctx, ownerUserID) log.ZDebug(ctx, "ConversationLocalCache getConversationIDs rpc", "ownerUserID", ownerUserID)
return cache.Marshal(c.client.Client.GetConversationIDs(ctx, &pbconversation.GetConversationIDsReq{UserID: ownerUserID}))
})) }))
} }
@@ -74,14 +84,15 @@ func (c *ConversationLocalCache) GetConversation(ctx context.Context, userID, co
log.ZDebug(ctx, "ConversationLocalCache GetConversation req", "userID", userID, "conversationID", conversationID) log.ZDebug(ctx, "ConversationLocalCache GetConversation req", "userID", userID, "conversationID", conversationID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "ConversationLocalCache GetConversation return", "value", val) log.ZDebug(ctx, "ConversationLocalCache GetConversation return", "userID", userID, "conversationID", conversationID, "value", val)
} else { } else {
log.ZError(ctx, "ConversationLocalCache GetConversation return", err) log.ZError(ctx, "ConversationLocalCache GetConversation return", err, "userID", userID, "conversationID", conversationID)
} }
}() }()
return localcache.AnyValue[*pbconversation.Conversation](c.local.Get(ctx, cachekey.GetConversationKey(userID, conversationID), func(ctx context.Context) (any, error) { var cache cacheProto[pbconversation.Conversation]
return cache.Unmarshal(c.local.Get(ctx, cachekey.GetConversationKey(userID, conversationID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "ConversationLocalCache GetConversation rpc", "userID", userID, "conversationID", conversationID) log.ZDebug(ctx, "ConversationLocalCache GetConversation rpc", "userID", userID, "conversationID", conversationID)
return c.client.GetConversation(ctx, userID, conversationID) return cache.Marshal(c.client.GetConversation(ctx, userID, conversationID))
})) }))
} }
@@ -126,9 +137,19 @@ func (c *ConversationLocalCache) GetConversations(ctx context.Context, ownerUser
return conversations, nil return conversations, nil
} }
func (c *ConversationLocalCache) getConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) (*listMap[string], error) { func (c *ConversationLocalCache) getConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) (val *pbconversation.GetConversationNotReceiveMessageUserIDsResp, err error) {
return localcache.AnyValue[*listMap[string]](c.local.Get(ctx, cachekey.GetConversationNotReceiveMessageUserIDsKey(conversationID), func(ctx context.Context) (any, error) { log.ZDebug(ctx, "ConversationLocalCache getConversationNotReceiveMessageUserIDs req", "conversationID", conversationID)
return newListMap(c.client.GetConversationNotReceiveMessageUserIDs(ctx, conversationID)) defer func() {
if err == nil {
log.ZDebug(ctx, "ConversationLocalCache getConversationNotReceiveMessageUserIDs return", "conversationID", conversationID, "value", val)
} else {
log.ZError(ctx, "ConversationLocalCache getConversationNotReceiveMessageUserIDs return", err, "conversationID", conversationID)
}
}()
var cache cacheProto[pbconversation.GetConversationNotReceiveMessageUserIDsResp]
return cache.Unmarshal(c.local.Get(ctx, cachekey.GetConversationNotReceiveMessageUserIDsKey(conversationID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "ConversationLocalCache getConversationNotReceiveMessageUserIDs rpc", "conversationID", conversationID)
return cache.Marshal(c.client.Client.GetConversationNotReceiveMessageUserIDs(ctx, &pbconversation.GetConversationNotReceiveMessageUserIDsReq{ConversationID: conversationID}))
})) }))
} }
@@ -137,7 +158,7 @@ func (c *ConversationLocalCache) GetConversationNotReceiveMessageUserIDs(ctx con
if err != nil { if err != nil {
return nil, err return nil, err
} }
return res.List, nil return res.UserIDs, nil
} }
func (c *ConversationLocalCache) GetConversationNotReceiveMessageUserIDMap(ctx context.Context, conversationID string) (map[string]struct{}, error) { func (c *ConversationLocalCache) GetConversationNotReceiveMessageUserIDMap(ctx context.Context, conversationID string) (map[string]struct{}, error) {
@@ -145,5 +166,5 @@ func (c *ConversationLocalCache) GetConversationNotReceiveMessageUserIDMap(ctx c
if err != nil { if err != nil {
return nil, err return nil, err
} }
return res.Map, nil return datautil.SliceSet(res.UserIDs), nil
} }
+36 -16
View File
@@ -16,7 +16,8 @@ package rpccache
import ( import (
"context" "context"
cachekey2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
"github.com/openimsdk/protocol/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/localcache" "github.com/openimsdk/open-im-server/v3/pkg/localcache"
@@ -30,7 +31,7 @@ func NewFriendLocalCache(client rpcclient.FriendRpcClient, localCache *config.Lo
log.ZDebug(context.Background(), "FriendLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable()) log.ZDebug(context.Background(), "FriendLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable())
x := &FriendLocalCache{ x := &FriendLocalCache{
client: client, client: client,
local: localcache.New[any]( local: localcache.New[[]byte](
localcache.WithLocalSlotNum(lc.SlotNum), localcache.WithLocalSlotNum(lc.SlotNum),
localcache.WithLocalSlotSize(lc.SlotSize), localcache.WithLocalSlotSize(lc.SlotSize),
localcache.WithLinkSlotNum(lc.SlotNum), localcache.WithLinkSlotNum(lc.SlotNum),
@@ -46,36 +47,55 @@ func NewFriendLocalCache(client rpcclient.FriendRpcClient, localCache *config.Lo
type FriendLocalCache struct { type FriendLocalCache struct {
client rpcclient.FriendRpcClient client rpcclient.FriendRpcClient
local localcache.Cache[any] local localcache.Cache[[]byte]
} }
func (f *FriendLocalCache) IsFriend(ctx context.Context, possibleFriendUserID, userID string) (val bool, err error) { func (f *FriendLocalCache) IsFriend(ctx context.Context, possibleFriendUserID, userID string) (val bool, err error) {
log.ZDebug(ctx, "FriendLocalCache IsFriend req", "possibleFriendUserID", possibleFriendUserID, "userID", userID) res, err := f.isFriend(ctx, possibleFriendUserID, userID)
if err != nil {
return false, err
}
return res.InUser1Friends, nil
}
func (f *FriendLocalCache) isFriend(ctx context.Context, possibleFriendUserID, userID string) (val *relation.IsFriendResp, err error) {
log.ZDebug(ctx, "FriendLocalCache isFriend req", "possibleFriendUserID", possibleFriendUserID, "userID", userID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "FriendLocalCache IsFriend return", "value", val) log.ZDebug(ctx, "FriendLocalCache isFriend return", "possibleFriendUserID", possibleFriendUserID, "userID", userID, "value", val)
} else { } else {
log.ZError(ctx, "FriendLocalCache IsFriend return", err) log.ZError(ctx, "FriendLocalCache isFriend return", err, "possibleFriendUserID", possibleFriendUserID, "userID", userID)
} }
}() }()
return localcache.AnyValue[bool](f.local.GetLink(ctx, cachekey2.GetIsFriendKey(possibleFriendUserID, userID), func(ctx context.Context) (any, error) { var cache cacheProto[relation.IsFriendResp]
log.ZDebug(ctx, "FriendLocalCache IsFriend rpc", "possibleFriendUserID", possibleFriendUserID, "userID", userID) return cache.Unmarshal(f.local.GetLink(ctx, cachekey.GetIsFriendKey(possibleFriendUserID, userID), func(ctx context.Context) ([]byte, error) {
return f.client.IsFriend(ctx, possibleFriendUserID, userID) log.ZDebug(ctx, "FriendLocalCache isFriend rpc", "possibleFriendUserID", possibleFriendUserID, "userID", userID)
}, cachekey2.GetFriendIDsKey(possibleFriendUserID))) return cache.Marshal(f.client.Client.IsFriend(ctx, &relation.IsFriendReq{UserID1: userID, UserID2: possibleFriendUserID}))
}, cachekey.GetFriendIDsKey(possibleFriendUserID)))
} }
// IsBlack possibleBlackUserID selfUserID. // IsBlack possibleBlackUserID selfUserID.
func (f *FriendLocalCache) IsBlack(ctx context.Context, possibleBlackUserID, userID string) (val bool, err error) { func (f *FriendLocalCache) IsBlack(ctx context.Context, possibleBlackUserID, userID string) (val bool, err error) {
log.ZDebug(ctx, "FriendLocalCache IsBlack req", "possibleBlackUserID", possibleBlackUserID, "userID", userID) res, err := f.isBlack(ctx, possibleBlackUserID, userID)
if err != nil {
return false, err
}
return res.InUser2Blacks, nil
}
// IsBlack possibleBlackUserID selfUserID.
func (f *FriendLocalCache) isBlack(ctx context.Context, possibleBlackUserID, userID string) (val *relation.IsBlackResp, err error) {
log.ZDebug(ctx, "FriendLocalCache isBlack req", "possibleBlackUserID", possibleBlackUserID, "userID", userID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "FriendLocalCache IsBlack return", "value", val) log.ZDebug(ctx, "FriendLocalCache isBlack return", "possibleBlackUserID", possibleBlackUserID, "userID", userID, "value", val)
} else { } else {
log.ZError(ctx, "FriendLocalCache IsBlack return", err) log.ZError(ctx, "FriendLocalCache isBlack return", err, "possibleBlackUserID", possibleBlackUserID, "userID", userID)
} }
}() }()
return localcache.AnyValue[bool](f.local.GetLink(ctx, cachekey2.GetIsBlackIDsKey(possibleBlackUserID, userID), func(ctx context.Context) (any, error) { var cache cacheProto[relation.IsBlackResp]
return cache.Unmarshal(f.local.GetLink(ctx, cachekey.GetIsBlackIDsKey(possibleBlackUserID, userID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "FriendLocalCache IsBlack rpc", "possibleBlackUserID", possibleBlackUserID, "userID", userID) log.ZDebug(ctx, "FriendLocalCache IsBlack rpc", "possibleBlackUserID", possibleBlackUserID, "userID", userID)
return f.client.IsBlack(ctx, possibleBlackUserID, userID) return cache.Marshal(f.client.Client.IsBlack(ctx, &relation.IsBlackReq{UserID1: possibleBlackUserID, UserID2: userID}))
}, cachekey2.GetBlackIDsKey(userID))) }, cachekey.GetBlackIDsKey(userID)))
} }
+22 -17
View File
@@ -17,6 +17,8 @@ package rpccache
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
"github.com/openimsdk/protocol/group"
"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/config"
"github.com/openimsdk/open-im-server/v3/pkg/localcache" "github.com/openimsdk/open-im-server/v3/pkg/localcache"
@@ -32,7 +34,7 @@ func NewGroupLocalCache(client rpcclient.GroupRpcClient, localCache *config.Loca
log.ZDebug(context.Background(), "GroupLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable()) log.ZDebug(context.Background(), "GroupLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable())
x := &GroupLocalCache{ x := &GroupLocalCache{
client: client, client: client,
local: localcache.New[any]( local: localcache.New[[]byte](
localcache.WithLocalSlotNum(lc.SlotNum), localcache.WithLocalSlotNum(lc.SlotNum),
localcache.WithLocalSlotSize(lc.SlotSize), localcache.WithLocalSlotSize(lc.SlotSize),
localcache.WithLinkSlotNum(lc.SlotNum), localcache.WithLinkSlotNum(lc.SlotNum),
@@ -48,21 +50,22 @@ func NewGroupLocalCache(client rpcclient.GroupRpcClient, localCache *config.Loca
type GroupLocalCache struct { type GroupLocalCache struct {
client rpcclient.GroupRpcClient client rpcclient.GroupRpcClient
local localcache.Cache[any] local localcache.Cache[[]byte]
} }
func (g *GroupLocalCache) getGroupMemberIDs(ctx context.Context, groupID string) (val *listMap[string], err error) { func (g *GroupLocalCache) getGroupMemberIDs(ctx context.Context, groupID string) (val *group.GetGroupMemberUserIDsResp, err error) {
log.ZDebug(ctx, "GroupLocalCache getGroupMemberIDs req", "groupID", groupID) log.ZDebug(ctx, "GroupLocalCache getGroupMemberIDs req", "groupID", groupID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "GroupLocalCache getGroupMemberIDs return", "value", val) log.ZDebug(ctx, "GroupLocalCache getGroupMemberIDs return", "groupID", groupID, "value", val)
} else { } else {
log.ZError(ctx, "GroupLocalCache getGroupMemberIDs return", err) log.ZError(ctx, "GroupLocalCache getGroupMemberIDs return", err, "groupID", groupID)
} }
}() }()
return localcache.AnyValue[*listMap[string]](g.local.Get(ctx, cachekey.GetGroupMemberIDsKey(groupID), func(ctx context.Context) (any, error) { var cache cacheProto[group.GetGroupMemberUserIDsResp]
return cache.Unmarshal(g.local.Get(ctx, cachekey.GetGroupMemberIDsKey(groupID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "GroupLocalCache getGroupMemberIDs rpc", "groupID", groupID) log.ZDebug(ctx, "GroupLocalCache getGroupMemberIDs rpc", "groupID", groupID)
return newListMap(g.client.GetGroupMemberIDs(ctx, groupID)) return cache.Marshal(g.client.Client.GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{GroupID: groupID}))
})) }))
} }
@@ -70,14 +73,15 @@ func (g *GroupLocalCache) GetGroupMember(ctx context.Context, groupID, userID st
log.ZDebug(ctx, "GroupLocalCache GetGroupInfo req", "groupID", groupID, "userID", userID) log.ZDebug(ctx, "GroupLocalCache GetGroupInfo req", "groupID", groupID, "userID", userID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "GroupLocalCache GetGroupInfo return", "value", val) log.ZDebug(ctx, "GroupLocalCache GetGroupInfo return", "groupID", groupID, "userID", userID, "value", val)
} else { } else {
log.ZError(ctx, "GroupLocalCache GetGroupInfo return", err) log.ZError(ctx, "GroupLocalCache GetGroupInfo return", err, "groupID", groupID, "userID", userID)
} }
}() }()
return localcache.AnyValue[*sdkws.GroupMemberFullInfo](g.local.Get(ctx, cachekey.GetGroupMemberInfoKey(groupID, userID), func(ctx context.Context) (any, error) { var cache cacheProto[sdkws.GroupMemberFullInfo]
return cache.Unmarshal(g.local.Get(ctx, cachekey.GetGroupMemberInfoKey(groupID, userID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "GroupLocalCache GetGroupInfo rpc", "groupID", groupID, "userID", userID) log.ZDebug(ctx, "GroupLocalCache GetGroupInfo rpc", "groupID", groupID, "userID", userID)
return g.client.GetGroupMemberCache(ctx, groupID, userID) return cache.Marshal(g.client.GetGroupMemberCache(ctx, groupID, userID))
})) }))
} }
@@ -85,14 +89,15 @@ func (g *GroupLocalCache) GetGroupInfo(ctx context.Context, groupID string) (val
log.ZDebug(ctx, "GroupLocalCache GetGroupInfo req", "groupID", groupID) log.ZDebug(ctx, "GroupLocalCache GetGroupInfo req", "groupID", groupID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "GroupLocalCache GetGroupInfo return", "value", val) log.ZDebug(ctx, "GroupLocalCache GetGroupInfo return", "groupID", groupID, "value", val)
} else { } else {
log.ZError(ctx, "GroupLocalCache GetGroupInfo return", err) log.ZError(ctx, "GroupLocalCache GetGroupInfo return", err, "groupID", groupID)
} }
}() }()
return localcache.AnyValue[*sdkws.GroupInfo](g.local.Get(ctx, cachekey.GetGroupInfoKey(groupID), func(ctx context.Context) (any, error) { var cache cacheProto[sdkws.GroupInfo]
return cache.Unmarshal(g.local.Get(ctx, cachekey.GetGroupInfoKey(groupID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "GroupLocalCache GetGroupInfo rpc", "groupID", groupID) log.ZDebug(ctx, "GroupLocalCache GetGroupInfo rpc", "groupID", groupID)
return g.client.GetGroupInfoCache(ctx, groupID) return cache.Marshal(g.client.GetGroupInfoCache(ctx, groupID))
})) }))
} }
@@ -101,7 +106,7 @@ func (g *GroupLocalCache) GetGroupMemberIDs(ctx context.Context, groupID string)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return res.List, nil return res.UserIDs, nil
} }
func (g *GroupLocalCache) GetGroupMemberIDMap(ctx context.Context, groupID string) (map[string]struct{}, error) { func (g *GroupLocalCache) GetGroupMemberIDMap(ctx context.Context, groupID string) (map[string]struct{}, error) {
@@ -109,7 +114,7 @@ func (g *GroupLocalCache) GetGroupMemberIDMap(ctx context.Context, groupID strin
if err != nil { if err != nil {
return nil, err return nil, err
} }
return res.Map, nil return datautil.SliceSet(res.UserIDs), nil
} }
func (g *GroupLocalCache) GetGroupInfos(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) { func (g *GroupLocalCache) GetGroupInfos(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) {
+53 -37
View File
@@ -28,7 +28,7 @@ func NewOnlineCache(user rpcclient.UserRpcClient, group *GroupLocalCache, rdb re
for message := range rdb.Subscribe(ctx, cachekey.OnlineChannel).Channel() { for message := range rdb.Subscribe(ctx, cachekey.OnlineChannel).Channel() {
userID, platformIDs, err := useronline.ParseUserOnlineStatus(message.Payload) userID, platformIDs, err := useronline.ParseUserOnlineStatus(message.Payload)
if err != nil { if err != nil {
log.ZError(ctx, "OnlineCache redis subscribe parseUserOnlineStatus", err, "payload", message.Payload, "channel", message.Channel) log.ZError(ctx, "OnlineCache setUserOnline redis subscribe parseUserOnlineStatus", err, "payload", message.Payload, "channel", message.Channel)
continue continue
} }
storageCache := x.setUserOnline(userID, platformIDs) storageCache := x.setUserOnline(userID, platformIDs)
@@ -47,53 +47,69 @@ type OnlineCache struct {
local lru.LRU[string, []int32] local lru.LRU[string, []int32]
} }
func (o *OnlineCache) GetUserOnlinePlatform(ctx context.Context, userID string) ([]int32, error) { func (o *OnlineCache) getUserOnlinePlatform(ctx context.Context, userID string) ([]int32, error) {
return o.local.Get(userID, func() ([]int32, error) { platformIDs, err := o.local.Get(userID, func() ([]int32, error) {
return o.user.GetUserOnlinePlatform(ctx, userID) return o.user.GetUserOnlinePlatform(ctx, userID)
}) })
if err != nil {
log.ZError(ctx, "OnlineCache GetUserOnlinePlatform", err, "userID", userID)
return nil, err
}
log.ZDebug(ctx, "OnlineCache GetUserOnlinePlatform", "userID", userID, "platformIDs", platformIDs)
return platformIDs, nil
}
func (o *OnlineCache) GetUserOnlinePlatform(ctx context.Context, userID string) ([]int32, error) {
platformIDs, err := o.getUserOnlinePlatform(ctx, userID)
if err != nil {
return nil, err
}
tmp := make([]int32, len(platformIDs))
copy(tmp, platformIDs)
return platformIDs, nil
} }
func (o *OnlineCache) GetUserOnline(ctx context.Context, userID string) (bool, error) { func (o *OnlineCache) GetUserOnline(ctx context.Context, userID string) (bool, error) {
platformIDs, err := o.GetUserOnlinePlatform(ctx, userID) platformIDs, err := o.getUserOnlinePlatform(ctx, userID)
if err != nil { if err != nil {
return false, err return false, err
} }
return len(platformIDs) > 0, nil return len(platformIDs) > 0, nil
} }
func (o *OnlineCache) GetUsersOnline(ctx context.Context, userIDs []string) ([]string, error) { //func (o *OnlineCache) GetUsersOnline(ctx context.Context, userIDs []string) ([]string, error) {
onlineUserIDs := make([]string, 0, len(userIDs)) // onlineUserIDs := make([]string, 0, len(userIDs))
for _, userID := range userIDs { // for _, userID := range userIDs {
online, err := o.GetUserOnline(ctx, userID) // online, err := o.GetUserOnline(ctx, userID)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
if online { // if online {
onlineUserIDs = append(onlineUserIDs, userID) // onlineUserIDs = append(onlineUserIDs, userID)
} // }
} // }
log.ZDebug(ctx, "OnlineCache GetUsersOnline", "userIDs", userIDs, "onlineUserIDs", onlineUserIDs) // log.ZDebug(ctx, "OnlineCache GetUsersOnline", "userIDs", userIDs, "onlineUserIDs", onlineUserIDs)
return onlineUserIDs, nil // return onlineUserIDs, nil
} //}
//
func (o *OnlineCache) GetGroupOnline(ctx context.Context, groupID string) ([]string, error) { //func (o *OnlineCache) GetGroupOnline(ctx context.Context, groupID string) ([]string, error) {
userIDs, err := o.group.GetGroupMemberIDs(ctx, groupID) // userIDs, err := o.group.GetGroupMemberIDs(ctx, groupID)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
var onlineUserIDs []string // var onlineUserIDs []string
for _, userID := range userIDs { // for _, userID := range userIDs {
online, err := o.GetUserOnline(ctx, userID) // online, err := o.GetUserOnline(ctx, userID)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
if online { // if online {
onlineUserIDs = append(onlineUserIDs, userID) // onlineUserIDs = append(onlineUserIDs, userID)
} // }
} // }
log.ZDebug(ctx, "OnlineCache GetGroupOnline", "groupID", groupID, "onlineUserIDs", onlineUserIDs, "allUserID", userIDs) // log.ZDebug(ctx, "OnlineCache GetGroupOnline", "groupID", groupID, "onlineUserIDs", onlineUserIDs, "allUserID", userIDs)
return onlineUserIDs, nil // return onlineUserIDs, nil
} //}
func (o *OnlineCache) setUserOnline(userID string, platformIDs []int32) bool { func (o *OnlineCache) setUserOnline(userID string, platformIDs []int32) bool {
return o.local.SetHas(userID, platformIDs) return o.local.SetHas(userID, platformIDs)
+21 -26
View File
@@ -16,12 +16,12 @@ package rpccache
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
"github.com/openimsdk/open-im-server/v3/pkg/localcache" "github.com/openimsdk/open-im-server/v3/pkg/localcache"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/protocol/sdkws" "github.com/openimsdk/protocol/sdkws"
"github.com/openimsdk/protocol/user"
"github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log" "github.com/openimsdk/tools/log"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
@@ -32,7 +32,7 @@ func NewUserLocalCache(client rpcclient.UserRpcClient, localCache *config.LocalC
log.ZDebug(context.Background(), "UserLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable()) log.ZDebug(context.Background(), "UserLocalCache", "topic", lc.Topic, "slotNum", lc.SlotNum, "slotSize", lc.SlotSize, "enable", lc.Enable())
x := &UserLocalCache{ x := &UserLocalCache{
client: client, client: client,
local: localcache.New[any]( local: localcache.New[[]byte](
localcache.WithLocalSlotNum(lc.SlotNum), localcache.WithLocalSlotNum(lc.SlotNum),
localcache.WithLocalSlotSize(lc.SlotSize), localcache.WithLocalSlotSize(lc.SlotSize),
localcache.WithLinkSlotNum(lc.SlotNum), localcache.WithLinkSlotNum(lc.SlotNum),
@@ -48,7 +48,7 @@ func NewUserLocalCache(client rpcclient.UserRpcClient, localCache *config.LocalC
type UserLocalCache struct { type UserLocalCache struct {
client rpcclient.UserRpcClient client rpcclient.UserRpcClient
local localcache.Cache[any] local localcache.Cache[[]byte]
} }
func (u *UserLocalCache) GetUserInfo(ctx context.Context, userID string) (val *sdkws.UserInfo, err error) { func (u *UserLocalCache) GetUserInfo(ctx context.Context, userID string) (val *sdkws.UserInfo, err error) {
@@ -60,24 +60,34 @@ func (u *UserLocalCache) GetUserInfo(ctx context.Context, userID string) (val *s
log.ZError(ctx, "UserLocalCache GetUserInfo return", err) log.ZError(ctx, "UserLocalCache GetUserInfo return", err)
} }
}() }()
return localcache.AnyValue[*sdkws.UserInfo](u.local.Get(ctx, cachekey.GetUserInfoKey(userID), func(ctx context.Context) (any, error) { var cache cacheProto[sdkws.UserInfo]
return cache.Unmarshal(u.local.Get(ctx, cachekey.GetUserInfoKey(userID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "UserLocalCache GetUserInfo rpc", "userID", userID) log.ZDebug(ctx, "UserLocalCache GetUserInfo rpc", "userID", userID)
return u.client.GetUserInfo(ctx, userID) return cache.Marshal(u.client.GetUserInfo(ctx, userID))
})) }))
} }
func (u *UserLocalCache) GetUserGlobalMsgRecvOpt(ctx context.Context, userID string) (val int32, err error) { func (u *UserLocalCache) GetUserGlobalMsgRecvOpt(ctx context.Context, userID string) (val int32, err error) {
log.ZDebug(ctx, "UserLocalCache GetUserGlobalMsgRecvOpt req", "userID", userID) resp, err := u.getUserGlobalMsgRecvOpt(ctx, userID)
if err != nil {
return 0, err
}
return resp.GlobalRecvMsgOpt, nil
}
func (u *UserLocalCache) getUserGlobalMsgRecvOpt(ctx context.Context, userID string) (val *user.GetGlobalRecvMessageOptResp, err error) {
log.ZDebug(ctx, "UserLocalCache getUserGlobalMsgRecvOpt req", "userID", userID)
defer func() { defer func() {
if err == nil { if err == nil {
log.ZDebug(ctx, "UserLocalCache GetUserGlobalMsgRecvOpt return", "value", val) log.ZDebug(ctx, "UserLocalCache getUserGlobalMsgRecvOpt return", "value", val)
} else { } else {
log.ZError(ctx, "UserLocalCache GetUserGlobalMsgRecvOpt return", err) log.ZError(ctx, "UserLocalCache getUserGlobalMsgRecvOpt return", err)
} }
}() }()
return localcache.AnyValue[int32](u.local.Get(ctx, cachekey.GetUserGlobalRecvMsgOptKey(userID), func(ctx context.Context) (any, error) { var cache cacheProto[user.GetGlobalRecvMessageOptResp]
return cache.Unmarshal(u.local.Get(ctx, cachekey.GetUserGlobalRecvMsgOptKey(userID), func(ctx context.Context) ([]byte, error) {
log.ZDebug(ctx, "UserLocalCache GetUserGlobalMsgRecvOpt rpc", "userID", userID) log.ZDebug(ctx, "UserLocalCache GetUserGlobalMsgRecvOpt rpc", "userID", userID)
return u.client.GetUserGlobalMsgRecvOpt(ctx, userID) return cache.Marshal(u.client.Client.GetGlobalRecvMessageOpt(ctx, &user.GetGlobalRecvMessageOptReq{UserID: userID}))
})) }))
} }
@@ -110,18 +120,3 @@ func (u *UserLocalCache) GetUsersInfoMap(ctx context.Context, userIDs []string)
} }
return users, nil return users, nil
} }
//func (u *UserLocalCache) GetUserOnlinePlatform(ctx context.Context, userID string) (val []int32, err error) {
// log.ZDebug(ctx, "UserLocalCache GetUserOnlinePlatform req", "userID", userID)
// defer func() {
// if err == nil {
// log.ZDebug(ctx, "UserLocalCache GetUserOnlinePlatform return", "value", val)
// } else {
// log.ZError(ctx, "UserLocalCache GetUserOnlinePlatform return", err)
// }
// }()
// return localcache.AnyValue[[]int32](u.local.Get(ctx, cachekey.GetOnlineKey(userID), func(ctx context.Context) (any, error) {
// log.ZDebug(ctx, "UserLocalCache GetUserGlobalMsgRecvOpt rpc", "userID", userID)
// return u.client.GetUserGlobalMsgRecvOpt(ctx, userID)
// }))
//}
+9 -1
View File
@@ -82,7 +82,7 @@ func (c *ConversationRpcClient) SetConversations(ctx context.Context, userIDs []
return err return err
} }
func (c *ConversationRpcClient) UpdateConversations(ctx context.Context, conversation *pbconversation.UpdateConversationReq) error { func (c *ConversationRpcClient) UpdateConversation(ctx context.Context, conversation *pbconversation.UpdateConversationReq) error {
_, err := c.Client.UpdateConversation(ctx, conversation) _, err := c.Client.UpdateConversation(ctx, conversation)
return err return err
} }
@@ -146,3 +146,11 @@ func (c *ConversationRpcClient) GetConversationNotReceiveMessageUserIDs(ctx cont
} }
return resp.UserIDs, nil return resp.UserIDs, nil
} }
func (c *ConversationRpcClient) GetConversationsNeedDestructMsgs(ctx context.Context) ([]*pbconversation.Conversation, error) {
resp, err := c.Client.GetConversationsNeedDestructMsgs(ctx, &pbconversation.GetConversationsNeedDestructMsgsReq{})
if err != nil {
return nil, err
}
return resp.Conversations, nil
}
+4
View File
@@ -324,6 +324,10 @@ func (s *NotificationSender) send(ctx context.Context, sendID, recvID string, co
options := config.GetOptionsByNotification(optionsConfig) options := config.GetOptionsByNotification(optionsConfig)
s.SetOptionsByContentType(ctx, options, contentType) s.SetOptionsByContentType(ctx, options, contentType)
msg.Options = options msg.Options = options
// fill Notification OfflinePush by config
offlineInfo.Title = optionsConfig.OfflinePush.Title
offlineInfo.Desc = optionsConfig.OfflinePush.Desc
offlineInfo.Ex = optionsConfig.OfflinePush.Ext
msg.OfflinePushInfo = &offlineInfo msg.OfflinePushInfo = &offlineInfo
req.MsgData = &msg req.MsgData = &msg
_, err = s.sendMsg(ctx, &req) _, err = s.sendMsg(ctx, &req)
+1
View File
@@ -0,0 +1 @@
3.8.0
+6
View File
@@ -0,0 +1,6 @@
package version
import _ "embed"
//go:embed version
var Version string