From a04c9d99ae42773be244458af2ff6159e6a465fc Mon Sep 17 00:00:00 2001
From: "fengyun.rui"
Date: Tue, 7 Nov 2023 10:42:54 +0800
Subject: [PATCH] refactor: client in msggateway (#1343)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* refactor: clietn in msggateway
Signed-off-by: rfyiamcool
* perf: add sync.pool for req object
Signed-off-by: rfyiamcool
---------
Signed-off-by: rfyiamcool
feat: use dummy pusher by default (#1349)
Add Prometheus monitoring function (#1337)
* Code adaptation k8s: service discovery and registration adaptation, configuration adaptation
* Initial submission of the help charts script for openim API
* change the help charts script
* change the help charts script
* change helm chart codes
* change dockerfiles script
* change chart script:add configmap mounts
* change chart script:change repository
* change chart script:msggateway add one service
* change config.yaml
* roll back some config values
* change chart script:change Ingress rule with a rewrite annotation
* add mysql charts scrible
* change chart script:add mysql.config.yaml
* add nfs provisioner charts
* change chart script:add nfs.config.yaml
* add ingress-nginx charts
* change chart script:add ingress-nginx.config.yaml
* add redis &mongodb charts
* add kafka&minio charts
* change chart script:change redis.values.yaml
* change chart script:add redis.config.yaml
* change chart script:change redis.config.yaml
* change chart script:change mongodb.value.yaml
* change chart script:change mongodb.value.yaml
* change chart script:add mongodb.config.yaml
* change chart script:change minio.values.yaml
* change chart script:add minio.config.yaml
* change chart script:change kafka.values.yaml
* change chart script:add kafka.config.yaml
* change chart script:change services.config.yaml
* bug fix:Delete websocket's Port restrictions
* bug fix:change port value
* change chart script:Submit a stable version script
* fix bug:Implement option interface
* fix bug:change K8sDR.Register
* change config.yaml
* change chats script:minio service add ingress
* change chats script:minio service add ingress
* change chats script:kafka.replicaCount=3& change minio.api ingress
* delete change chats script
* change config.yaml
* change openim.yaml
* merge go.sum
* Add monitoring function and struct for Prometheus on gin and GRPC
* Add GRPC and gin server monitoring logic
* Add GRPC and gin server monitoring logic2
* Add GRPC and gin server monitoring logic3
* Add GRPC and gin server monitoring logic4
* Add GRPC and gin server monitoring logic5
* Add GRPC and gin server monitoring logic6
* Add GRPC and gin server monitoring logic7
* delete:old monitoring code
* add for test
* fix bug:change packname
* fix bug:delete getPromPort funciton
* fix bug:delete getPromPort funciton
* fix bug:change logs
* fix bug:change registerName logic in GetGrpcCusMetrics function
* add getPrometheus url api
* fix:config path logic
* fix:prometheus enable function
* fix:prometheus enable function
* fix:transfer Multi process monitoring logic
* del:del not using manifest
* fix:openim-msgtransfer.sh
* fix:openim-msgtransfer.sh
---------
Co-authored-by: lin.huang
Co-authored-by: Xinwei Xiong <3293172751@qq.com>
fix: initiateUpload sign list number (#1358)
* optimize scheduled deletion
* optimize scheduled deletion
* optimize scheduled deletion
* optimize scheduled deletion
* minio cache
* fix: conflicts
* feat: minio cache
* feat: cache optimize
* feat: cache optimize
* feat: cache optimize
* feat: cache optimize
* feat: cache optimize
* fix: initiateUpload sign list number
fix: msg pull change and fcm redis flag fix. (#1367)
* fix: to start im or chat, ZooKeeper must be started first.
* fix: msg gateway start output err info
Signed-off-by: Gordon <1432970085@qq.com>
* fix: msg gateway start output err info
Signed-off-by: Gordon <1432970085@qq.com>
* chore: package path changes
Signed-off-by: withchao <993506633@qq.com>
* fix: go mod update
Signed-off-by: Gordon <1432970085@qq.com>
* fix: token update
Signed-off-by: Gordon <1432970085@qq.com>
* chore: package path changes
Signed-off-by: withchao <993506633@qq.com>
* chore: package path changes
Signed-off-by: withchao <993506633@qq.com>
* fix: token update
Signed-off-by: Gordon <1432970085@qq.com>
* fix: token update
Signed-off-by: Gordon <1432970085@qq.com>
* fix: token update
Signed-off-by: Gordon <1432970085@qq.com>
* fix: token update
Signed-off-by: Gordon <1432970085@qq.com>
* fix: token update
Signed-off-by: Gordon <1432970085@qq.com>
* fix: token update
Signed-off-by: Gordon <1432970085@qq.com>
* fix: get all userID
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: msggateway add online status call
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* refactor: log change
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* refactor: log change
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* chore: network mode change
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* cicd: robot automated Change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* cicd: robot automated Change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat: add api of get server time
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* feat: remove go work sum
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: pull message add isRead field
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: check msg-transfer script
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: script update
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: start don't kill old process
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: check component
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: pull message set isRead only message come from single.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: multiple gateway kick user each other.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: multiple gateway kick user each other.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: multiple gateway kick user each other.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: multiple gateway kick user each other.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: multiple gateway kick user each other.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: multiple gateway kick user each other.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: multiple gateway kick user each other.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: add ex field to update group info.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
* cicd: robot automated Change
* refactor: change project module name.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* refactor: change project module name.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* refactor: change project module name.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
* test: for pressure test.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* test: for pressure test.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* test: for pressure test.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* test: message log.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
* fxi: component check output valid info.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fxi: component check output valid info.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* test: send message test log.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* cicd: robot automated Change
* cicd: robot automated Change
* test: remove info log.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* feat: api of send message add sendTime field.
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
* fix: add callback for update user's info.
* cicd: robot automated Change
* fix: change callback command name.
* cicd: robot automated Change
* fix: single chat unread status change.
* fix: single chat unread status change.
* fix: single chat unread status change.
* fix: user status change.
* cicd: robot automated Change
* fix: user status change.
* fix: user status change.
* fix: user status change.
* cicd: robot automated Change
* fix: ws close when user logout.
* fix: remove repeat platform on online status.
* cicd: robot automated Change
* fix: api send messages for notification conversation .
* fix: api send messages for notification conversation .
* fix: api send messages for notification conversation .
* fix: api send messages for notification conversation .
* fix: api send messages for notification conversation .
* fix: api send messages for notification conversation.
* fix: api send messages for notification conversation.
* fix: api send messages for notification conversation.
* fix: api send messages for notification conversation.
* fix: api send messages for notification conversation.
* fix: api send messages for notification conversation.
* re: remove router of unsubscribeStatus.
* re: remove router of unsubscribeStatus.
* re: remove router of unsubscribeStatus.
* re: remove router of unsubscribeStatus.
* fix: reset branch
* fix: not support redis cluster. CROSSSLOT Keys in request don't hash to the same slot
* fix: update user.FaceURL do not trigger GroupMemberInfoSetNotification
* cicd: robot automated Change
* fix: api send messages for notification conversation.
* fix: api send messages for notification conversation.
* fix: zk add close to avoid zk block.
* fix: go mod update.
* fix: msg pull change and fcm redis flag fix.
---------
Signed-off-by: Gordon <1432970085@qq.com>
Signed-off-by: withchao <993506633@qq.com>
Signed-off-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: withchao <993506633@qq.com>
Co-authored-by: Xinwei Xiong <3293172751NSS@gmail.com>
Co-authored-by: FGadvancer
Co-authored-by: withchao
fix: sync close ws conn when kick old user avoid wrong trigger order about online status. (#1368)
Update README-zh_CN.md
Update README-zh_CN.md
fix: GetUserReqApplicationList error when there is a disbanded group chat (#1374)
fix: error when querying some information about disbanded group (#1376)
* fix: GetUserReqApplicationList error when there is a disbanded group chat
* fix: error when querying some information about disbanded group
fix: GetUserReqApplicationList dismissed group error (#1378)
* fix: GetUserReqApplicationList error when there is a disbanded group chat
* fix: error when querying some information about disbanded group
* fix: GetUserReqApplicationList dismissed group error
refactor: lower the level of code nesting (#1370)
* refactor: lower the level of code nesting
Signed-off-by: rfyiamcool
* refactor: lower the level of code nesting
Signed-off-by: rfyiamcool
---------
Signed-off-by: rfyiamcool
☀️ feat: Enhancing OpenIM with Integrated E2E Testing and CI/CD Enhancements (#1359)
* cicd: robot automated Change
* feat: add api test
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add api test make file
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim e2e test
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim e2e test
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: Fixed some unused scripts and some names
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* docs: optimize openim docs
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add prom address
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim info test
* feat: add openim images config path
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* fix: fix tim file rename
* fix: fix tim file rename
* fix: fix tim file rename
* fix: fix tim file rename
* fix: add openim test e2e
* feat: add openim test .keep
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: add openim test .keep
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: openim test
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: openim test
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
* feat: openim test
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
---------
Signed-off-by: Xinwei Xiong(cubxxw) <3293172751nss@gmail.com>
Co-authored-by: cubxxw
perf: auto set runtime maxprocs in docker (#1339)
Signed-off-by: rfyiamcool
build: build openim image (#1381)
perf: improve gzip performance with sync.pool (#1321)
Signed-off-by: rfyiamcool
Co-authored-by: Gordon <46924906+FGadvancer@users.noreply.github.com>
fix: add kafka compress type and producer ack params (#1310)
Signed-off-by: rfyiamcool
delete not using files
cicd: robot automated Change
add prometheus docker-compose for monitor
fix prometheus.yaml
fix environment.sh
fix init-config.sh
fix init-config.sh
fix env_template.yaml
fix docker-compose.yml
fix docker-compose.yml
add openim_admin_front service
change openim-admin-front
del not using files
add node-exporter-dashaboard.yaml
---
.env | 4 +-
.github/.codecov.yml | 18 +-
.github/workflows/api-test.yml | 90 +
.github/workflows/build-docker-image.yml | 12 +
.github/workflows/create_branch_on_tag.yml | 14 +
.github/workflows/e2e-test.yml | 60 +-
.github/workflows/openimci.yml | 33 +-
CHANGELOG/CHANGELOG.md | 2 +-
CONTRIBUTING.md | 8 +-
Makefile | 11 +-
README-zh_CN.md | 18 +-
README.md | 81 +-
build/images/Dockerfile | 14 +
chat | Bin 0 -> 7068773 bytes
cmd/openim-api/main.go | 10 +-
config/config.yaml | 2 +-
config/node-exporter-dashaboard.yaml | 1061 ++++++++++++
config/prometheus-dashboard.yaml | 1460 +++++++++++++++++
config/prometheus.yml | 85 +
deployments/README.md | 2 +-
.../openim-api/templates/deployment.yaml | 4 +-
.../templates/deployment.yaml | 18 +-
.../templates/deployment.yaml | 4 +-
.../openim-push/templates/deployment.yaml | 4 +-
.../openim-rpc-auth/templates/deployment.yaml | 4 +-
.../templates/deployment.yaml | 4 +-
.../templates/deployment.yaml | 4 +-
.../templates/deployment.yaml | 4 +-
.../openim-rpc-msg/templates/deployment.yaml | 4 +-
.../templates/deployment.yaml | 4 +-
.../openim-rpc-user/templates/deployment.yaml | 4 +-
deployments/templates/env_template.yaml | 25 +-
deployments/templates/prometheus.yml | 85 +
docker-compose.yml | 132 +-
docs/README.md | 52 +-
docs/contrib/README.md | 42 +
docs/{conversions => contrib}/api.md | 0
.../bash_log.md => contrib/bash-log.md} | 0
.../cicd-actions.md} | 0
...ode_conventions.md => code-conventions.md} | 43 +-
docs/{conversions => contrib}/commit.md | 0
docs/{conversions => contrib}/directory.md | 0
docs/contrib/environment.md | 4 +-
.../error_code.md => contrib/error-code.md} | 0
.../{git_workflow.md => git-workflow.md} | 0
.../{git_cherry-pick.md => gitcherry-pick.md} | 0
.../github-workflow.md | 2 +-
.../go_code.md => contrib/go-code.md} | 12 +
docs/{conversions => contrib}/images.md | 0
.../{init_config.md => init-config.md} | 0
.../{install_docker.md => install-docker.md} | 0
...ux_development.md => linux-development.md} | 0
.../{local_actions.md => local-actions.md} | 0
docs/{conversions => contrib}/logging.md | 0
docs/contrib/offline-deployment.md | 4 +-
.../{protoc_tools.md => protoc-tools.md} | 0
docs/contrib/test.md | 183 +++
docs/contrib/{util_go.md => util-go.md} | 0
.../{util_makefile.md => util-makefile.md} | 0
.../{util_scripts.md => util-scripts.md} | 0
docs/{conversions => contrib}/version.md | 2 +-
docs/conversions/README.md | 10 -
go.mod | 4 +
go.sum | 7 +
img.png | Bin 0 -> 44213 bytes
img_1.png | Bin 0 -> 71446 bytes
img_2.png | Bin 0 -> 58877 bytes
img_3.png | Bin 0 -> 41529 bytes
install.sh | 15 +-
install_guide.sh | 2 +-
internal/api/msg.go | 2 +-
internal/api/third.go | 3 +-
internal/msggateway/client.go | 90 +-
internal/msggateway/compressor.go | 45 +
internal/msggateway/compressor_test.go | 107 ++
internal/msggateway/init.go | 2 +-
internal/msggateway/message_handler.go | 46 +-
internal/msggateway/n_ws_server.go | 13 +-
internal/msgtransfer/init.go | 15 +-
.../online_msg_to_mongo_handler.go | 6 +-
internal/push/offlinepush/dummy/push.go | 18 +
internal/push/offlinepush/fcm/push_test.go | 32 -
internal/push/push_to_client.go | 107 +-
internal/rpc/auth/auth.go | 4 +-
internal/rpc/group/group.go | 43 +-
internal/rpc/msg/send.go | 12 +-
internal/tools/conversation.go | 12 +-
internal/tools/msg.go | 11 +-
pkg/apistruct/manage.go | 79 +-
pkg/common/cmd/msg_gateway_test.go | 51 +
pkg/common/cmd/msg_transfer.go | 4 +-
pkg/common/cmd/root.go | 1 +
pkg/common/config/config.go | 10 +-
pkg/common/config/parse.go | 4 +-
pkg/common/config/parse_test.go | 117 ++
pkg/common/db/cache/meta_cache.go | 3 +-
pkg/common/db/cache/msg.go | 8 +-
pkg/common/db/cache/s3.go | 8 +-
pkg/common/db/controller/msg.go | 66 +-
pkg/common/db/controller/s3.go | 8 +-
pkg/common/db/relation/conversation_model.go | 1 +
pkg/common/db/s3/cont/controller.go | 5 +-
pkg/common/db/s3/minio/minio.go | 3 +-
pkg/common/db/s3/minio/thumbnail.go | 12 +-
.../discoveryregister.go} | 2 +-
.../discoveryregister_test.go | 407 +++++
.../ginprometheus.go} | 2 +-
pkg/common/http/http_client_test.go | 154 ++
pkg/common/kafka/producer.go | 19 +-
pkg/common/locker/doc.go | 15 -
pkg/common/locker/message_locker.go | 72 -
.../gin-api.go => prommetrics/gin_api.go} | 4 +-
.../grpc-auth.go => prommetrics/grpc_auth.go} | 2 +-
.../grpc-msg.go => prommetrics/grpc_msg.go} | 2 +-
.../grpc_msggateway.go} | 2 +-
.../grpc_push.go | 2 +-
.../func.go => prommetrics/prommetrics.go} | 13 +-
pkg/common/prommetrics/prommetrics_test.go | 61 +
.../{prom_metrics => prommetrics}/transfer.go | 2 +-
pkg/common/startrpc/start.go | 16 +-
pkg/common/startrpc/start_test.go | 52 +
pkg/common/tls/tls.go | 1 +
pkg/msgprocessor/conversation_test.go | 334 ++++
prometheus.md | 14 +
scripts/README.md | 6 +-
scripts/batch_start_all.sh | 84 -
scripts/build.cmd | 13 -
scripts/cherry-pick.sh | 6 +-
scripts/{create_topic.sh => create-topic.sh} | 0
scripts/genconfig.sh | 5 +-
scripts/init-config.sh | 3 +-
scripts/{init_pwd.sh => init-pwd.sh} | 0
scripts/install/dependency.sh | 6 +-
scripts/install/environment.sh | 25 +-
scripts/install/install.sh | 9 +-
scripts/install/openim-api.sh | 3 +-
scripts/install/openim-crontask.sh | 12 +-
scripts/install/openim-msggateway.sh | 12 +-
scripts/install/openim-msgtransfer.sh | 15 +-
scripts/install/openim-push.sh | 12 +-
scripts/install/openim-rpc.sh | 9 +-
scripts/install/test.sh | 1394 +++++++++++++---
scripts/install_im_compose.sh | 66 -
scripts/lib/color.sh | 3 +-
scripts/lib/logging.sh | 3 +-
scripts/lib/util.sh | 15 +
scripts/make-rules/golang.mk | 12 +
scripts/make-rules/image.mk | 2 +-
scripts/start.bat | 12 -
scripts/template/head.md.tmpl | 4 +-
scripts/wait-for-it.sh | 9 +-
test/e2e/README.md | 134 ++
test/e2e/api/.keep | 1 +
test/e2e/api/token/token.go | 138 ++
test/e2e/api/user/curd.go | 44 +
test/e2e/api/user/user.go | 101 ++
test/e2e/conformance/.keep | 1 +
test/e2e/e2e.go | 37 +
test/e2e/e2e_test.go | 23 +
test/e2e/framework/config/.keep | 1 +
test/e2e/framework/config/config.go | 21 +
test/e2e/framework/config/config_test.go | 75 +
test/e2e/framework/ginkgowrapper/.keep | 1 +
.../framework/ginkgowrapper/ginkgowrapper.go | 1 +
.../ginkgowrapper/ginkgowrapper_test.go | 1 +
test/e2e/framework/helpers/.keep | 1 +
test/e2e/framework/helpers/chat/chat.go | 152 ++
test/e2e/performance/.keep | 1 +
test/e2e/rpc/auth/.keep | 1 +
test/e2e/rpc/conversation/.keep | 1 +
test/e2e/rpc/friend/.keep | 1 +
test/e2e/rpc/group/.keep | 1 +
test/e2e/rpc/message/.keep | 1 +
test/e2e/scalability/.keep | 1 +
test/e2e/upgrade/.keep | 1 +
test/e2e/web/.keep | 1 +
test/readme | 2 +
test/typecheck/typecheck_test.go | 4 +-
test/wrktest.sh | 12 +-
179 files changed, 7247 insertions(+), 1043 deletions(-)
create mode 100644 .github/workflows/api-test.yml
create mode 100755 chat
create mode 100644 config/node-exporter-dashaboard.yaml
create mode 100644 config/prometheus-dashboard.yaml
create mode 100644 config/prometheus.yml
create mode 100644 deployments/templates/prometheus.yml
create mode 100644 docs/contrib/README.md
rename docs/{conversions => contrib}/api.md (100%)
rename docs/{conversions/bash_log.md => contrib/bash-log.md} (100%)
rename docs/{conversions/cicd_actions.md => contrib/cicd-actions.md} (100%)
rename docs/contrib/{code_conventions.md => code-conventions.md} (52%)
rename docs/{conversions => contrib}/commit.md (100%)
rename docs/{conversions => contrib}/directory.md (100%)
rename docs/{conversions/error_code.md => contrib/error-code.md} (100%)
rename docs/contrib/{git_workflow.md => git-workflow.md} (100%)
rename docs/contrib/{git_cherry-pick.md => gitcherry-pick.md} (100%)
rename docs/{conversions => contrib}/github-workflow.md (99%)
rename docs/{conversions/go_code.md => contrib/go-code.md} (96%)
rename docs/{conversions => contrib}/images.md (100%)
rename docs/contrib/{init_config.md => init-config.md} (100%)
rename docs/contrib/{install_docker.md => install-docker.md} (100%)
rename docs/contrib/{linux_development.md => linux-development.md} (100%)
rename docs/contrib/{local_actions.md => local-actions.md} (100%)
rename docs/{conversions => contrib}/logging.md (100%)
rename docs/contrib/{protoc_tools.md => protoc-tools.md} (100%)
create mode 100644 docs/contrib/test.md
rename docs/contrib/{util_go.md => util-go.md} (100%)
rename docs/contrib/{util_makefile.md => util-makefile.md} (100%)
rename docs/contrib/{util_scripts.md => util-scripts.md} (100%)
rename docs/{conversions => contrib}/version.md (99%)
delete mode 100644 docs/conversions/README.md
create mode 100644 img.png
create mode 100644 img_1.png
create mode 100644 img_2.png
create mode 100644 img_3.png
create mode 100644 internal/msggateway/compressor_test.go
create mode 100644 internal/push/offlinepush/dummy/push.go
delete mode 100644 internal/push/offlinepush/fcm/push_test.go
create mode 100644 pkg/common/cmd/msg_gateway_test.go
create mode 100644 pkg/common/config/parse_test.go
rename pkg/common/{discovery_register/k8s_discovery_register.go => discoveryregister/discoveryregister.go} (98%)
create mode 100644 pkg/common/discoveryregister/discoveryregister_test.go
rename pkg/common/{ginPrometheus/ginPrometheus.go => ginprometheus/ginprometheus.go} (99%)
create mode 100644 pkg/common/http/http_client_test.go
delete mode 100644 pkg/common/locker/doc.go
delete mode 100644 pkg/common/locker/message_locker.go
rename pkg/common/{prom_metrics/gin-api.go => prommetrics/gin_api.go} (91%)
rename pkg/common/{prom_metrics/grpc-auth.go => prommetrics/grpc_auth.go} (90%)
rename pkg/common/{prom_metrics/grpc-msg.go => prommetrics/grpc_msg.go} (97%)
rename pkg/common/{prom_metrics/grpc-msggateway.go => prommetrics/grpc_msggateway.go} (90%)
rename pkg/common/{prom_metrics => prommetrics}/grpc_push.go (92%)
rename pkg/common/{prom_metrics/func.go => prommetrics/prommetrics.go} (87%)
create mode 100644 pkg/common/prommetrics/prommetrics_test.go
rename pkg/common/{prom_metrics => prommetrics}/transfer.go (97%)
create mode 100644 pkg/common/startrpc/start_test.go
create mode 100644 pkg/msgprocessor/conversation_test.go
create mode 100644 prometheus.md
delete mode 100755 scripts/batch_start_all.sh
delete mode 100644 scripts/build.cmd
rename scripts/{create_topic.sh => create-topic.sh} (100%)
rename scripts/{init_pwd.sh => init-pwd.sh} (100%)
delete mode 100755 scripts/install_im_compose.sh
delete mode 100644 scripts/start.bat
create mode 100644 test/e2e/README.md
create mode 100644 test/e2e/api/.keep
create mode 100644 test/e2e/api/token/token.go
create mode 100644 test/e2e/api/user/curd.go
create mode 100644 test/e2e/api/user/user.go
create mode 100644 test/e2e/conformance/.keep
create mode 100644 test/e2e/e2e.go
create mode 100644 test/e2e/e2e_test.go
create mode 100644 test/e2e/framework/config/.keep
create mode 100644 test/e2e/framework/config/config.go
create mode 100644 test/e2e/framework/config/config_test.go
create mode 100644 test/e2e/framework/ginkgowrapper/.keep
create mode 100644 test/e2e/framework/ginkgowrapper/ginkgowrapper.go
create mode 100644 test/e2e/framework/ginkgowrapper/ginkgowrapper_test.go
create mode 100644 test/e2e/framework/helpers/.keep
create mode 100644 test/e2e/framework/helpers/chat/chat.go
create mode 100644 test/e2e/performance/.keep
create mode 100644 test/e2e/rpc/auth/.keep
create mode 100644 test/e2e/rpc/conversation/.keep
create mode 100644 test/e2e/rpc/friend/.keep
create mode 100644 test/e2e/rpc/group/.keep
create mode 100644 test/e2e/rpc/message/.keep
create mode 100644 test/e2e/scalability/.keep
create mode 100644 test/e2e/upgrade/.keep
create mode 100644 test/e2e/web/.keep
diff --git a/.env b/.env
index bcfc0722a..cc42fbcb7 100644
--- a/.env
+++ b/.env
@@ -29,8 +29,8 @@ PASSWORD=openIM123
MINIO_ENDPOINT=http://172.28.0.1:10005
# Base URL for the application programming interface (API).
-# Default: API_URL=http://172.28.0.1:10002
-API_URL=http://172.28.0.1:10002
+# Default: API_URL=http://172.0.0.1:10002
+API_URL=http://172.0.0.1:10002
# Directory path for storing data files or related information.
# Default: DATA_DIR=./
diff --git a/.github/.codecov.yml b/.github/.codecov.yml
index 9e262e0e3..fab584a31 100644
--- a/.github/.codecov.yml
+++ b/.github/.codecov.yml
@@ -20,4 +20,20 @@ coverage:
paths:
- pkg/* # only include coverage in "pkg/" folder
informational: true # Always pass check
- patch: off # disable the commit only checks
\ No newline at end of file
+ tools: # declare a new status context "tools"
+ paths:
+ - tools/* # only include coverage in "tools/" folder
+ informational: true # Always pass check
+ test: # declare a new status context "test"
+ paths:
+ - test/* # only include coverage in "test/" folder
+ informational: true # Always pass check
+ # internal: # declare a new status context "internal"
+ # paths:
+ # - internal/* # only include coverage in "internal/" folder
+ # informational: true # Always pass check
+ # cmd: # declare a new status context "cmd"
+ # paths:
+ # - cmd/* # only include coverage in "cmd/" folder
+ # informational: true # Always pass check
+ patch: off # disable the commit only checks
diff --git a/.github/workflows/api-test.yml b/.github/workflows/api-test.yml
new file mode 100644
index 000000000..0bbc86619
--- /dev/null
+++ b/.github/workflows/api-test.yml
@@ -0,0 +1,90 @@
+# 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.
+
+name: OpenIM API TEST
+
+on:
+ push:
+ branches:
+ - main
+ paths-ignore:
+ - "docs/**"
+ - "README.md"
+ - "README_zh-CN.md"
+ - "CONTRIBUTING.md"
+ pull_request:
+ branches:
+ - main
+ paths-ignore:
+ - "README.md"
+ - "README_zh-CN.md"
+ - "CONTRIBUTING.md"
+ - "docs/**"
+
+env:
+ GO_VERSION: "1.19"
+ GOLANGCI_VERSION: "v1.50.1"
+
+jobs:
+ execute-linux-systemd-scripts:
+ name: Execute OpenIM script on ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ environment:
+ name: openim
+ strategy:
+ matrix:
+ go_version: ["1.20"]
+ os: ["ubuntu-latest"]
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Go ${{ matrix.go_version }}
+ uses: actions/setup-go@v4
+ with:
+ go-version: ${{ matrix.go_version }}
+ id: go
+
+ - name: Install Task
+ uses: arduino/setup-task@v1
+ with:
+ version: '3.x' # If available, use the latest major version that's compatible
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Docker Operations
+ run: |
+ curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
+ sudo docker compose up -d
+ sudo sleep 60
+
+ - name: Module Operations
+ run: |
+ sudo make tidy
+ sudo make tools.verify.go-gitlint
+
+ - name: Build, Start, Check Services and Print Logs
+ run: |
+ sudo ./scripts/install/install.sh -i && \
+ sudo ./scripts/install/install.sh -s && \
+ (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+
+ - name: Run Test
+ run: |
+ sudo make test-api && \
+ (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
+
+ - name: Stop Services
+ run: |
+ sudo ./scripts/install/install.sh -u && \
+ (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
\ No newline at end of file
diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml
index 79b60fbed..a8cb98a51 100644
--- a/.github/workflows/build-docker-image.yml
+++ b/.github/workflows/build-docker-image.yml
@@ -52,6 +52,7 @@ jobs:
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
@@ -87,6 +88,16 @@ jobs:
uses: docker/metadata-action@v5.0.0
with:
images: registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-server
+ # generate Docker tags based on the following events/attributes
+ tags: |
+ 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
@@ -126,6 +137,7 @@ jobs:
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
diff --git a/.github/workflows/create_branch_on_tag.yml b/.github/workflows/create_branch_on_tag.yml
index 0d8b0d91a..b6b9eb8e8 100644
--- a/.github/workflows/create_branch_on_tag.yml
+++ b/.github/workflows/create_branch_on_tag.yml
@@ -1,3 +1,17 @@
+# 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.
+
name: Create Branch on Tag
on:
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index 1e5949edf..535c30f75 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-name: OpenIM E2E Test
+name: OpenIM Linux System E2E Test
on:
workflow_dispatch:
@@ -41,4 +41,60 @@ jobs:
- name: Create e2e test
run: |
- echo "...test e2e"
\ No newline at end of file
+ echo "...test e2e"
+
+ execute-linux-systemd-scripts:
+ name: Execute OpenIM script on ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ environment:
+ name: openim
+ strategy:
+ matrix:
+ go_version: ["1.20"]
+ os: ["ubuntu-latest"]
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Go ${{ matrix.go_version }}
+ uses: actions/setup-go@v4
+ with:
+ go-version: ${{ matrix.go_version }}
+ id: go
+
+ - name: Install Task
+ uses: arduino/setup-task@v1
+ with:
+ version: '3.x' # If available, use the latest major version that's compatible
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Docker Operations
+ run: |
+ curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
+ sudo docker compose up -d
+ sudo sleep 60
+
+ - name: Module Operations
+ run: |
+ sudo make tidy
+ sudo make tools.verify.go-gitlint
+
+ - name: Build, Start
+ run: |
+ sudo ./scripts/install/install.sh -i
+
+ - name: Exec OpenIM System Status Chack
+ run: |
+ sudo ./scripts/install/install.sh -s
+
+ - name: Exec OpenIM API test
+ run: |
+ sudo make test-api
+
+ - name: Exec OpenIM E2E test
+ run: |
+ sudo make test-e2e
+
+ - name: Exec OpenIM System uninstall
+ run: |
+ sudo ./scripts/install/install.sh -u
\ No newline at end of file
diff --git a/.github/workflows/openimci.yml b/.github/workflows/openimci.yml
index 05a8ce5c5..2e4cc9e24 100644
--- a/.github/workflows/openimci.yml
+++ b/.github/workflows/openimci.yml
@@ -64,7 +64,8 @@ jobs:
- name: Install Task
uses: arduino/setup-task@v1
with:
- version: 2.x
+ version: '3.x' # If available, use the latest major version that's compatible
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Module Operations
run: |
@@ -122,7 +123,8 @@ jobs:
- name: Install Task
uses: arduino/setup-task@v1
with:
- version: 2.x
+ version: '3.x' # If available, use the latest major version that's compatible
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run OpenIM make install start
run: |
sudo make install
@@ -145,10 +147,13 @@ jobs:
with:
go-version: ${{ matrix.go_version }}
id: go
+
- name: Install Task
uses: arduino/setup-task@v1
with:
- version: 2.x
+ version: '3.x' # If available, use the latest major version that's compatible
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
- name: Docker Operations
run: |
curl -o docker-compose.yml https://raw.githubusercontent.com/OpenIMSDK/openim-docker/main/example/basic-openim-server-dependency.yml
@@ -160,18 +165,15 @@ jobs:
sudo make tidy
sudo make tools.verify.go-gitlint
- - name: Build, Start and Check Services
+ - name: Build, Start, Check Services and Print Logs
run: |
- sudo make init
- sudo make build
- sudo make start
- sudo make check
-
- - name: Print OpenIM Logs
- run: sudo cat ./_output/logs/* 2>/dev/null
- continue-on-error: true
+ sudo make init && \
+ sudo make build && \
+ sudo make start && \
+ sudo make check || \
+ (echo "An error occurred, printing logs:" && sudo cat ./_output/logs/* 2>/dev/null)
- openim-build-image:
+ openim-test-build-image:
name: Build OpenIM Docker Image
runs-on: ubuntu-latest
environment:
@@ -184,10 +186,13 @@ jobs:
with:
go-version: ${{ matrix.go_version }}
id: go
+
- name: Install Task
uses: arduino/setup-task@v1
with:
- version: 2.x
+ version: '3.x' # If available, use the latest major version that's compatible
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
- name: Test Docker Build
run: |
sudo make image
\ No newline at end of file
diff --git a/CHANGELOG/CHANGELOG.md b/CHANGELOG/CHANGELOG.md
index 2358b5fb8..f5d62ab24 100644
--- a/CHANGELOG/CHANGELOG.md
+++ b/CHANGELOG/CHANGELOG.md
@@ -20,7 +20,7 @@ All notable changes to this project will be documented in this file.
## OpenIM versioning policy
-+ [OpenIM Version](../docs/conversions/version.md)
++ [OpenIM Version](../docs/contrib/version.md)
## command
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index afa8b35d4..ee275e7ad 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,6 +42,12 @@ If you are familiar with [Makefile](./Makefile) , you can easily see the clever
The [Makefile](./Makefile) is for every developer, even if you don't know how to use the Makefile tool, don't worry, we provide two great commands to get you up to speed with the Makefile architecture, `make help` and `make help-all`, it can reduce problems of the developing environment.
+In accordance with the naming conventions adopted by OpenIM and drawing reference from the Google Naming Conventions as per the guidelines available at https://google.github.io/styleguide/go/, the following expectations for naming practices within the project are set forth:
+
++ https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/code-conventions.md
++ https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md
+
+
## Code of ConductCode of Conduct
#### Code and doc contribution
@@ -270,7 +276,7 @@ You can find some very formal PR in [RFC](https://github.com/openimsdk/open-im-s
**🈴 Reviewing PRs:**
+ Be respectful and constructive
-+ Assign yourself to the PR
++ Assign yourself to the PR (comment `/assign`)
+ Check if all checks are passing
+ Suggest changes instead of simply commenting on found issues
+ If you are unsure about something, ask the author
diff --git a/Makefile b/Makefile
index 67f595fb4..1941bde6c 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
## all: Run tidy, gen, add-copyright, format, lint, cover, build ✨
.PHONY: all
-all: tidy gen add-copyright verify lint cover restart
+all: tidy gen add-copyright verify test-api lint cover restart
# ==============================================================================
# Build set
@@ -166,6 +166,15 @@ test:
cover:
@$(MAKE) go.test.cover
+## test-api: Run api test. ✨
+.PHONY: test-api
+test-api:
+ @$(MAKE) go.test.api
+
+## test-e2e: Run e2e test
+test-e2e:
+ @$(MAKE) go.test.e2e
+
## updates: Check for updates to go.mod dependencies. ✨
.PHONY: updates
@$(MAKE) go.updates
diff --git a/README-zh_CN.md b/README-zh_CN.md
index f24ee4739..6dd264342 100644
--- a/README-zh_CN.md
+++ b/README-zh_CN.md
@@ -29,6 +29,10 @@
+## 🟢 扫描微信进群交流
+
+
+
## Ⓜ️ 关于 OpenIM
OpenIM 不仅仅是一个开源的即时消息组件,它是你的应用程序生态系统的一个不可或缺的部分。查看下面的图表,了解 AppServer、AppClient、OpenIMServer 和 OpenIMSDK 是如何交互的。
@@ -86,22 +90,22 @@ OpenIM 我们的目标是建立一个顶级的开源社区。我们有一套标
在开始之前,请确保你的更改是有需求的。最好的方法是创建一个[新的讨论](https://github.com/openimsdk/open-im-server/discussions/new/choose) 或 [Slack 通信](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q),或者如果你发现一个问题,首先[报告它](https://github.com/openimsdk/open-im-server/issues/new/choose)。
-+ [代码标准](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/go_code.md)
++ [代码标准](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/go-code.md)
-+ [Docker 镜像标准](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/images.md)
++ [Docker 镜像标准](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md)
-+ [目录标准](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/directory.md)
++ [目录标准](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/directory.md)
-+ [提交标准](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/commit.md)
++ [提交标准](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/commit.md)
-+ [版本控制标准](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/version.md)
++ [版本控制标准](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md)
-+ [接口标准](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/interface.md)
++ [接口标准](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/interface.md)
+ [OpenIM配置和环境变量设置](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md)
> **Note**
-> 针对中国的用户,阅读我们的 [Docker 镜像标准](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/images.md) 以便使用国内 aliyun 的镜像地址。OpenIM 也有针对中国的 gitee 同步仓库,你可以在 [gitee.com](https://gitee.com/openimsdk) 上找到它。
+> 针对中国的用户,阅读我们的 [Docker 镜像标准](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/images.md) 以便使用国内 aliyun 的镜像地址。OpenIM 也有针对中国的 gitee 同步仓库,你可以在 [gitee.com](https://gitee.com/openimsdk) 上找到它。
## :link: 链接
diff --git a/README.md b/README.md
index 0a569af6e..722de0240 100644
--- a/README.md
+++ b/README.md
@@ -4,31 +4,28 @@
-
- ⭐️ Open source Instant Messaging Server ⭐️
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+[](https://github.com/openimsdk/open-im-server/stargazers)
+[](https://github.com/openimsdk/open-im-server/network/members)
+[](https://app.codecov.io/gh/openimsdk/open-im-server)
+[](https://goreportcard.com/report/github.com/openimsdk/open-im-server)
+[](https://pkg.go.dev/github.com/openimsdk/open-im-server/v3)
+[](https://github.com/openimsdk/open-im-server/blob/main/LICENSE)
+[](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q)
+[](https://www.bestpractices.dev/projects/8045)
+[](https://github.com/openimsdk/open-im-server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22)
+[](https://golang.org/)
+
+[**English**](./README.md) •
+[**简体中文**](./README-zh_CN.md) •
+[**Docs**](https://openim.io/en)
-
- English •
- 简体中文 •
- Docs
-
+
+
## Ⓜ️ About OpenIM
OpenIM isn't just an open-source instant messaging component, it's an integral part of your application ecosystem. Check out this diagram to understand how AppServer, AppClient, OpenIMServer, and OpenIMSDK interact.
@@ -118,7 +115,7 @@ It is recommended to use Docker Compose for deployment, which can easily and qui
> **Note**
>
-> If you don't know OpenIM's versioning policy, 📚Read our release policy: https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/version.md
+> If you don't know OpenIM's versioning policy, 📚Read our release policy: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md
@@ -133,7 +130,7 @@ Ur need `Go 1.20` or higher version, and `make`.
go version && make --version || echo "Error: One of the commands failed."
```
-Version Details: https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/version.md
+Version Details: https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md
You can get the version number from the command below or from [github releases](https://github.com/openimsdk/open-im-server/tags).
@@ -141,7 +138,7 @@ You can get the version number from the command below or from [github releases](
$ curl --silent "https://api.github.com/repos/openimsdk/open-im-server/releases" | jq -r '.[].tag_name'
```
-We have our own version management policy, if you are interested in our version management, I recommend reading [📚 OpenIM Version](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/version.md), We recommend using stable versions such as `v3.3.0` and `v3.2.0` whenever possible. `v3.1.1-alpha.3` as well as `v3.3.0-beta.0` and `v3.2.0-rc.0` are pre-release or beta versions and are not recommended.
+We have our own version management policy, if you are interested in our version management, I recommend reading [📚 OpenIM Version](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/version.md), We recommend using stable versions such as `v3.3.0` and `v3.2.0` whenever possible. `v3.1.1-alpha.3` as well as `v3.3.0-beta.0` and `v3.2.0-rc.0` are pre-release or beta versions and are not recommended.
Set `OPENIM_VERSION` environment variables for the latest `OPENIM_VERSION` number, or replace the `OPENIM_VERSION` for you to install the OpenIM-Server `OPENIM_VERSION`:
@@ -199,21 +196,41 @@ Delve into the heart of Open-IM-Server's functionality with our architecture dia
## :hammer_and_wrench: To start developing OpenIM
+[](https://vscode.dev/github/openimsdk/open-im-server)
+
OpenIM Our goal is to build a top-level open source community. We have a set of standards, in the [Community repository](https://github.com/OpenIMSDK/community).
If you'd like to contribute to this Open-IM-Server repository, please read our [contributor documentation](https://github.com/openimsdk/open-im-server/blob/main/CONTRIBUTING.md).
Before you start, please make sure your changes are in demand. The best for that is to create a [new discussion](https://github.com/openimsdk/open-im-server/discussions/new/choose) OR [Slack Communication](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q), or if you find an issue, [report it](https://github.com/openimsdk/open-im-server/issues/new/choose) first.
-- [Code Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/go_code.md)
-- [Docker Images Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/images.md)
-- [Directory Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/directory.md)
-- [Commit Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/commit.md)
-- [Versioning Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/version.md)
-- [Interface Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/api.md)
-- [Log Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/logging.md)
-- [Error Code Standards](https://github.com/openimsdk/open-im-server/blob/main/docs/conversions/error_code.md)
-- [OpenIM configuration and environment variable Settings](https://github.com/openimsdk/open-im-server/blob/main/docs/contrib/environment.md)
+- [OpenIM API Reference](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/api.md)
+- [OpenIM Bash Logging](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/bash-log.md)
+- [OpenIM CI/CD Actions](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/cicd-actions.md)
+- [OpenIM Code Conventions](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/code-conventions.md)
+- [OpenIM Commit Guidelines](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/commit.md)
+- [OpenIM Development Guide](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/development.md)
+- [OpenIM Directory Structure](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/directory.md)
+- [OpenIM Environment Setup](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/environment.md)
+- [OpenIM Error Code Reference](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/error-code.md)
+- [OpenIM Git Workflow](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/git-workflow.md)
+- [OpenIM Git Cherry Pick Guide](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/gitcherry-pick.md)
+- [OpenIM GitHub Workflow](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/github-workflow.md)
+- [OpenIM Go Code Standards](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/go-code.md)
+- [OpenIM Image Guidelines](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/images.md)
+- [OpenIM Initial Configuration](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/init-config.md)
+- [OpenIM Docker Installation Guide](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/install-docker.md)
+- [OpenIM OpenIM Linux System Installation](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/install-openim-linux-system.md)
+- [OpenIM Linux Development Guide](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/linux-development.md)
+- [OpenIM Local Actions Guide](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/local-actions.md)
+- [OpenIM Logging Conventions](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/logging.md)
+- [OpenIM Offline Deployment](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/offline-deployment.md)
+- [OpenIM Protoc Tools](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/protoc-tools.md)
+- [OpenIM Testing Guide](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/test.md)
+- [OpenIM Utility Go](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/util-go.md)
+- [OpenIM Makefile Utilities](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/util-makefile.md)
+- [OpenIM Script Utilities](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/util-scripts.md)
+- [OpenIM Versioning](https://github.com/openimsdk/open-im-server/tree/main/docs/contrib/version.md)
## :busts_in_silhouette: Community
diff --git a/build/images/Dockerfile b/build/images/Dockerfile
index 518de78b1..51fe94e1c 100644
--- a/build/images/Dockerfile
+++ b/build/images/Dockerfile
@@ -1,3 +1,17 @@
+# Copyright © 2023 OpenIM. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
FROM BASE_IMAGE
WORKDIR ${SERVER_WORKDIR}
diff --git a/chat b/chat
new file mode 100755
index 0000000000000000000000000000000000000000..b79e06dd7fc98898f96d053443784f8a4e760d9b
GIT binary patch
literal 7068773
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
z
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
@DI=u^R(r!Zg*Ql!YX2B992D|d
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