From acd5976a9e684e7c89e7ddc5f39784efe06a73c5 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Wed, 21 Aug 2024 00:22:48 +0800 Subject: [PATCH 1/7] init project --- .gitignore | 6 + .golangci.yaml | 140 ++++++++++++ .../20230529020011_account_table.down.sql | 1 + .../mysql/20230529020011_account_table.up.sql | 10 + .../20230529020011_account_uid_table.down.sql | 1 + .../20230529020011_account_uid_table.up.sql | 8 + .../mysql/20230529020011_user_table.down.sql | 1 + .../mysql/20230529020011_user_table.up.sql | 17 ++ .../20230719061241_machine_node.down.sql | 1 + .../mysql/20230719061241_machine_node.up.sql | 7 + .../20230529020000_create_schema.down.sql | 1 + .../20230529020000_create_schema.up.sql | 1 + generate/database/readme.md | 39 ++++ generate/protobuf/member.proto | 214 ++++++++++++++++++ 14 files changed, 447 insertions(+) create mode 100644 .gitignore create mode 100644 .golangci.yaml create mode 100644 generate/database/mysql/20230529020011_account_table.down.sql create mode 100644 generate/database/mysql/20230529020011_account_table.up.sql create mode 100644 generate/database/mysql/20230529020011_account_uid_table.down.sql create mode 100644 generate/database/mysql/20230529020011_account_uid_table.up.sql create mode 100644 generate/database/mysql/20230529020011_user_table.down.sql create mode 100644 generate/database/mysql/20230529020011_user_table.up.sql create mode 100644 generate/database/mysql/20230719061241_machine_node.down.sql create mode 100644 generate/database/mysql/20230719061241_machine_node.up.sql create mode 100644 generate/database/mysql/create/20230529020000_create_schema.down.sql create mode 100644 generate/database/mysql/create/20230529020000_create_schema.up.sql create mode 100644 generate/database/readme.md create mode 100644 generate/protobuf/member.proto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a56a16 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.idea/ +go.sum +account/ +gen_result/ +etc/service.yaml +client/ \ No newline at end of file diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..5518484 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,140 @@ +run: + timeout: 3m + # Exit code when at least one issue was found. + # Default: 1 + issues-exit-code: 2 + # Include test files or not. + # Default: true + tests: false + +# Reference URL: https://golangci-lint.run/usage/linters/ +linters: + # Disable everything by default so upgrades to not include new - default + # enabled- linters. + disable-all: true + # Specifically enable linters we want to use. + enable: + # - depguard + - errcheck + # - godot + - gofmt + - goimports + - gosimple + - govet + - ineffassign + - misspell + - revive + # - staticcheck + - typecheck + - unused + # - wsl + - asasalint + - asciicheck + - bidichk + - bodyclose + # - containedctx + - contextcheck + # - cyclop + # - varnamelen + # - gci + - wastedassign + - whitespace + # - wrapcheck + - thelper + - tparallel + - unconvert + - unparam + - usestdlibvars + - tenv + - testableexamples + - stylecheck + - sqlclosecheck + - nosprintfhostport + - paralleltest + - prealloc + - predeclared + - promlinter + - reassign + - rowserrcheck + - nakedret + - nestif + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nonamedreturns + - decorder + - dogsled + # - dupl + - dupword + - durationcheck + - errchkjson + - errname + - errorlint + # - execinquery + - exhaustive + - exportloopref + - forbidigo + - forcetypeassert + # - gochecknoglobals + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + # - godox + # - goerr113 + # - gofumpt + - goheader + - gomoddirectives + # - gomodguard always failed + - goprintffuncname + - gosec + - grouper + - importas + - interfacebloat + # - ireturn + - lll + - loggercheck + - maintidx + - makezero + +issues: + exclude-rules: + - path: _test\.go + linters: + - funlen + - goconst + - interfacer + - dupl + - lll + - goerr113 + - errcheck + - gocritic + - cyclop + - wrapcheck + - gocognit + - contextcheck + +linters-settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + gocognit: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 40 + nestif: + # Minimal complexity of if statements to report. + # Default: 5 + min-complexity: 10 + lll: + # Max line length, lines longer will be reported. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option. + # Default: 120. + line-length: 200 + # Tab width in spaces. + # Default: 1 + tab-width: 1 diff --git a/generate/database/mysql/20230529020011_account_table.down.sql b/generate/database/mysql/20230529020011_account_table.down.sql new file mode 100644 index 0000000..e807a6d --- /dev/null +++ b/generate/database/mysql/20230529020011_account_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `account`; diff --git a/generate/database/mysql/20230529020011_account_table.up.sql b/generate/database/mysql/20230529020011_account_table.up.sql new file mode 100644 index 0000000..d113a59 --- /dev/null +++ b/generate/database/mysql/20230529020011_account_table.up.sql @@ -0,0 +1,10 @@ +CREATE TABLE `account` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `account` VARCHAR(50) NOT NULL, + `token` VARCHAR(255) NOT NULL, + `platform` INT NOT NULL COMMENT '平台類型 1. ark 2. google', + `create_time` BIGINT NOT NULL DEFAULT 0, + `update_time` BIGINT NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE INDEX `uk_account` (`account` ASC) +)ENGINE=InnoDB COMMENT='帳號'; diff --git a/generate/database/mysql/20230529020011_account_uid_table.down.sql b/generate/database/mysql/20230529020011_account_uid_table.down.sql new file mode 100644 index 0000000..dd19471 --- /dev/null +++ b/generate/database/mysql/20230529020011_account_uid_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `account_to_uid`; diff --git a/generate/database/mysql/20230529020011_account_uid_table.up.sql b/generate/database/mysql/20230529020011_account_uid_table.up.sql new file mode 100644 index 0000000..bf48c07 --- /dev/null +++ b/generate/database/mysql/20230529020011_account_uid_table.up.sql @@ -0,0 +1,8 @@ +CREATE TABLE `account_to_uid` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `account` VARCHAR(50) NOT NULL, + `uid` VARCHAR(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `uk_account` (`account` ASC), + INDEX `idx_uid` (`uid` ASC) +)ENGINE=InnoDB COMMENT='帳號轉換表'; diff --git a/generate/database/mysql/20230529020011_user_table.down.sql b/generate/database/mysql/20230529020011_user_table.down.sql new file mode 100644 index 0000000..45aaa85 --- /dev/null +++ b/generate/database/mysql/20230529020011_user_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `user_table`; diff --git a/generate/database/mysql/20230529020011_user_table.up.sql b/generate/database/mysql/20230529020011_user_table.up.sql new file mode 100644 index 0000000..40f58c5 --- /dev/null +++ b/generate/database/mysql/20230529020011_user_table.up.sql @@ -0,0 +1,17 @@ +CREATE TABLE `user_table` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `verify_type` tinyint DEFAULT 0 NOT NULL COMMENT '驗證類型 0. 異常 1.信箱 2.手機 3. GA 4.不驗證', + `alarm_type` tinyint DEFAULT 0 NOT NULL COMMENT '告警狀態 0. 異常 1. 正常(未告警) 2.系統告警中', + `status` tinyint DEFAULT 0 NOT NULL COMMENT '會員狀態 0. 異常 1. 尚未驗證 2. 啟用 3. 停權中 4. 信箱以驗證 5. 手機以驗證 6. GA 以驗證', + `uid` VARCHAR(255) NOT NULL, + `language` VARCHAR(255) NOT NULL DEFAULT '', + `currency` VARCHAR(255) NOT NULL DEFAULT '', + `nick_name` VARCHAR(255) DEFAULT '', + `gender` tinyint DEFAULT 0 NOT NULL COMMENT '0. 不願透露, 1 男 2 女', + `birthday` INT NOT NULL DEFAULT 0, + `create_time` BIGINT NOT NULL DEFAULT 0, + `update_time` BIGINT NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + INDEX `idx_create_time` (`create_time` ASC), + UNIQUE INDEX `uk_uid` (`uid` ASC) +)ENGINE=InnoDB COMMENT='使用者資訊'; diff --git a/generate/database/mysql/20230719061241_machine_node.down.sql b/generate/database/mysql/20230719061241_machine_node.down.sql new file mode 100644 index 0000000..b299591 --- /dev/null +++ b/generate/database/mysql/20230719061241_machine_node.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `machine_node`; \ No newline at end of file diff --git a/generate/database/mysql/20230719061241_machine_node.up.sql b/generate/database/mysql/20230719061241_machine_node.up.sql new file mode 100644 index 0000000..855ccd8 --- /dev/null +++ b/generate/database/mysql/20230719061241_machine_node.up.sql @@ -0,0 +1,7 @@ +CREATE TABLE `machine_node` ( + `id` bigint AUTO_INCREMENT NOT NULL COMMENT '流水號', + `create_time` bigint DEFAULT 0 NOT NULL COMMENT '創建時間', + `update_time` bigint DEFAULT 0 NOT NULL COMMENT '更新時間', + `host_name` varchar(200) DEFAULT '' NOT NULL COMMENT 'host name', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='machineID Assigner for Generator'; diff --git a/generate/database/mysql/create/20230529020000_create_schema.down.sql b/generate/database/mysql/create/20230529020000_create_schema.down.sql new file mode 100644 index 0000000..e7727a5 --- /dev/null +++ b/generate/database/mysql/create/20230529020000_create_schema.down.sql @@ -0,0 +1 @@ +DROP DATABASE IF EXISTS `ark_member`; \ No newline at end of file diff --git a/generate/database/mysql/create/20230529020000_create_schema.up.sql b/generate/database/mysql/create/20230529020000_create_schema.up.sql new file mode 100644 index 0000000..d997e04 --- /dev/null +++ b/generate/database/mysql/create/20230529020000_create_schema.up.sql @@ -0,0 +1 @@ +CREATE DATABASE IF NOT EXISTS `ark_member`; \ No newline at end of file diff --git a/generate/database/readme.md b/generate/database/readme.md new file mode 100644 index 0000000..4db6e02 --- /dev/null +++ b/generate/database/readme.md @@ -0,0 +1,39 @@ +# migrate +數據庫遷移工具 + +[golang-migrate](https://github.com/golang-migrate/migrate) + +## 安裝 make +```shell +brew install Makefile +``` + +## 安裝 golang-migrate +```shell +brew install golang-migrate +``` + +## 執行刪除 mysql schema + +```shell +migrate -source file://database/migrations/mysql -database 'mysql://account:password@tcp(127.0.0.1:3306)/esc_c2c' down +``` + +## 執行安裝 mysql schema + +```shell +migrate -source file://database/migrations/mysql -database 'mysql://account:password@tcp(127.0.0.1:3306)/esc_c2c' up +``` + +## 執行刪除 mongo schema + +```shell +migrate -source file://database/migrations/mongodb -database 'mongodb://127.0.0.1:27017/esc_c2c' down +``` + +## 執行安裝 mongo schema + +```shell +migrate -source file://database/migrations/mongodb -database 'mongodb://127.0.0.1:27017/esc_c2c' up +``` + diff --git a/generate/protobuf/member.proto b/generate/protobuf/member.proto new file mode 100644 index 0000000..932e3dd --- /dev/null +++ b/generate/protobuf/member.proto @@ -0,0 +1,214 @@ +syntax = "proto3"; + +package member; +option go_package="./member"; + +// ================ enum ================ +enum VerifyType { + VERIFY_NONE = 0; // 初始(異常) + VERIFY_EMAIL = 1; + VERIFY_PHONE = 2; + VERIFY_GOOGLE = 3; +} + +enum AlarmType { + ALARM_NONE = 0; // 初始(異常) + ALARM_NOT = 1; // 未告警 + ALARM_SYSTEM = 2; // 系統告警中 +} + +enum MemberStatus { + STATUS_NONE = 0; // 初始(異常) + STATUS_VERIFY = 1; // 尚未驗證 + STATUS_COMPLETE = 2; // 帳號啟用中 + STATUS_DISABLE = 3; // 帳號停權中 + STATUS_EMAIL = 4; // 信箱以驗證 + STATUS_PHONE = 5; // 手機以驗證 + STATUS_GA = 6; // GA 已綁定 +} + +enum Gender { + GENDER_NONE = 0; // 初始(未提供) + GENDER_MALE = 1; // 男性 + GENDER_FEMALE = 2; // 女性 +} +// ================ enum ================ + + +// ================ common ================ +message Pager { + int64 total =1; + int64 size=2; + int64 index=3; +} + +message Response { + BaseResp status=1; +} + +message BaseResp { + string code = 1; + string message = 2; + string error = 3; +} + +// ================ common ================ + + +// ================ account ================ +message CreateLoginUserReq { + string login_id = 1; + int64 platform = 2; + string token = 3; +} + +message BindingUserReq { + string uid = 1; + string login_id = 2; +} + +message CreateUserInfoReq { + string uid = 1; + VerifyType verify_type = 2; + AlarmType alarm_type = 3; + MemberStatus status = 4; + string language = 5; + string currency = 6; + optional string nick_name = 7; + optional uint32 gender = 8; + optional int64 birthday = 9; +} + +message GetAccountInfoResp { + BaseResp status = 1; + CreateLoginUserReq data = 2; +} + +// UpdateUserInfoReq 不處理邏輯給不給改,這裡只關新增修改刪除 +message UpdateUserInfoReq { + string uid = 1; + optional string language = 2; + optional string currency = 3; + optional string nick_name = 4; + optional uint32 gender = 5; + optional int64 birthday = 6; + optional VerifyType verify_type = 7; + optional AlarmType alarm_type = 8; + optional MemberStatus status = 9; +} + +message GetUIDByAccountReq { + string account = 1; +} + +message UID { + string uid = 1; +} + +message GetUidByAccountResp { + BaseResp status = 1; + UID data = 2; +} + +message UpdateTokenReq { + string account = 1; + string token = 2; +} + +message GenerateRefreshCodeReq { + string account = 1; + int32 code_type =2; +} + +message VerifyCode { + string verify_code = 1; +} + +message GenerateRefreshCodeResp { + BaseResp status = 1; + VerifyCode data = 2; +} + +message VerifyRefreshCodeReq { + string account = 1; + int32 code_type =2; + string verify_code = 3; +} + +message UpdateStatusReq { + string uid = 1; + MemberStatus status = 2; +} + +message GetUserInfoReq { + string uid = 1; + optional string nick_name =2; +} + +message UserInfo { + string uid = 1; + VerifyType verify_type = 2; + AlarmType alarm_type = 3; + MemberStatus status = 4; + string language = 5; + string currency = 6; + optional string nick_name = 7; + optional uint32 gender = 8; + optional int64 birthday = 9; +} + +message GetUserInfoResp { + BaseResp status = 1; + UserInfo data = 2; +} + +message ListUserInfoReq { + optional VerifyType verify_type = 1; + optional AlarmType alarm_type = 2; + optional MemberStatus status = 3; + optional int64 create_start_time = 4; + optional int64 create_end_time = 5; + int64 page_size =6; + int64 page_index=7; +} + +message ListUserInfoResp { + BaseResp status = 1; + repeated UserInfo data = 2; + Pager page =3; +} + + +service Account { + // CreateUserAccount 建立帳號與密碼 -> 可登入,但可不可以做其他事情看業務流程,也可以只註冊就好 + rpc CreateUserAccount(CreateLoginUserReq) returns(Response); + // GetUserAccountInfo 取得帳號密碼資料 + rpc GetUserAccountInfo(GetUIDByAccountReq) returns(GetAccountInfoResp); + // UpdateUserToken 更新密碼 + rpc UpdateUserToken(UpdateTokenReq) returns(Response); + + + // GetUidByAccount 用帳號換取 UID + rpc GetUidByAccount(GetUIDByAccountReq) returns(GetUidByAccountResp); + // BindAccount 綁定帳號 -> account bind to UID + rpc BindAccount(BindingUserReq) returns(Response); + + + // BindUserInfo 初次,綁定 User Info + rpc BindUserInfo(CreateUserInfoReq) returns(Response); + // UpdateUserInfo 更新 User Info + rpc UpdateUserInfo(UpdateUserInfoReq) returns(Response); + // UpdateStatus 修改狀態 + rpc UpdateStatus(UpdateStatusReq) returns(Response); + // UpdateStatus 取得會員資訊 + rpc GetUserInfo(GetUserInfoReq) returns(GetUserInfoResp); + // ListMember 取得會員列表 + rpc ListMember(ListUserInfoReq) returns(ListUserInfoResp); + + // GenerateRefreshCode 這個帳號驗證碼(十分鐘),通用的 + rpc GenerateRefreshCode(GenerateRefreshCodeReq) returns(GenerateRefreshCodeResp); + // VerifyRefreshCode 驗證忘記密碼 token + rpc VerifyRefreshCode(VerifyRefreshCodeReq) returns(Response); + +} +// ================ account ================ \ No newline at end of file -- 2.40.1 From 518cb03b4b3c6d25d56e5cdffe6d9a2cd7cc4a91 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Wed, 21 Aug 2024 08:21:29 +0800 Subject: [PATCH 2/7] generate account --- Makefile | 49 +++++++++++ .../20230529020011_account_uid_table.up.sql | 1 + .../mysql/20230529020011_user_table.up.sql | 11 ++- .../protobuf/{member.proto => service.proto} | 15 ++-- go.mod | 88 +++++++++++++++++++ internal/config/config.go | 7 ++ internal/svc/service_context.go | 13 +++ service.go | 39 ++++++++ 8 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 Makefile rename generate/protobuf/{member.proto => service.proto} (95%) create mode 100644 go.mod create mode 100755 internal/config/config.go create mode 100644 internal/svc/service_context.go create mode 100644 service.go diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1d51c21 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +GO_CTL_NAME=goctl + +# go-zero 生成風格 +GO_ZERO_STYLE=go_zero + +GO ?= go +GOFMT ?= gofmt "-s" +GOFILES := $(shell find . -name "*.go") +LDFLAGS := -s -w +VERSION="v1.0.3" +DOCKER_REPO="igs170911/notification" + +.PHONY: test +test: # 進行測試 + go test -v --cover ./... + +.PHONY: fmt +fmt: # 格式優化 + $(GOFMT) -w $(GOFILES) + goimports -w ./ + +.PHONY: gen-rpc +gen-rpc: # 建立 rpc code + $(GO_CTL_NAME) rpc protoc ./generate/protobuf/service.proto -m --style=$(GO_ZERO_STYLE) --go_out=./gen_result/pb --go-grpc_out=./gen_result/pb --zrpc_out=. + copy ./etc/service.yaml ./etc/service.example.yaml + go mod tidy + @echo "Generate core-api files successfully" + +.PHONY: gen-clean +gen-clean: # 建立 rpc code + rm -rf ./client + rm -rf ./etc + rm -rf ./gen_result + rm -rf ./internal + rm -rf go.mod + rm -rf go.sum + rm -rf service.go + @echo "Generate core-api files successfully" + +.PHONY: run-docker +run-docker: # 建立 rpc code + docker run --platform=linux/arm64/v8 -p 8080:8080 $(DOCKER_REPO):$(VERSION) + +.PHONY: build-docker +build-docker: + cp ./build/Dockerfile Dockerfile + docker buildx build -t $(DOCKER_REPO):$(VERSION) --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/ed_25519)" . + rm -rf Dockerfile + @echo "Generate core-api files successfully" diff --git a/generate/database/mysql/20230529020011_account_uid_table.up.sql b/generate/database/mysql/20230529020011_account_uid_table.up.sql index bf48c07..3d7b5e6 100644 --- a/generate/database/mysql/20230529020011_account_uid_table.up.sql +++ b/generate/database/mysql/20230529020011_account_uid_table.up.sql @@ -2,6 +2,7 @@ CREATE TABLE `account_to_uid` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `account` VARCHAR(50) NOT NULL, `uid` VARCHAR(255) NOT NULL, + `type` tinyint DEFAULT 0 NOT NULL COMMENT '1 手機 2 信箱 3 自定義帳號', PRIMARY KEY (`id`), UNIQUE INDEX `uk_account` (`account` ASC), INDEX `idx_uid` (`uid` ASC) diff --git a/generate/database/mysql/20230529020011_user_table.up.sql b/generate/database/mysql/20230529020011_user_table.up.sql index 40f58c5..ce8a45d 100644 --- a/generate/database/mysql/20230529020011_user_table.up.sql +++ b/generate/database/mysql/20230529020011_user_table.up.sql @@ -3,12 +3,11 @@ CREATE TABLE `user_table` ( `verify_type` tinyint DEFAULT 0 NOT NULL COMMENT '驗證類型 0. 異常 1.信箱 2.手機 3. GA 4.不驗證', `alarm_type` tinyint DEFAULT 0 NOT NULL COMMENT '告警狀態 0. 異常 1. 正常(未告警) 2.系統告警中', `status` tinyint DEFAULT 0 NOT NULL COMMENT '會員狀態 0. 異常 1. 尚未驗證 2. 啟用 3. 停權中 4. 信箱以驗證 5. 手機以驗證 6. GA 以驗證', - `uid` VARCHAR(255) NOT NULL, - `language` VARCHAR(255) NOT NULL DEFAULT '', - `currency` VARCHAR(255) NOT NULL DEFAULT '', - `nick_name` VARCHAR(255) DEFAULT '', - `gender` tinyint DEFAULT 0 NOT NULL COMMENT '0. 不願透露, 1 男 2 女', - `birthday` INT NOT NULL DEFAULT 0, + `uid` VARCHAR(255) NOT NULL COMMENT '唯一辨識碼', + `nick_name` VARCHAR(255) DEFAULT '' COMMENT '暱稱', + `language` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '使用語言', + `currency` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '使用幣別', + `avatar` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '會員頭像', `create_time` BIGINT NOT NULL DEFAULT 0, `update_time` BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), diff --git a/generate/protobuf/member.proto b/generate/protobuf/service.proto similarity index 95% rename from generate/protobuf/member.proto rename to generate/protobuf/service.proto index 932e3dd..e9ab8a8 100644 --- a/generate/protobuf/member.proto +++ b/generate/protobuf/service.proto @@ -8,7 +8,7 @@ enum VerifyType { VERIFY_NONE = 0; // 初始(異常) VERIFY_EMAIL = 1; VERIFY_PHONE = 2; - VERIFY_GOOGLE = 3; + VERIFY_GOOGLE = 3; // google 驗證器 } enum AlarmType { @@ -65,6 +65,7 @@ message CreateLoginUserReq { message BindingUserReq { string uid = 1; string login_id = 2; + int64 type = 3; } message CreateUserInfoReq { @@ -152,9 +153,8 @@ message UserInfo { MemberStatus status = 4; string language = 5; string currency = 6; - optional string nick_name = 7; - optional uint32 gender = 8; - optional int64 birthday = 9; + string avatar = 7; + optional string nick_name = 8; } message GetUserInfoResp { @@ -186,25 +186,20 @@ service Account { rpc GetUserAccountInfo(GetUIDByAccountReq) returns(GetAccountInfoResp); // UpdateUserToken 更新密碼 rpc UpdateUserToken(UpdateTokenReq) returns(Response); - - // GetUidByAccount 用帳號換取 UID rpc GetUidByAccount(GetUIDByAccountReq) returns(GetUidByAccountResp); // BindAccount 綁定帳號 -> account bind to UID rpc BindAccount(BindingUserReq) returns(Response); - - // BindUserInfo 初次,綁定 User Info rpc BindUserInfo(CreateUserInfoReq) returns(Response); // UpdateUserInfo 更新 User Info rpc UpdateUserInfo(UpdateUserInfoReq) returns(Response); // UpdateStatus 修改狀態 rpc UpdateStatus(UpdateStatusReq) returns(Response); - // UpdateStatus 取得會員資訊 + // GetUserInfo 取得會員資訊 rpc GetUserInfo(GetUserInfoReq) returns(GetUserInfoResp); // ListMember 取得會員列表 rpc ListMember(ListUserInfoReq) returns(ListUserInfoResp); - // GenerateRefreshCode 這個帳號驗證碼(十分鐘),通用的 rpc GenerateRefreshCode(GenerateRefreshCodeReq) returns(GenerateRefreshCodeResp); // VerifyRefreshCode 驗證忘記密碼 token diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d075de8 --- /dev/null +++ b/go.mod @@ -0,0 +1,88 @@ +module app-cloudep-member-server + +go 1.22.3 + +require ( + github.com/zeromicro/go-zero v1.7.0 + google.golang.org/grpc v1.65.0 + google.golang.org/protobuf v1.34.2 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/fatih/color v1.17.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/openzipkin/zipkin-go v0.4.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/redis/go-redis/v9 v9.6.1 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + go.etcd.io/etcd/api/v3 v3.5.15 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect + go.etcd.io/etcd/client/v3 v3.5.15 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/automaxprocs v1.5.3 // indirect + go.uber.org/multierr v1.9.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.29.3 // indirect + k8s.io/apimachinery v0.29.4 // indirect + k8s.io/client-go v0.29.3 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100755 index 0000000..c1f85b9 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,7 @@ +package config + +import "github.com/zeromicro/go-zero/zrpc" + +type Config struct { + zrpc.RpcServerConf +} diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go new file mode 100644 index 0000000..127530e --- /dev/null +++ b/internal/svc/service_context.go @@ -0,0 +1,13 @@ +package svc + +import "app-cloudep-member-server/internal/config" + +type ServiceContext struct { + Config config.Config +} + +func NewServiceContext(c config.Config) *ServiceContext { + return &ServiceContext{ + Config: c, + } +} diff --git a/service.go b/service.go new file mode 100644 index 0000000..19081ec --- /dev/null +++ b/service.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + "fmt" + + "app-cloudep-member-server/gen_result/pb/member" + "app-cloudep-member-server/internal/config" + accountServer "app-cloudep-member-server/internal/server/account" + "app-cloudep-member-server/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/service" + "github.com/zeromicro/go-zero/zrpc" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +var configFile = flag.String("f", "etc/service.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + ctx := svc.NewServiceContext(c) + + s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) { + member.RegisterAccountServer(grpcServer, accountServer.NewAccountServer(ctx)) + + if c.Mode == service.DevMode || c.Mode == service.TestMode { + reflection.Register(grpcServer) + } + }) + defer s.Stop() + + fmt.Printf("Starting rpc server at %s...\n", c.ListenOn) + s.Start() +} -- 2.40.1 From 5aff70ae2fe8641dcf57b47fde250d5627e8ded7 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Wed, 21 Aug 2024 16:12:34 +0800 Subject: [PATCH 3/7] add uid generate --- Makefile | 18 +++ generate/protobuf/service.proto | 65 +++------ go.mod | 12 ++ internal/config/config.go | 28 +++- internal/domain/const.go | 18 +++ internal/domain/usecase/errors.go | 21 +++ internal/domain/usecase/uid_generate.go | 7 + internal/lib/middleware/with_context.go | 27 ++++ internal/lib/snackflow/error.go | 18 +++ internal/lib/snackflow/error_test.go | 54 +++++++ internal/lib/snackflow/readme.md | 8 ++ internal/lib/snackflow/snowflake.go | 81 +++++++++++ internal/lib/snackflow/snowflake_test.go | 148 +++++++++++++++++++ internal/model/account_model.go | 27 ++++ internal/model/account_model_gen.go | 154 ++++++++++++++++++++ internal/model/account_to_uid_model.go | 27 ++++ internal/model/account_to_uid_model_gen.go | 152 ++++++++++++++++++++ internal/model/machine_node_model.go | 27 ++++ internal/model/machine_node_model_gen.go | 117 +++++++++++++++ internal/model/mongo/auto_id_model.go | 46 ++++++ internal/model/mongo/auto_id_model_gen.go | 77 ++++++++++ internal/model/mongo/auto_id_types.go | 15 ++ internal/model/mongo/error.go | 12 ++ internal/model/user_table_model.go | 27 ++++ internal/model/user_table_model_gen.go | 159 +++++++++++++++++++++ internal/model/vars.go | 5 + internal/svc/service_context.go | 49 ++++++- internal/usecase/google_authenticator.go | 1 + internal/usecase/uid_generate.go | 75 ++++++++++ 29 files changed, 1428 insertions(+), 47 deletions(-) create mode 100644 internal/domain/const.go create mode 100644 internal/domain/usecase/errors.go create mode 100644 internal/domain/usecase/uid_generate.go create mode 100644 internal/lib/middleware/with_context.go create mode 100644 internal/lib/snackflow/error.go create mode 100644 internal/lib/snackflow/error_test.go create mode 100644 internal/lib/snackflow/readme.md create mode 100644 internal/lib/snackflow/snowflake.go create mode 100644 internal/lib/snackflow/snowflake_test.go create mode 100755 internal/model/account_model.go create mode 100755 internal/model/account_model_gen.go create mode 100755 internal/model/account_to_uid_model.go create mode 100755 internal/model/account_to_uid_model_gen.go create mode 100755 internal/model/machine_node_model.go create mode 100755 internal/model/machine_node_model_gen.go create mode 100644 internal/model/mongo/auto_id_model.go create mode 100644 internal/model/mongo/auto_id_model_gen.go create mode 100644 internal/model/mongo/auto_id_types.go create mode 100644 internal/model/mongo/error.go create mode 100755 internal/model/user_table_model.go create mode 100755 internal/model/user_table_model_gen.go create mode 100644 internal/model/vars.go create mode 100644 internal/usecase/google_authenticator.go create mode 100644 internal/usecase/uid_generate.go diff --git a/Makefile b/Makefile index 1d51c21..6d0df19 100644 --- a/Makefile +++ b/Makefile @@ -47,3 +47,21 @@ build-docker: docker buildx build -t $(DOCKER_REPO):$(VERSION) --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/ed_25519)" . rm -rf Dockerfile @echo "Generate core-api files successfully" + +.PHONY: gen-model +gen-model: # 建立 rpc 資料庫 + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_table.up.sql --style go_zero -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_uid_table.up.sql --style go_zero -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_user_table.up.sql --style go_zero -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230719061241_machine_node.up.sql --style go_zero -d ./internal/model -i '' + @echo "Generate model files successfully" + # 只產生 Model 剩下的要自己撰寫,連欄位名稱也是 + goctl model mongo -t AutoId -c --dir ./internal/model/mongo --style go_zero + +#goctl model mysql ddl -s ./generate/database/mysql/20240819090248_create_role_permission_table.up.sql --style go_zero -d ./internal/model -i '' (沒cache) +#goctl model mysql ddl -c no -s ./generate/database/mysql/20240816014305_create_permission_table.up.sql --style go_zero -d ./internal/model -i '' (有cache) + +#.PHONY: mock-gen +#mock-gen: # 建立 mock 資料 +# mockgen -source=./order.go -destination=../../repository/mock/order.go -package=mock +# @echo "Generate model files successfully" \ No newline at end of file diff --git a/generate/protobuf/service.proto b/generate/protobuf/service.proto index e9ab8a8..98a47fa 100644 --- a/generate/protobuf/service.proto +++ b/generate/protobuf/service.proto @@ -3,6 +3,11 @@ syntax = "proto3"; package member; option go_package="./member"; +// OKResp +message OKResp {} +// NoneReq +message NoneReq {} + // ================ enum ================ enum VerifyType { VERIFY_NONE = 0; // 初始(異常) @@ -27,11 +32,6 @@ enum MemberStatus { STATUS_GA = 6; // GA 已綁定 } -enum Gender { - GENDER_NONE = 0; // 初始(未提供) - GENDER_MALE = 1; // 男性 - GENDER_FEMALE = 2; // 女性 -} // ================ enum ================ @@ -41,17 +41,6 @@ message Pager { int64 size=2; int64 index=3; } - -message Response { - BaseResp status=1; -} - -message BaseResp { - string code = 1; - string message = 2; - string error = 3; -} - // ================ common ================ @@ -81,8 +70,7 @@ message CreateUserInfoReq { } message GetAccountInfoResp { - BaseResp status = 1; - CreateLoginUserReq data = 2; + CreateLoginUserReq data = 1; } // UpdateUserInfoReq 不處理邏輯給不給改,這裡只關新增修改刪除 @@ -91,24 +79,18 @@ message UpdateUserInfoReq { optional string language = 2; optional string currency = 3; optional string nick_name = 4; - optional uint32 gender = 5; - optional int64 birthday = 6; - optional VerifyType verify_type = 7; - optional AlarmType alarm_type = 8; - optional MemberStatus status = 9; + optional VerifyType verify_type = 5; + optional AlarmType alarm_type = 6; + optional MemberStatus status = 7; } message GetUIDByAccountReq { string account = 1; } -message UID { - string uid = 1; -} - message GetUidByAccountResp { - BaseResp status = 1; - UID data = 2; + string uid = 1; + string account =2; } message UpdateTokenReq { @@ -126,8 +108,7 @@ message VerifyCode { } message GenerateRefreshCodeResp { - BaseResp status = 1; - VerifyCode data = 2; + VerifyCode data = 1; } message VerifyRefreshCodeReq { @@ -158,8 +139,7 @@ message UserInfo { } message GetUserInfoResp { - BaseResp status = 1; - UserInfo data = 2; + UserInfo data = 1; } message ListUserInfoReq { @@ -173,29 +153,28 @@ message ListUserInfoReq { } message ListUserInfoResp { - BaseResp status = 1; - repeated UserInfo data = 2; - Pager page =3; + repeated UserInfo data = 1; + Pager page =2; } service Account { // CreateUserAccount 建立帳號與密碼 -> 可登入,但可不可以做其他事情看業務流程,也可以只註冊就好 - rpc CreateUserAccount(CreateLoginUserReq) returns(Response); + rpc CreateUserAccount(CreateLoginUserReq) returns(OKResp); // GetUserAccountInfo 取得帳號密碼資料 rpc GetUserAccountInfo(GetUIDByAccountReq) returns(GetAccountInfoResp); // UpdateUserToken 更新密碼 - rpc UpdateUserToken(UpdateTokenReq) returns(Response); + rpc UpdateUserToken(UpdateTokenReq) returns(OKResp); // GetUidByAccount 用帳號換取 UID rpc GetUidByAccount(GetUIDByAccountReq) returns(GetUidByAccountResp); // BindAccount 綁定帳號 -> account bind to UID - rpc BindAccount(BindingUserReq) returns(Response); + rpc BindAccount(BindingUserReq) returns(OKResp); // BindUserInfo 初次,綁定 User Info - rpc BindUserInfo(CreateUserInfoReq) returns(Response); + rpc BindUserInfo(CreateUserInfoReq) returns(OKResp); // UpdateUserInfo 更新 User Info - rpc UpdateUserInfo(UpdateUserInfoReq) returns(Response); + rpc UpdateUserInfo(UpdateUserInfoReq) returns(OKResp); // UpdateStatus 修改狀態 - rpc UpdateStatus(UpdateStatusReq) returns(Response); + rpc UpdateStatus(UpdateStatusReq) returns(OKResp); // GetUserInfo 取得會員資訊 rpc GetUserInfo(GetUserInfoReq) returns(GetUserInfoResp); // ListMember 取得會員列表 @@ -203,7 +182,7 @@ service Account { // GenerateRefreshCode 這個帳號驗證碼(十分鐘),通用的 rpc GenerateRefreshCode(GenerateRefreshCodeReq) returns(GenerateRefreshCodeResp); // VerifyRefreshCode 驗證忘記密碼 token - rpc VerifyRefreshCode(VerifyRefreshCodeReq) returns(Response); + rpc VerifyRefreshCode(VerifyRefreshCodeReq) returns(OKResp); } // ================ account ================ \ No newline at end of file diff --git a/go.mod b/go.mod index d075de8..13b294d 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,17 @@ module app-cloudep-member-server go 1.22.3 require ( + code.30cm.net/digimon/library-go/errors v1.0.1 + code.30cm.net/digimon/library-go/validator v1.0.0 + github.com/bwmarrin/snowflake v0.3.0 github.com/zeromicro/go-zero v1.7.0 + go.uber.org/goleak v1.3.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 ) require ( + filippo.io/edwards25519 v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -18,11 +23,16 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/fatih/color v1.17.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -33,6 +43,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -65,6 +76,7 @@ require ( go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect golang.org/x/sys v0.22.0 // indirect diff --git a/internal/config/config.go b/internal/config/config.go index c1f85b9..696a3f7 100755 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,7 +1,33 @@ package config -import "github.com/zeromicro/go-zero/zrpc" +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/zrpc" +) type Config struct { zrpc.RpcServerConf + // 加上 DB 結構體 + DB struct { + DsnString string + } + // 快取 + Cache cache.CacheConf + // 密碼加密層數 + Bcrypt struct { + Cost int + } + // Redis Cluster + RedisCluster redis.RedisConf + + Mongo struct { + Schema string + User string + Password string + Host string + Port string + Database string + Collection string + } } diff --git a/internal/domain/const.go b/internal/domain/const.go new file mode 100644 index 0000000..5279edd --- /dev/null +++ b/internal/domain/const.go @@ -0,0 +1,18 @@ +package domain + +const ( + DefaultPageSize = 100 + DefaultPageIndex = 1 + Scope = 10 +) + +const InitAutoId = 1000000 +const DefaultReferralCodeLen = 8 + +var ConvertTable = [...]string{ + "O", "D", "W", "X", "Y", + "G", "B", "C", "H", "E", + "F", "A", "Q", "I", "J", + "L", "M", "N", "Z", "K", + "P", "V", "R", "S", "T", +} diff --git a/internal/domain/usecase/errors.go b/internal/domain/usecase/errors.go new file mode 100644 index 0000000..0455dfa --- /dev/null +++ b/internal/domain/usecase/errors.go @@ -0,0 +1,21 @@ +package usecase + +import ( + ers "code.30cm.net/digimon/library-go/errors" + "code.30cm.net/digimon/library-go/errors/code" +) + +// 12 represents Scope +// 100 represents Category +// 9 represents Detail error code +// full code 12009 只會有 系統以及錯誤碼,category 是給系統判定用的 +// 目前 Scope 以及分類要系統共用,係向的錯誤各自服務實作就好 + +const ( + UIDOutOfRangeErrorCode = iota + 1 +) + +// UIDOutOfRangeErrorCodeError 20001 Token 簽名錯誤 +func UIDOutOfRangeErrorCodeError(msg string) *ers.LibError { + return ers.NewErr(code.CloudEPMember, code.CatInput, UIDOutOfRangeErrorCode, msg) +} diff --git a/internal/domain/usecase/uid_generate.go b/internal/domain/usecase/uid_generate.go new file mode 100644 index 0000000..3f9bbb8 --- /dev/null +++ b/internal/domain/usecase/uid_generate.go @@ -0,0 +1,7 @@ +package usecase + +import "context" + +type UIDGenerateUseCase interface { + Generate(ctx context.Context) (string, error) +} diff --git a/internal/lib/middleware/with_context.go b/internal/lib/middleware/with_context.go new file mode 100644 index 0000000..39d8a05 --- /dev/null +++ b/internal/lib/middleware/with_context.go @@ -0,0 +1,27 @@ +package middleware + +import ( + ers "code.30cm.net/digimon/library-go/errors" + "context" + "errors" + "github.com/zeromicro/go-zero/core/logx" + "google.golang.org/grpc" + "time" +) + +const defaultTimeout = 30 * time.Second + +func TimeoutMiddleware(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { + + newCtx, cancelCtx := context.WithTimeout(ctx, defaultTimeout) + defer func() { + cancelCtx() + + if errors.Is(newCtx.Err(), context.DeadlineExceeded) { + err = ers.SystemTimeoutError(info.FullMethod) + logx.Errorf("Method: %s, request %v, timeout: %d", info.FullMethod, req, defaultTimeout) + } + }() + + return handler(ctx, req) +} diff --git a/internal/lib/snackflow/error.go b/internal/lib/snackflow/error.go new file mode 100644 index 0000000..45327f2 --- /dev/null +++ b/internal/lib/snackflow/error.go @@ -0,0 +1,18 @@ +package snowflake + +import ( + "fmt" + "time" +) + +type NewNodeError struct { + machineNodeID int64 + startTime time.Time + + Err error +} + +func (e *NewNodeError) Error() string { + return fmt.Sprintf("new node fail machineNodeID: %d, startTime: %s, err: %v", + e.machineNodeID, e.startTime, e.Err) +} diff --git a/internal/lib/snackflow/error_test.go b/internal/lib/snackflow/error_test.go new file mode 100644 index 0000000..48c64b4 --- /dev/null +++ b/internal/lib/snackflow/error_test.go @@ -0,0 +1,54 @@ +package snowflake + +import ( + "fmt" + "testing" + "time" +) + +func TestNewNodeError_Error(t *testing.T) { + startTime, err := time.Parse(time.DateOnly, "2023-07-20") + if err != nil { + t.Error(err) + } + + t.Parallel() + + type fields struct { + machineNodeID int64 + startTime time.Time + Err error + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "success", + fields: fields{ + machineNodeID: 1, + startTime: startTime, + Err: nil, + }, + want: fmt.Sprintf("new node fail machineNodeID: %d, startTime: %s, err: %v", + 1, "2023-07-20 00:00:00 +0000 UTC", nil), + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + e := &NewNodeError{ + machineNodeID: tt.fields.machineNodeID, + startTime: tt.fields.startTime, + Err: tt.fields.Err, + } + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/lib/snackflow/readme.md b/internal/lib/snackflow/readme.md new file mode 100644 index 0000000..bdf2d8d --- /dev/null +++ b/internal/lib/snackflow/readme.md @@ -0,0 +1,8 @@ +### +# snowflake + +```go +import "yt.com/backend/common.git/snowflake" +``` + +### 量級超過1024 再來做解決 \ No newline at end of file diff --git a/internal/lib/snackflow/snowflake.go b/internal/lib/snackflow/snowflake.go new file mode 100644 index 0000000..09f3fb6 --- /dev/null +++ b/internal/lib/snackflow/snowflake.go @@ -0,0 +1,81 @@ +package snowflake + +import ( + "fmt" + "sync" + "time" + + "github.com/bwmarrin/snowflake" +) + +var mu sync.Mutex + +// Snowflake provides a way to NewNode for Generate UID. +type Snowflake struct { + machineNodeID int64 + + startTime time.Time +} + +// Option is the options type to configure Snowflake. +type Option func(*Snowflake) + +// New returns a new Snowflake instance with the provided options. +func New(opts ...Option) *Snowflake { + s := &Snowflake{ + // default machine 1 + machineNodeID: 1, + } + + for _, opt := range opts { + opt(s) + } + + return s +} + +// WithMachineNodeID adds machineID total 10bit = 1024 machine number. +func WithMachineNodeID(machineNodeID int64) Option { + return func(snowflake *Snowflake) { + snowflake.machineNodeID = machineNodeID + } +} + +// WithStartTime adds snowflake start timestamp in milliseconds. +func WithStartTime(startTime time.Time) Option { + return func(snowflake *Snowflake) { + snowflake.startTime = startTime + } +} + +// GetNowDate return nowTodayDate e.g. 2023-07-20 00:00:00 +0000 UTC. +func GetNowDate() (time.Time, error) { + startTime := time.Now().UTC().Format(time.DateOnly) + + st, err := time.Parse(time.DateOnly, startTime) + if err != nil { + return time.Time{}, fmt.Errorf("time.Parse failed :%w", err) + } + + return st, nil +} + +// NewNode return snowflake node use Generate UID. +func (s *Snowflake) NewNode() (*snowflake.Node, error) { + mu.Lock() + defer mu.Unlock() + + snowflake.Epoch = s.startTime.UnixMilli() + + node, err := snowflake.NewNode(s.machineNodeID) + if err != nil { + return nil, fmt.Errorf("snowflake.NewNode, failed :%w", + &NewNodeError{ + machineNodeID: s.machineNodeID, + startTime: s.startTime, + Err: err, + }) + } + + return node, nil +} diff --git a/internal/lib/snackflow/snowflake_test.go b/internal/lib/snackflow/snowflake_test.go new file mode 100644 index 0000000..2b477af --- /dev/null +++ b/internal/lib/snackflow/snowflake_test.go @@ -0,0 +1,148 @@ +package snowflake + +import ( + "flag" + "os" + "reflect" + "testing" + "time" + + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + leak := flag.Bool("leak", false, "use leak detector") + flag.Parse() + + if *leak { + goleak.VerifyTestMain(m) + + return + } + + os.Exit(m.Run()) +} + +func TestSnowflake(t *testing.T) { + st, err := GetNowDate() + if err != nil { + t.Error(err) + } + + t.Parallel() + + type args struct { + machineNodeID int64 + startTime time.Time + } + tests := []struct { + name string + args args + want *Snowflake + + wantDeepEqualErr bool + wantNewNodeErr bool + }{ + { + name: "success", + args: args{ + machineNodeID: 10, + startTime: st, + }, + want: &Snowflake{ + machineNodeID: 10, + startTime: st, + }, + wantDeepEqualErr: false, + wantNewNodeErr: false, + }, + { + name: "failed machine node ID negative number", + args: args{ + machineNodeID: -1, + startTime: time.Time{}, + }, + want: &Snowflake{ + machineNodeID: -1, + startTime: time.Time{}, + }, + wantDeepEqualErr: false, + wantNewNodeErr: true, + }, + { + name: "failed snowflake struct field by machine node ID", + args: args{ + machineNodeID: 10, + startTime: st, + }, + want: &Snowflake{ + machineNodeID: 2, + startTime: st, + }, + wantDeepEqualErr: true, + wantNewNodeErr: false, + }, + { + name: "failed snowflake struct field by startTime", + args: args{ + machineNodeID: 2, + startTime: st, + }, + want: &Snowflake{ + machineNodeID: 2, + startTime: time.Time{}, + }, + wantDeepEqualErr: true, + wantNewNodeErr: false, + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got := New( + WithMachineNodeID(tt.args.machineNodeID), + WithStartTime(tt.args.startTime), + ) + + if !reflect.DeepEqual(got, tt.want) != tt.wantDeepEqualErr { + t.Errorf("Snowflake.New() = %v, want %v", got, tt.want) + } + + node, err := got.NewNode() + if (err != nil) != tt.wantNewNodeErr { + t.Errorf("NewNode() = %v, want %v", err != nil, tt.wantNewNodeErr) + } + + if err == nil { + id := node.Generate().Int64() + if id <= 0 { + t.Errorf("node.Generate().Int64() = %v, want %s", id, "id > 0") + } + } + }) + } +} + +func BenchmarkSnowflake(b *testing.B) { + st, err := GetNowDate() + if err != nil { + b.Error(err) + } + + snowflake := New( + WithMachineNodeID(1), + WithStartTime(st), + ) + + node, err := snowflake.NewNode() + if err != nil { + b.Error(err) + } + + for i := 0; i < b.N; i++ { + node.Generate().Int64() + } +} diff --git a/internal/model/account_model.go b/internal/model/account_model.go new file mode 100755 index 0000000..958d6dc --- /dev/null +++ b/internal/model/account_model.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ AccountModel = (*customAccountModel)(nil) + +type ( + // AccountModel is an interface to be customized, add more methods here, + // and implement the added methods in customAccountModel. + AccountModel interface { + accountModel + } + + customAccountModel struct { + *defaultAccountModel + } +) + +// NewAccountModel returns a model for the database table. +func NewAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) AccountModel { + return &customAccountModel{ + defaultAccountModel: newAccountModel(conn, c, opts...), + } +} diff --git a/internal/model/account_model_gen.go b/internal/model/account_model_gen.go new file mode 100755 index 0000000..97c22bf --- /dev/null +++ b/internal/model/account_model_gen.go @@ -0,0 +1,154 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + accountFieldNames = builder.RawFieldNames(&Account{}) + accountRows = strings.Join(accountFieldNames, ",") + accountRowsExpectAutoSet = strings.Join(stringx.Remove(accountFieldNames, "`id`"), ",") + accountRowsWithPlaceHolder = strings.Join(stringx.Remove(accountFieldNames, "`id`"), "=?,") + "=?" + + cacheAccountIdPrefix = "cache:account:id:" + cacheAccountAccountPrefix = "cache:account:account:" +) + +type ( + accountModel interface { + Insert(ctx context.Context, data *Account) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Account, error) + FindOneByAccount(ctx context.Context, account string) (*Account, error) + Update(ctx context.Context, data *Account) error + Delete(ctx context.Context, id int64) error + } + + defaultAccountModel struct { + sqlc.CachedConn + table string + } + + Account struct { + Id int64 `db:"id"` + Account string `db:"account"` + Token string `db:"token"` + Platform int64 `db:"platform"` // 平台類型 1. ark 2. google + CreateTime int64 `db:"create_time"` + UpdateTime int64 `db:"update_time"` + } +) + +func newAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultAccountModel { + return &defaultAccountModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`account`", + } +} + +func (m *defaultAccountModel) withSession(session sqlx.Session) *defaultAccountModel { + return &defaultAccountModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`account`", + } +} + +func (m *defaultAccountModel) Delete(ctx context.Context, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, accountAccountKey, accountIdKey) + return err +} + +func (m *defaultAccountModel) FindOne(ctx context.Context, id int64) (*Account, error) { + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, id) + var resp Account + err := m.QueryRowCtx(ctx, &resp, accountIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountModel) FindOneByAccount(ctx context.Context, account string) (*Account, error) { + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, account) + var resp Account + err := m.QueryRowIndexCtx(ctx, &resp, accountAccountKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `account` = ? limit 1", accountRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, account); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountModel) Insert(ctx context.Context, data *Account) (sql.Result, error) { + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, data.Id) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, accountRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.Account, data.Token, data.Platform, data.CreateTime, data.UpdateTime) + }, accountAccountKey, accountIdKey) + return ret, err +} + +func (m *defaultAccountModel) Update(ctx context.Context, newData *Account) error { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, data.Id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, accountRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, newData.Account, newData.Token, newData.Platform, newData.CreateTime, newData.UpdateTime, newData.Id) + }, accountAccountKey, accountIdKey) + return err +} + +func (m *defaultAccountModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheAccountIdPrefix, primary) +} + +func (m *defaultAccountModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultAccountModel) tableName() string { + return m.table +} diff --git a/internal/model/account_to_uid_model.go b/internal/model/account_to_uid_model.go new file mode 100755 index 0000000..095457e --- /dev/null +++ b/internal/model/account_to_uid_model.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ AccountToUidModel = (*customAccountToUidModel)(nil) + +type ( + // AccountToUidModel is an interface to be customized, add more methods here, + // and implement the added methods in customAccountToUidModel. + AccountToUidModel interface { + accountToUidModel + } + + customAccountToUidModel struct { + *defaultAccountToUidModel + } +) + +// NewAccountToUidModel returns a model for the database table. +func NewAccountToUidModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) AccountToUidModel { + return &customAccountToUidModel{ + defaultAccountToUidModel: newAccountToUidModel(conn, c, opts...), + } +} diff --git a/internal/model/account_to_uid_model_gen.go b/internal/model/account_to_uid_model_gen.go new file mode 100755 index 0000000..75aea24 --- /dev/null +++ b/internal/model/account_to_uid_model_gen.go @@ -0,0 +1,152 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + accountToUidFieldNames = builder.RawFieldNames(&AccountToUid{}) + accountToUidRows = strings.Join(accountToUidFieldNames, ",") + accountToUidRowsExpectAutoSet = strings.Join(stringx.Remove(accountToUidFieldNames, "`id`"), ",") + accountToUidRowsWithPlaceHolder = strings.Join(stringx.Remove(accountToUidFieldNames, "`id`"), "=?,") + "=?" + + cacheAccountToUidIdPrefix = "cache:accountToUid:id:" + cacheAccountToUidAccountPrefix = "cache:accountToUid:account:" +) + +type ( + accountToUidModel interface { + Insert(ctx context.Context, data *AccountToUid) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*AccountToUid, error) + FindOneByAccount(ctx context.Context, account string) (*AccountToUid, error) + Update(ctx context.Context, data *AccountToUid) error + Delete(ctx context.Context, id int64) error + } + + defaultAccountToUidModel struct { + sqlc.CachedConn + table string + } + + AccountToUid struct { + Id int64 `db:"id"` + Account string `db:"account"` + Uid string `db:"uid"` + Type int64 `db:"type"` // 1 手機 2 信箱 3 自定義帳號 + } +) + +func newAccountToUidModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultAccountToUidModel { + return &defaultAccountToUidModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`account_to_uid`", + } +} + +func (m *defaultAccountToUidModel) withSession(session sqlx.Session) *defaultAccountToUidModel { + return &defaultAccountToUidModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`account_to_uid`", + } +} + +func (m *defaultAccountToUidModel) Delete(ctx context.Context, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, data.Account) + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, accountToUidAccountKey, accountToUidIdKey) + return err +} + +func (m *defaultAccountToUidModel) FindOne(ctx context.Context, id int64) (*AccountToUid, error) { + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, id) + var resp AccountToUid + err := m.QueryRowCtx(ctx, &resp, accountToUidIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountToUidRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*AccountToUid, error) { + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, account) + var resp AccountToUid + err := m.QueryRowIndexCtx(ctx, &resp, accountToUidAccountKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `account` = ? limit 1", accountToUidRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, account); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAccountToUidModel) Insert(ctx context.Context, data *AccountToUid) (sql.Result, error) { + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, data.Account) + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, data.Id) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, accountToUidRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.Account, data.Uid, data.Type) + }, accountToUidAccountKey, accountToUidIdKey) + return ret, err +} + +func (m *defaultAccountToUidModel) Update(ctx context.Context, newData *AccountToUid) error { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + + accountToUidAccountKey := fmt.Sprintf("%s%v", cacheAccountToUidAccountPrefix, data.Account) + accountToUidIdKey := fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, data.Id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, accountToUidRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, newData.Account, newData.Uid, newData.Type, newData.Id) + }, accountToUidAccountKey, accountToUidIdKey) + return err +} + +func (m *defaultAccountToUidModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheAccountToUidIdPrefix, primary) +} + +func (m *defaultAccountToUidModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", accountToUidRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultAccountToUidModel) tableName() string { + return m.table +} diff --git a/internal/model/machine_node_model.go b/internal/model/machine_node_model.go new file mode 100755 index 0000000..0bd7cd2 --- /dev/null +++ b/internal/model/machine_node_model.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ MachineNodeModel = (*customMachineNodeModel)(nil) + +type ( + // MachineNodeModel is an interface to be customized, add more methods here, + // and implement the added methods in customMachineNodeModel. + MachineNodeModel interface { + machineNodeModel + } + + customMachineNodeModel struct { + *defaultMachineNodeModel + } +) + +// NewMachineNodeModel returns a model for the database table. +func NewMachineNodeModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) MachineNodeModel { + return &customMachineNodeModel{ + defaultMachineNodeModel: newMachineNodeModel(conn, c, opts...), + } +} diff --git a/internal/model/machine_node_model_gen.go b/internal/model/machine_node_model_gen.go new file mode 100755 index 0000000..37d29b5 --- /dev/null +++ b/internal/model/machine_node_model_gen.go @@ -0,0 +1,117 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + machineNodeFieldNames = builder.RawFieldNames(&MachineNode{}) + machineNodeRows = strings.Join(machineNodeFieldNames, ",") + machineNodeRowsExpectAutoSet = strings.Join(stringx.Remove(machineNodeFieldNames, "`id`"), ",") + machineNodeRowsWithPlaceHolder = strings.Join(stringx.Remove(machineNodeFieldNames, "`id`"), "=?,") + "=?" + + cacheMachineNodeIdPrefix = "cache:machineNode:id:" +) + +type ( + machineNodeModel interface { + Insert(ctx context.Context, data *MachineNode) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*MachineNode, error) + Update(ctx context.Context, data *MachineNode) error + Delete(ctx context.Context, id int64) error + } + + defaultMachineNodeModel struct { + sqlc.CachedConn + table string + } + + MachineNode struct { + Id int64 `db:"id"` // 流水號 + CreateTime int64 `db:"create_time"` // 創建時間 + UpdateTime int64 `db:"update_time"` // 更新時間 + HostName string `db:"host_name"` // host name + } +) + +func newMachineNodeModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultMachineNodeModel { + return &defaultMachineNodeModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`machine_node`", + } +} + +func (m *defaultMachineNodeModel) withSession(session sqlx.Session) *defaultMachineNodeModel { + return &defaultMachineNodeModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`machine_node`", + } +} + +func (m *defaultMachineNodeModel) Delete(ctx context.Context, id int64) error { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, id) + _, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, machineNodeIdKey) + return err +} + +func (m *defaultMachineNodeModel) FindOne(ctx context.Context, id int64) (*MachineNode, error) { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, id) + var resp MachineNode + err := m.QueryRowCtx(ctx, &resp, machineNodeIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", machineNodeRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultMachineNodeModel) Insert(ctx context.Context, data *MachineNode) (sql.Result, error) { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, data.Id) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, machineNodeRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.CreateTime, data.UpdateTime, data.HostName) + }, machineNodeIdKey) + return ret, err +} + +func (m *defaultMachineNodeModel) Update(ctx context.Context, data *MachineNode) error { + machineNodeIdKey := fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, data.Id) + _, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, machineNodeRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, data.CreateTime, data.UpdateTime, data.HostName, data.Id) + }, machineNodeIdKey) + return err +} + +func (m *defaultMachineNodeModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheMachineNodeIdPrefix, primary) +} + +func (m *defaultMachineNodeModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", machineNodeRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultMachineNodeModel) tableName() string { + return m.table +} diff --git a/internal/model/mongo/auto_id_model.go b/internal/model/mongo/auto_id_model.go new file mode 100644 index 0000000..bd5d619 --- /dev/null +++ b/internal/model/mongo/auto_id_model.go @@ -0,0 +1,46 @@ +package model + +import ( + "context" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/monc" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" +) + +var _ AutoIdModel = (*customAutoIdModel)(nil) + +type ( + // AutoIdModel is an interface to be customized, add more methods here, + // and implement the added methods in customAutoIdModel. + AutoIdModel interface { + autoIdModel + Inc(ctx context.Context, data *AutoId) error + } + + customAutoIdModel struct { + *defaultAutoIdModel + } +) + +// NewAutoIdModel returns a model for the mongo. +func NewAutoIdModel(url, db, collection string, c cache.CacheConf) AutoIdModel { + conn := monc.MustNewModel(url, db, collection, c) + return &customAutoIdModel{ + defaultAutoIdModel: newDefaultAutoIdModel(conn), + } +} + +func (m *customAutoIdModel) Inc(ctx context.Context, data *AutoId) error { + filter := bson.M{"admin": "auto_id"} + update := bson.M{"$inc": bson.M{"counter": 1}} + + key := prefixAutoIdCacheKey + "count" + + err := m.conn.FindOneAndUpdate(ctx, key, data, filter, update, + options.FindOneAndUpdate().SetUpsert(true), + options.FindOneAndUpdate().SetReturnDocument(options.After), + ) + + return err +} diff --git a/internal/model/mongo/auto_id_model_gen.go b/internal/model/mongo/auto_id_model_gen.go new file mode 100644 index 0000000..5163d74 --- /dev/null +++ b/internal/model/mongo/auto_id_model_gen.go @@ -0,0 +1,77 @@ +// Code generated by goctl. DO NOT EDIT. +package model + +import ( + "context" + "time" + + "github.com/zeromicro/go-zero/core/stores/monc" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" +) + +var prefixAutoIdCacheKey = "cache:autoId:" + +type autoIdModel interface { + Insert(ctx context.Context, data *AutoId) error + FindOne(ctx context.Context, id string) (*AutoId, error) + Update(ctx context.Context, data *AutoId) (*mongo.UpdateResult, error) + Delete(ctx context.Context, id string) (int64, error) +} + +type defaultAutoIdModel struct { + conn *monc.Model +} + +func newDefaultAutoIdModel(conn *monc.Model) *defaultAutoIdModel { + return &defaultAutoIdModel{conn: conn} +} + +func (m *defaultAutoIdModel) Insert(ctx context.Context, data *AutoId) error { + if data.ID.IsZero() { + data.ID = primitive.NewObjectID() + data.CreateAt = time.Now() + data.UpdateAt = time.Now() + } + + key := prefixAutoIdCacheKey + data.ID.Hex() + _, err := m.conn.InsertOne(ctx, key, data) + return err +} + +func (m *defaultAutoIdModel) FindOne(ctx context.Context, id string) (*AutoId, error) { + oid, err := primitive.ObjectIDFromHex(id) + if err != nil { + return nil, ErrInvalidObjectId + } + + var data AutoId + key := prefixAutoIdCacheKey + id + err = m.conn.FindOne(ctx, key, &data, bson.M{"_id": oid}) + switch err { + case nil: + return &data, nil + case monc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultAutoIdModel) Update(ctx context.Context, data *AutoId) (*mongo.UpdateResult, error) { + data.UpdateAt = time.Now() + key := prefixAutoIdCacheKey + data.ID.Hex() + res, err := m.conn.UpdateOne(ctx, key, bson.M{"_id": data.ID}, bson.M{"$set": data}) + return res, err +} + +func (m *defaultAutoIdModel) Delete(ctx context.Context, id string) (int64, error) { + oid, err := primitive.ObjectIDFromHex(id) + if err != nil { + return 0, ErrInvalidObjectId + } + key := prefixAutoIdCacheKey + id + res, err := m.conn.DeleteOne(ctx, key, bson.M{"_id": oid}) + return res, err +} diff --git a/internal/model/mongo/auto_id_types.go b/internal/model/mongo/auto_id_types.go new file mode 100644 index 0000000..3605d9d --- /dev/null +++ b/internal/model/mongo/auto_id_types.go @@ -0,0 +1,15 @@ +package model + +import ( + "time" + + "go.mongodb.org/mongo-driver/bson/primitive" +) + +type AutoId struct { + ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"` + Name string `bson:"name,omitempty" json:"name,omitempty"` + Count uint64 `bson:"count,omitempty" json:"count,omitempty"` + UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"` + CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"` +} diff --git a/internal/model/mongo/error.go b/internal/model/mongo/error.go new file mode 100644 index 0000000..27d9244 --- /dev/null +++ b/internal/model/mongo/error.go @@ -0,0 +1,12 @@ +package model + +import ( + "errors" + + "github.com/zeromicro/go-zero/core/stores/mon" +) + +var ( + ErrNotFound = mon.ErrNotFound + ErrInvalidObjectId = errors.New("invalid objectId") +) diff --git a/internal/model/user_table_model.go b/internal/model/user_table_model.go new file mode 100755 index 0000000..13f2b1d --- /dev/null +++ b/internal/model/user_table_model.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ UserTableModel = (*customUserTableModel)(nil) + +type ( + // UserTableModel is an interface to be customized, add more methods here, + // and implement the added methods in customUserTableModel. + UserTableModel interface { + userTableModel + } + + customUserTableModel struct { + *defaultUserTableModel + } +) + +// NewUserTableModel returns a model for the database table. +func NewUserTableModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) UserTableModel { + return &customUserTableModel{ + defaultUserTableModel: newUserTableModel(conn, c, opts...), + } +} diff --git a/internal/model/user_table_model_gen.go b/internal/model/user_table_model_gen.go new file mode 100755 index 0000000..80a8b5f --- /dev/null +++ b/internal/model/user_table_model_gen.go @@ -0,0 +1,159 @@ +// Code generated by goctl. DO NOT EDIT. + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var ( + userTableFieldNames = builder.RawFieldNames(&UserTable{}) + userTableRows = strings.Join(userTableFieldNames, ",") + userTableRowsExpectAutoSet = strings.Join(stringx.Remove(userTableFieldNames, "`id`"), ",") + userTableRowsWithPlaceHolder = strings.Join(stringx.Remove(userTableFieldNames, "`id`"), "=?,") + "=?" + + cacheUserTableIdPrefix = "cache:userTable:id:" + cacheUserTableUidPrefix = "cache:userTable:uid:" +) + +type ( + userTableModel interface { + Insert(ctx context.Context, data *UserTable) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*UserTable, error) + FindOneByUid(ctx context.Context, uid string) (*UserTable, error) + Update(ctx context.Context, data *UserTable) error + Delete(ctx context.Context, id int64) error + } + + defaultUserTableModel struct { + sqlc.CachedConn + table string + } + + UserTable struct { + Id int64 `db:"id"` + VerifyType int64 `db:"verify_type"` // 驗證類型 0. 異常 1.信箱 2.手機 3. GA 4.不驗證 + AlarmType int64 `db:"alarm_type"` // 告警狀態 0. 異常 1. 正常(未告警) 2.系統告警中 + Status int64 `db:"status"` // 會員狀態 0. 異常 1. 尚未驗證 2. 啟用 3. 停權中 4. 信箱以驗證 5. 手機以驗證 6. GA 以驗證 + Uid string `db:"uid"` // 唯一辨識碼 + NickName string `db:"nick_name"` // 暱稱 + Language string `db:"language"` // 使用語言 + Currency string `db:"currency"` // 使用幣別 + Avatar string `db:"avatar"` // 會員頭像 + CreateTime int64 `db:"create_time"` + UpdateTime int64 `db:"update_time"` + } +) + +func newUserTableModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultUserTableModel { + return &defaultUserTableModel{ + CachedConn: sqlc.NewConn(conn, c, opts...), + table: "`user_table`", + } +} + +func (m *defaultUserTableModel) withSession(session sqlx.Session) *defaultUserTableModel { + return &defaultUserTableModel{ + CachedConn: m.CachedConn.WithSession(session), + table: "`user_table`", + } +} + +func (m *defaultUserTableModel) Delete(ctx context.Context, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, id) + }, userTableIdKey, userTableUidKey) + return err +} + +func (m *defaultUserTableModel) FindOne(ctx context.Context, id int64) (*UserTable, error) { + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, id) + var resp UserTable + err := m.QueryRowCtx(ctx, &resp, userTableIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", userTableRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserTableModel) FindOneByUid(ctx context.Context, uid string) (*UserTable, error) { + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, uid) + var resp UserTable + err := m.QueryRowIndexCtx(ctx, &resp, userTableUidKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `uid` = ? limit 1", userTableRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, uid); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserTableModel) Insert(ctx context.Context, data *UserTable) (sql.Result, error) { + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, userTableRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.VerifyType, data.AlarmType, data.Status, data.Uid, data.NickName, data.Language, data.Currency, data.Avatar, data.CreateTime, data.UpdateTime) + }, userTableIdKey, userTableUidKey) + return ret, err +} + +func (m *defaultUserTableModel) Update(ctx context.Context, newData *UserTable) error { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userTableRowsWithPlaceHolder) + return conn.ExecCtx(ctx, query, newData.VerifyType, newData.AlarmType, newData.Status, newData.Uid, newData.NickName, newData.Language, newData.Currency, newData.Avatar, newData.CreateTime, newData.UpdateTime, newData.Id) + }, userTableIdKey, userTableUidKey) + return err +} + +func (m *defaultUserTableModel) formatPrimary(primary any) string { + return fmt.Sprintf("%s%v", cacheUserTableIdPrefix, primary) +} + +func (m *defaultUserTableModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", userTableRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary) +} + +func (m *defaultUserTableModel) tableName() string { + return m.table +} diff --git a/internal/model/vars.go b/internal/model/vars.go new file mode 100644 index 0000000..69ca814 --- /dev/null +++ b/internal/model/vars.go @@ -0,0 +1,5 @@ +package model + +import "github.com/zeromicro/go-zero/core/stores/sqlx" + +var ErrNotFound = sqlx.ErrNotFound diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 127530e..9146b2a 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -1,13 +1,56 @@ package svc -import "app-cloudep-member-server/internal/config" +import ( + "app-cloudep-member-server/internal/config" + "app-cloudep-member-server/internal/domain" + domainUC "app-cloudep-member-server/internal/domain/usecase" + "app-cloudep-member-server/internal/model" + mgo "app-cloudep-member-server/internal/model/mongo" + "app-cloudep-member-server/internal/usecase" + ers "code.30cm.net/digimon/library-go/errors" + vi "code.30cm.net/digimon/library-go/validator" + "fmt" + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) type ServiceContext struct { - Config config.Config + Config config.Config + Validate vi.Validate + + AccountModel model.AccountModel + UserModel model.UserTableModel + AccountToUidModel model.AccountToUidModel + GenUIDUseCase domainUC.UIDGenerateUseCase + Redis redis.Redis } func NewServiceContext(c config.Config) *ServiceContext { + // 設置 + ers.Scope = domain.Scope + + sqlConn := sqlx.NewMysql(c.DB.DsnString) + newRedis, err := redis.NewRedis(c.RedisCluster, redis.Cluster()) + if err != nil { + panic(err) + } + mongo := mgo.NewAutoIdModel( + fmt.Sprintf( + "%s://%s:%s@%s:%s", c.Mongo.Schema, + c.Mongo.User, c.Mongo.Password, c.Mongo.Host, c.Mongo.Port), + c.Mongo.Database, + c.Mongo.Collection, + c.Cache) + return &ServiceContext{ - Config: c, + Config: c, + Validate: vi.MustValidator(vi.WithAccount("account")), + Redis: *newRedis, + UserModel: model.NewUserTableModel(sqlConn, c.Cache), + AccountToUidModel: model.NewAccountToUidModel(sqlConn, c.Cache), + AccountModel: model.NewAccountModel(sqlConn, c.Cache), + GenUIDUseCase: usecase.MustGenerateUseCase(usecase.GenerateUseCaseParam{ + GenerateUIDRepo: mongo, + }), } } diff --git a/internal/usecase/google_authenticator.go b/internal/usecase/google_authenticator.go new file mode 100644 index 0000000..aed2454 --- /dev/null +++ b/internal/usecase/google_authenticator.go @@ -0,0 +1 @@ +package usecase diff --git a/internal/usecase/uid_generate.go b/internal/usecase/uid_generate.go new file mode 100644 index 0000000..5f5458a --- /dev/null +++ b/internal/usecase/uid_generate.go @@ -0,0 +1,75 @@ +package usecase + +import ( + "app-cloudep-member-server/internal/domain" + "app-cloudep-member-server/internal/domain/usecase" + mgo "app-cloudep-member-server/internal/model/mongo" + "context" + "math" + "strconv" + "strings" +) + +type GenerateUseCaseParam struct { + GenerateUIDRepo mgo.AutoIdModel +} + +type GenerateUseCase struct { + generateUIDRepo mgo.AutoIdModel +} + +func MustGenerateUseCase(param GenerateUseCaseParam) usecase.UIDGenerateUseCase { + return &GenerateUseCase{ + generateUIDRepo: param.GenerateUIDRepo, + } +} + +// Generate 利用 mongo 創立全局唯一的 ark id +// 如果之後有效能問題,扛在同一個 mongo 資料庫,在改成雪花算法 +func (g GenerateUseCase) Generate(ctx context.Context) (string, error) { + var data mgo.AutoId + err := g.generateUIDRepo.Inc(ctx, &data) + if err != nil { + return "", err + } + uid := strconv.Itoa(int(domain.InitAutoId + data.Count)) + code, err := generateReferralCode(uid) + if err != nil { + return "", err + } + + return code, nil +} + +// generateReferralCode 從 UID 生成 referralCode +func generateReferralCode(uid string) (string, error) { + uidInt, err := strconv.ParseInt(uid, 10, 64) + if err != nil { + return "", err + } + + maxReferralUIDBoundary := int64(math.Pow(float64(len(domain.ConvertTable)), float64(domain.DefaultReferralCodeLen))) + if uidInt > maxReferralUIDBoundary { + return "", usecase.UIDOutOfRangeErrorCodeError("uid encode out of range") + } + + encoded := encodeToBase(uidInt, len(domain.ConvertTable), domain.DefaultReferralCodeLen) + + return encoded, nil +} + +func encodeToBase(num int64, base int, length int) string { + result := "" + for num > 0 { + index := num % int64(base) + result = domain.ConvertTable[index] + result + num /= int64(base) + } + + // makes sure the length fo result feats the input length + if len(result) < length { + result = strings.Repeat(domain.ConvertTable[0], length-len(result)) + result + } + + return result +} -- 2.40.1 From a64aa7e1763487c0f24aeb34a4e62725fcecead9 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Thu, 22 Aug 2024 21:12:14 +0800 Subject: [PATCH 4/7] add uid generate --- Makefile | 46 ++++--- .../mongo/20240422112701_audo_id.up.js | 2 + ...20230529020012_account_uid_table.down.sql} | 0 ...> 20230529020012_account_uid_table.up.sql} | 0 ...sql => 20230529020013_user_table.down.sql} | 0 ...p.sql => 20230529020013_user_table.up.sql} | 0 .../20230529020000_create_schema.down.sql | 2 +- .../20230529020000_create_schema.up.sql | 2 +- generate/protobuf/service.proto | 14 ++- go.mod | 17 ++- internal/domain/const.go | 14 ++- internal/mock/lib/validate.go | 72 +++++++++++ internal/mock/model/account_model.go | 115 ++++++++++++++++++ internal/mock/model/account_model_gen.go | 115 ++++++++++++++++++ .../mock/model/account_to_uid_model_gen.go | 115 ++++++++++++++++++ internal/mock/model/account_to_uidmodel.go | 115 ++++++++++++++++++ internal/mock/model/auto_id_model.go | 115 ++++++++++++++++++ internal/mock/model/auto_id_model_gen.go | 101 +++++++++++++++ internal/mock/model/machine_node_model.go | 100 +++++++++++++++ internal/mock/model/machine_node_model_gen.go | 100 +++++++++++++++ internal/mock/model/user_table_model.go | 115 ++++++++++++++++++ internal/mock/model/user_table_model_gen.go | 115 ++++++++++++++++++ internal/mock/usecase/uid_generate.go | 55 +++++++++ internal/model/mongo/auto_id_model.go | 25 ++-- internal/model/mongo/auto_id_model_gen.go | 31 +++-- internal/model/mongo/auto_id_types.go | 2 +- internal/svc/service_context.go | 7 +- internal/usecase/uid_generate.go | 7 +- internal/usecase/uid_generate_test.go | 35 ++++++ internal/utils/password.go | 20 +++ 30 files changed, 1397 insertions(+), 60 deletions(-) create mode 100644 generate/database/mongo/20240422112701_audo_id.up.js rename generate/database/mysql/{20230529020011_account_uid_table.down.sql => 20230529020012_account_uid_table.down.sql} (100%) rename generate/database/mysql/{20230529020011_account_uid_table.up.sql => 20230529020012_account_uid_table.up.sql} (100%) rename generate/database/mysql/{20230529020011_user_table.down.sql => 20230529020013_user_table.down.sql} (100%) rename generate/database/mysql/{20230529020011_user_table.up.sql => 20230529020013_user_table.up.sql} (100%) create mode 100644 internal/mock/lib/validate.go create mode 100644 internal/mock/model/account_model.go create mode 100644 internal/mock/model/account_model_gen.go create mode 100644 internal/mock/model/account_to_uid_model_gen.go create mode 100644 internal/mock/model/account_to_uidmodel.go create mode 100644 internal/mock/model/auto_id_model.go create mode 100644 internal/mock/model/auto_id_model_gen.go create mode 100644 internal/mock/model/machine_node_model.go create mode 100644 internal/mock/model/machine_node_model_gen.go create mode 100644 internal/mock/model/user_table_model.go create mode 100644 internal/mock/model/user_table_model_gen.go create mode 100644 internal/mock/usecase/uid_generate.go create mode 100644 internal/usecase/uid_generate_test.go create mode 100644 internal/utils/password.go diff --git a/Makefile b/Makefile index 6d0df19..7953270 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,3 @@ -GO_CTL_NAME=goctl - # go-zero 生成風格 GO_ZERO_STYLE=go_zero @@ -21,8 +19,7 @@ fmt: # 格式優化 .PHONY: gen-rpc gen-rpc: # 建立 rpc code - $(GO_CTL_NAME) rpc protoc ./generate/protobuf/service.proto -m --style=$(GO_ZERO_STYLE) --go_out=./gen_result/pb --go-grpc_out=./gen_result/pb --zrpc_out=. - copy ./etc/service.yaml ./etc/service.example.yaml + goctl rpc protoc ./generate/protobuf/service.proto -m --style=$(GO_ZERO_STYLE) --go_out=./gen_result/pb --go-grpc_out=./gen_result/pb --zrpc_out=. go mod tidy @echo "Generate core-api files successfully" @@ -48,20 +45,37 @@ build-docker: rm -rf Dockerfile @echo "Generate core-api files successfully" -.PHONY: gen-model -gen-model: # 建立 rpc 資料庫 - goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_table.up.sql --style go_zero -d ./internal/model -i '' - goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_uid_table.up.sql --style go_zero -d ./internal/model -i '' - goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_user_table.up.sql --style go_zero -d ./internal/model -i '' - goctl model mysql ddl -c no -s ./generate/database/mysql/20230719061241_machine_node.up.sql --style go_zero -d ./internal/model -i '' - @echo "Generate model files successfully" +.PHONY: gen-my-sql-model +gen-my-sql-model: # 建立 rpc 資料庫 + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_uid_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_user_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230719061241_machine_node.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + @echo "Generate mysql model files successfully" + +gen-mongo-model: # 建立 rpc 資料庫 # 只產生 Model 剩下的要自己撰寫,連欄位名稱也是 - goctl model mongo -t AutoId -c --dir ./internal/model/mongo --style go_zero + goctl model mongo -t AutoId --dir ./internal/model/mongo --style $(GO_ZERO_STYLE) + @echo "Generate mongo model files successfully" #goctl model mysql ddl -s ./generate/database/mysql/20240819090248_create_role_permission_table.up.sql --style go_zero -d ./internal/model -i '' (沒cache) #goctl model mysql ddl -c no -s ./generate/database/mysql/20240816014305_create_permission_table.up.sql --style go_zero -d ./internal/model -i '' (有cache) -#.PHONY: mock-gen -#mock-gen: # 建立 mock 資料 -# mockgen -source=./order.go -destination=../../repository/mock/order.go -package=mock -# @echo "Generate model files successfully" \ No newline at end of file +.PHONY: mock-gen +mock-gen: # 建立 mock 資料 + mockgen -source=./internal/domain/usecase/uid_generate.go -destination=./internal/mock/usecase/uid_generate.go -package=mock + mockgen -source=./internal/model/account_model_gen.go -destination=./internal/mock/model/account_model_gen.go -package=mock + mockgen -source=./internal/model/account_model.go -destination=./internal/mock/model/account_model.go -package=mock + mockgen -source=./internal/model/account_to_uid_model_gen.go -destination=./internal/mock/model/account_to_uid_model_gen.go -package=mock + mockgen -source=./internal/model/account_to_uid_model.go -destination=./internal/mock/model/account_to_uidmodel.go -package=mock + mockgen -source=./internal/model/machine_node_model_gen.go -destination=./internal/mock/model/machine_node_model_gen.go -package=mock + mockgen -source=./internal/model/machine_node_model.go -destination=./internal/mock/model/machine_node_model.go -package=mock + mockgen -source=./internal/model/user_table_model_gen.go -destination=./internal/mock/model/user_table_model_gen.go -package=mock + mockgen -source=./internal/model/user_table_model.go -destination=./internal/mock/model/user_table_model.go -package=mock + mockgen -source=./internal/model/mongo/auto_id_model_gen.go -destination=./internal/mock/model/auto_id_model_gen.go -package=mock + mockgen -source=./internal/model/mongo/auto_id_model.go -destination=./internal/mock/model/auto_id_model.go -package=mock + @echo "Generate mock files successfully" + +.PHONY: migrate-database +migrate-database: + migrate -source file://generate/database/mysql -database 'mysql://root:yytt@tcp(127.0.0.1:3306)/digimon_member' up diff --git a/generate/database/mongo/20240422112701_audo_id.up.js b/generate/database/mongo/20240422112701_audo_id.up.js new file mode 100644 index 0000000..86e2f63 --- /dev/null +++ b/generate/database/mongo/20240422112701_audo_id.up.js @@ -0,0 +1,2 @@ +use digimon_member; +db.getCollection("count").createIndex({ "name": 1 }); diff --git a/generate/database/mysql/20230529020011_account_uid_table.down.sql b/generate/database/mysql/20230529020012_account_uid_table.down.sql similarity index 100% rename from generate/database/mysql/20230529020011_account_uid_table.down.sql rename to generate/database/mysql/20230529020012_account_uid_table.down.sql diff --git a/generate/database/mysql/20230529020011_account_uid_table.up.sql b/generate/database/mysql/20230529020012_account_uid_table.up.sql similarity index 100% rename from generate/database/mysql/20230529020011_account_uid_table.up.sql rename to generate/database/mysql/20230529020012_account_uid_table.up.sql diff --git a/generate/database/mysql/20230529020011_user_table.down.sql b/generate/database/mysql/20230529020013_user_table.down.sql similarity index 100% rename from generate/database/mysql/20230529020011_user_table.down.sql rename to generate/database/mysql/20230529020013_user_table.down.sql diff --git a/generate/database/mysql/20230529020011_user_table.up.sql b/generate/database/mysql/20230529020013_user_table.up.sql similarity index 100% rename from generate/database/mysql/20230529020011_user_table.up.sql rename to generate/database/mysql/20230529020013_user_table.up.sql diff --git a/generate/database/mysql/create/20230529020000_create_schema.down.sql b/generate/database/mysql/create/20230529020000_create_schema.down.sql index e7727a5..7bcbe27 100644 --- a/generate/database/mysql/create/20230529020000_create_schema.down.sql +++ b/generate/database/mysql/create/20230529020000_create_schema.down.sql @@ -1 +1 @@ -DROP DATABASE IF EXISTS `ark_member`; \ No newline at end of file +DROP DATABASE IF EXISTS `digimon_member`; \ No newline at end of file diff --git a/generate/database/mysql/create/20230529020000_create_schema.up.sql b/generate/database/mysql/create/20230529020000_create_schema.up.sql index d997e04..1b00479 100644 --- a/generate/database/mysql/create/20230529020000_create_schema.up.sql +++ b/generate/database/mysql/create/20230529020000_create_schema.up.sql @@ -1 +1 @@ -CREATE DATABASE IF NOT EXISTS `ark_member`; \ No newline at end of file +CREATE DATABASE IF NOT EXISTS `digimon_member`; \ No newline at end of file diff --git a/generate/protobuf/service.proto b/generate/protobuf/service.proto index 98a47fa..76819d1 100644 --- a/generate/protobuf/service.proto +++ b/generate/protobuf/service.proto @@ -14,6 +14,7 @@ enum VerifyType { VERIFY_EMAIL = 1; VERIFY_PHONE = 2; VERIFY_GOOGLE = 3; // google 驗證器 + VERIFY_NOT = 4; // 尚未 } enum AlarmType { @@ -57,6 +58,12 @@ message BindingUserReq { int64 type = 3; } +message BindingUserResp { + string uid = 1; + string login_id = 2; + int64 type = 3; +} + message CreateUserInfoReq { string uid = 1; VerifyType verify_type = 2; @@ -64,9 +71,8 @@ message CreateUserInfoReq { MemberStatus status = 4; string language = 5; string currency = 6; - optional string nick_name = 7; - optional uint32 gender = 8; - optional int64 birthday = 9; + optional string avatar= 7; + optional string nick_name = 8; } message GetAccountInfoResp { @@ -168,7 +174,7 @@ service Account { // GetUidByAccount 用帳號換取 UID rpc GetUidByAccount(GetUIDByAccountReq) returns(GetUidByAccountResp); // BindAccount 綁定帳號 -> account bind to UID - rpc BindAccount(BindingUserReq) returns(OKResp); + rpc BindAccount(BindingUserReq) returns(BindingUserResp); // BindUserInfo 初次,綁定 User Info rpc BindUserInfo(CreateUserInfoReq) returns(OKResp); // UpdateUserInfo 更新 User Info diff --git a/go.mod b/go.mod index 13b294d..cb140e3 100644 --- a/go.mod +++ b/go.mod @@ -5,15 +5,21 @@ go 1.22.3 require ( code.30cm.net/digimon/library-go/errors v1.0.1 code.30cm.net/digimon/library-go/validator v1.0.0 + github.com/alicebob/miniredis/v2 v2.33.0 github.com/bwmarrin/snowflake v0.3.0 + github.com/go-sql-driver/mysql v1.8.1 + github.com/stretchr/testify v1.9.0 github.com/zeromicro/go-zero v1.7.0 + go.mongodb.org/mongo-driver v1.16.0 go.uber.org/goleak v1.3.0 + go.uber.org/mock v0.4.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 ) require ( filippo.io/edwards25519 v1.1.0 // indirect + github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -32,10 +38,10 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect - github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -43,21 +49,29 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/redis/go-redis/v9 v9.6.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect go.etcd.io/etcd/api/v3 v3.5.15 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect go.etcd.io/etcd/client/v3 v3.5.15 // indirect @@ -79,6 +93,7 @@ require ( golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect diff --git a/internal/domain/const.go b/internal/domain/const.go index 5279edd..b5e1c29 100644 --- a/internal/domain/const.go +++ b/internal/domain/const.go @@ -6,7 +6,7 @@ const ( Scope = 10 ) -const InitAutoId = 1000000 +const InitAutoId = 10000000 const DefaultReferralCodeLen = 8 var ConvertTable = [...]string{ @@ -16,3 +16,15 @@ var ConvertTable = [...]string{ "L", "M", "N", "Z", "K", "P", "V", "R", "S", "T", } + +type AccountType int8 + +func (a AccountType) ToInt64() int64 { + return int64(a) +} + +const ( + AccountTypePhone AccountType = 1 + AccountTypeMail AccountType = 2 + AccountTypeAccount AccountType = 3 +) diff --git a/internal/mock/lib/validate.go b/internal/mock/lib/validate.go new file mode 100644 index 0000000..2c01cc6 --- /dev/null +++ b/internal/mock/lib/validate.go @@ -0,0 +1,72 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./validate.go +// +// Generated by this command: +// +// mockgen -source=./validate.go -destination=../../mock/lib/validate.go -package=lib +// + +// Package lib is a generated GoMock package. +package lib + +import ( + required "code.30cm.net/digimon/library-go/validator" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockValidate is a mock of Validate interface. +type MockValidate struct { + ctrl *gomock.Controller + recorder *MockValidateMockRecorder +} + +// MockValidateMockRecorder is the mock recorder for MockValidate. +type MockValidateMockRecorder struct { + mock *MockValidate +} + +// NewMockValidate creates a new mock instance. +func NewMockValidate(ctrl *gomock.Controller) *MockValidate { + mock := &MockValidate{ctrl: ctrl} + mock.recorder = &MockValidateMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockValidate) EXPECT() *MockValidateMockRecorder { + return m.recorder +} + +// BindToValidator mocks base method. +func (m *MockValidate) BindToValidator(opts ...required.Option) error { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BindToValidator", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindToValidator indicates an expected call of BindToValidator. +func (mr *MockValidateMockRecorder) BindToValidator(opts ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindToValidator", reflect.TypeOf((*MockValidate)(nil).BindToValidator), opts...) +} + +// ValidateAll mocks base method. +func (m *MockValidate) ValidateAll(obj any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateAll", obj) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateAll indicates an expected call of ValidateAll. +func (mr *MockValidateMockRecorder) ValidateAll(obj any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAll", reflect.TypeOf((*MockValidate)(nil).ValidateAll), obj) +} diff --git a/internal/mock/model/account_model.go b/internal/mock/model/account_model.go new file mode 100644 index 0000000..b2a650b --- /dev/null +++ b/internal/mock/model/account_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_model.go -destination=./internal/mock/model/account_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockAccountModel is a mock of AccountModel interface. +type MockAccountModel struct { + ctrl *gomock.Controller + recorder *MockAccountModelMockRecorder +} + +// MockAccountModelMockRecorder is the mock recorder for MockAccountModel. +type MockAccountModelMockRecorder struct { + mock *MockAccountModel +} + +// NewMockAccountModel creates a new mock instance. +func NewMockAccountModel(ctrl *gomock.Controller) *MockAccountModel { + mock := &MockAccountModel{ctrl: ctrl} + mock.recorder = &MockAccountModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountModel) EXPECT() *MockAccountModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAccountModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAccountModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAccountModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAccountModel) FindOne(ctx context.Context, id int64) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAccountModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAccountModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockAccountModel) FindOneByAccount(ctx context.Context, account string) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockAccountModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockAccountModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockAccountModel) Insert(ctx context.Context, data *model.Account) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAccountModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAccountModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAccountModel) Update(ctx context.Context, data *model.Account) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockAccountModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAccountModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_model_gen.go b/internal/mock/model/account_model_gen.go new file mode 100644 index 0000000..2ffb134 --- /dev/null +++ b/internal/mock/model/account_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_model_gen.go -destination=./internal/mock/model/account_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockaccountModel is a mock of accountModel interface. +type MockaccountModel struct { + ctrl *gomock.Controller + recorder *MockaccountModelMockRecorder +} + +// MockaccountModelMockRecorder is the mock recorder for MockaccountModel. +type MockaccountModelMockRecorder struct { + mock *MockaccountModel +} + +// NewMockaccountModel creates a new mock instance. +func NewMockaccountModel(ctrl *gomock.Controller) *MockaccountModel { + mock := &MockaccountModel{ctrl: ctrl} + mock.recorder = &MockaccountModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockaccountModel) EXPECT() *MockaccountModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockaccountModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockaccountModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockaccountModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockaccountModel) FindOne(ctx context.Context, id int64) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockaccountModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockaccountModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockaccountModel) FindOneByAccount(ctx context.Context, account string) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockaccountModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockaccountModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockaccountModel) Insert(ctx context.Context, data *model.Account) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockaccountModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockaccountModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockaccountModel) Update(ctx context.Context, data *model.Account) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockaccountModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockaccountModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_to_uid_model_gen.go b/internal/mock/model/account_to_uid_model_gen.go new file mode 100644 index 0000000..1ff6123 --- /dev/null +++ b/internal/mock/model/account_to_uid_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_to_uid_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_to_uid_model_gen.go -destination=./internal/mock/model/account_to_uid_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockaccountToUidModel is a mock of accountToUidModel interface. +type MockaccountToUidModel struct { + ctrl *gomock.Controller + recorder *MockaccountToUidModelMockRecorder +} + +// MockaccountToUidModelMockRecorder is the mock recorder for MockaccountToUidModel. +type MockaccountToUidModelMockRecorder struct { + mock *MockaccountToUidModel +} + +// NewMockaccountToUidModel creates a new mock instance. +func NewMockaccountToUidModel(ctrl *gomock.Controller) *MockaccountToUidModel { + mock := &MockaccountToUidModel{ctrl: ctrl} + mock.recorder = &MockaccountToUidModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockaccountToUidModel) EXPECT() *MockaccountToUidModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockaccountToUidModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockaccountToUidModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockaccountToUidModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockaccountToUidModel) FindOne(ctx context.Context, id int64) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockaccountToUidModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockaccountToUidModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockaccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockaccountToUidModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockaccountToUidModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockaccountToUidModel) Insert(ctx context.Context, data *model.AccountToUid) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockaccountToUidModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockaccountToUidModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockaccountToUidModel) Update(ctx context.Context, data *model.AccountToUid) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockaccountToUidModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockaccountToUidModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_to_uidmodel.go b/internal/mock/model/account_to_uidmodel.go new file mode 100644 index 0000000..756031f --- /dev/null +++ b/internal/mock/model/account_to_uidmodel.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/account_to_uid_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/account_to_uid_model.go -destination=./internal/mock/model/account_to_uidmodel.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockAccountToUidModel is a mock of AccountToUidModel interface. +type MockAccountToUidModel struct { + ctrl *gomock.Controller + recorder *MockAccountToUidModelMockRecorder +} + +// MockAccountToUidModelMockRecorder is the mock recorder for MockAccountToUidModel. +type MockAccountToUidModelMockRecorder struct { + mock *MockAccountToUidModel +} + +// NewMockAccountToUidModel creates a new mock instance. +func NewMockAccountToUidModel(ctrl *gomock.Controller) *MockAccountToUidModel { + mock := &MockAccountToUidModel{ctrl: ctrl} + mock.recorder = &MockAccountToUidModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountToUidModel) EXPECT() *MockAccountToUidModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAccountToUidModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAccountToUidModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAccountToUidModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAccountToUidModel) FindOne(ctx context.Context, id int64) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAccountToUidModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAccountToUidModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockAccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockAccountToUidModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockAccountToUidModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockAccountToUidModel) Insert(ctx context.Context, data *model.AccountToUid) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAccountToUidModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAccountToUidModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAccountToUidModel) Update(ctx context.Context, data *model.AccountToUid) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockAccountToUidModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAccountToUidModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/auto_id_model.go b/internal/mock/model/auto_id_model.go new file mode 100644 index 0000000..f506d0d --- /dev/null +++ b/internal/mock/model/auto_id_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/mongo/auto_id_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/mongo/auto_id_model.go -destination=./internal/mock/model/auto_id_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model/mongo" + context "context" + reflect "reflect" + + mongo "go.mongodb.org/mongo-driver/mongo" + gomock "go.uber.org/mock/gomock" +) + +// MockAutoIdModel is a mock of AutoIdModel interface. +type MockAutoIdModel struct { + ctrl *gomock.Controller + recorder *MockAutoIdModelMockRecorder +} + +// MockAutoIdModelMockRecorder is the mock recorder for MockAutoIdModel. +type MockAutoIdModelMockRecorder struct { + mock *MockAutoIdModel +} + +// NewMockAutoIdModel creates a new mock instance. +func NewMockAutoIdModel(ctrl *gomock.Controller) *MockAutoIdModel { + mock := &MockAutoIdModel{ctrl: ctrl} + mock.recorder = &MockAutoIdModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAutoIdModel) EXPECT() *MockAutoIdModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAutoIdModel) Delete(ctx context.Context, id string) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAutoIdModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAutoIdModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAutoIdModel) FindOne(ctx context.Context, id string) (*model.AutoId, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AutoId) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAutoIdModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAutoIdModel)(nil).FindOne), ctx, id) +} + +// Inc mocks base method. +func (m *MockAutoIdModel) Inc(ctx context.Context, data *model.AutoId) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Inc", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Inc indicates an expected call of Inc. +func (mr *MockAutoIdModelMockRecorder) Inc(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Inc", reflect.TypeOf((*MockAutoIdModel)(nil).Inc), ctx, data) +} + +// Insert mocks base method. +func (m *MockAutoIdModel) Insert(ctx context.Context, data *model.AutoId) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAutoIdModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAutoIdModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAutoIdModel) Update(ctx context.Context, data *model.AutoId) (*mongo.UpdateResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(*mongo.UpdateResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockAutoIdModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAutoIdModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/auto_id_model_gen.go b/internal/mock/model/auto_id_model_gen.go new file mode 100644 index 0000000..d329a09 --- /dev/null +++ b/internal/mock/model/auto_id_model_gen.go @@ -0,0 +1,101 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/mongo/auto_id_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/mongo/auto_id_model_gen.go -destination=./internal/mock/model/auto_id_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model/mongo" + context "context" + reflect "reflect" + + mongo "go.mongodb.org/mongo-driver/mongo" + gomock "go.uber.org/mock/gomock" +) + +// MockautoIdModel is a mock of autoIdModel interface. +type MockautoIdModel struct { + ctrl *gomock.Controller + recorder *MockautoIdModelMockRecorder +} + +// MockautoIdModelMockRecorder is the mock recorder for MockautoIdModel. +type MockautoIdModelMockRecorder struct { + mock *MockautoIdModel +} + +// NewMockautoIdModel creates a new mock instance. +func NewMockautoIdModel(ctrl *gomock.Controller) *MockautoIdModel { + mock := &MockautoIdModel{ctrl: ctrl} + mock.recorder = &MockautoIdModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockautoIdModel) EXPECT() *MockautoIdModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockautoIdModel) Delete(ctx context.Context, id string) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Delete indicates an expected call of Delete. +func (mr *MockautoIdModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockautoIdModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockautoIdModel) FindOne(ctx context.Context, id string) (*model.AutoId, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AutoId) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockautoIdModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockautoIdModel)(nil).FindOne), ctx, id) +} + +// Insert mocks base method. +func (m *MockautoIdModel) Insert(ctx context.Context, data *model.AutoId) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Insert indicates an expected call of Insert. +func (mr *MockautoIdModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockautoIdModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockautoIdModel) Update(ctx context.Context, data *model.AutoId) (*mongo.UpdateResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(*mongo.UpdateResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockautoIdModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockautoIdModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/machine_node_model.go b/internal/mock/model/machine_node_model.go new file mode 100644 index 0000000..3dfc332 --- /dev/null +++ b/internal/mock/model/machine_node_model.go @@ -0,0 +1,100 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/machine_node_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/machine_node_model.go -destination=./internal/mock/model/machine_node_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockMachineNodeModel is a mock of MachineNodeModel interface. +type MockMachineNodeModel struct { + ctrl *gomock.Controller + recorder *MockMachineNodeModelMockRecorder +} + +// MockMachineNodeModelMockRecorder is the mock recorder for MockMachineNodeModel. +type MockMachineNodeModelMockRecorder struct { + mock *MockMachineNodeModel +} + +// NewMockMachineNodeModel creates a new mock instance. +func NewMockMachineNodeModel(ctrl *gomock.Controller) *MockMachineNodeModel { + mock := &MockMachineNodeModel{ctrl: ctrl} + mock.recorder = &MockMachineNodeModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMachineNodeModel) EXPECT() *MockMachineNodeModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockMachineNodeModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockMachineNodeModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockMachineNodeModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockMachineNodeModel) FindOne(ctx context.Context, id int64) (*model.MachineNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.MachineNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockMachineNodeModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockMachineNodeModel)(nil).FindOne), ctx, id) +} + +// Insert mocks base method. +func (m *MockMachineNodeModel) Insert(ctx context.Context, data *model.MachineNode) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockMachineNodeModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockMachineNodeModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockMachineNodeModel) Update(ctx context.Context, data *model.MachineNode) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockMachineNodeModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockMachineNodeModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/machine_node_model_gen.go b/internal/mock/model/machine_node_model_gen.go new file mode 100644 index 0000000..e8c053d --- /dev/null +++ b/internal/mock/model/machine_node_model_gen.go @@ -0,0 +1,100 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/machine_node_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/machine_node_model_gen.go -destination=./internal/mock/model/machine_node_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockmachineNodeModel is a mock of machineNodeModel interface. +type MockmachineNodeModel struct { + ctrl *gomock.Controller + recorder *MockmachineNodeModelMockRecorder +} + +// MockmachineNodeModelMockRecorder is the mock recorder for MockmachineNodeModel. +type MockmachineNodeModelMockRecorder struct { + mock *MockmachineNodeModel +} + +// NewMockmachineNodeModel creates a new mock instance. +func NewMockmachineNodeModel(ctrl *gomock.Controller) *MockmachineNodeModel { + mock := &MockmachineNodeModel{ctrl: ctrl} + mock.recorder = &MockmachineNodeModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockmachineNodeModel) EXPECT() *MockmachineNodeModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockmachineNodeModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockmachineNodeModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockmachineNodeModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockmachineNodeModel) FindOne(ctx context.Context, id int64) (*model.MachineNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.MachineNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockmachineNodeModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockmachineNodeModel)(nil).FindOne), ctx, id) +} + +// Insert mocks base method. +func (m *MockmachineNodeModel) Insert(ctx context.Context, data *model.MachineNode) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockmachineNodeModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockmachineNodeModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockmachineNodeModel) Update(ctx context.Context, data *model.MachineNode) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockmachineNodeModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockmachineNodeModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/user_table_model.go b/internal/mock/model/user_table_model.go new file mode 100644 index 0000000..7370944 --- /dev/null +++ b/internal/mock/model/user_table_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/user_table_model.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/user_table_model.go -destination=./internal/mock/model/user_table_model.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockUserTableModel is a mock of UserTableModel interface. +type MockUserTableModel struct { + ctrl *gomock.Controller + recorder *MockUserTableModelMockRecorder +} + +// MockUserTableModelMockRecorder is the mock recorder for MockUserTableModel. +type MockUserTableModelMockRecorder struct { + mock *MockUserTableModel +} + +// NewMockUserTableModel creates a new mock instance. +func NewMockUserTableModel(ctrl *gomock.Controller) *MockUserTableModel { + mock := &MockUserTableModel{ctrl: ctrl} + mock.recorder = &MockUserTableModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockUserTableModel) EXPECT() *MockUserTableModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockUserTableModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockUserTableModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockUserTableModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockUserTableModel) FindOne(ctx context.Context, id int64) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockUserTableModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockUserTableModel)(nil).FindOne), ctx, id) +} + +// FindOneByUid mocks base method. +func (m *MockUserTableModel) FindOneByUid(ctx context.Context, uid string) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByUid", ctx, uid) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByUid indicates an expected call of FindOneByUid. +func (mr *MockUserTableModelMockRecorder) FindOneByUid(ctx, uid any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByUid", reflect.TypeOf((*MockUserTableModel)(nil).FindOneByUid), ctx, uid) +} + +// Insert mocks base method. +func (m *MockUserTableModel) Insert(ctx context.Context, data *model.UserTable) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockUserTableModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockUserTableModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockUserTableModel) Update(ctx context.Context, data *model.UserTable) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockUserTableModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUserTableModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/user_table_model_gen.go b/internal/mock/model/user_table_model_gen.go new file mode 100644 index 0000000..14cd694 --- /dev/null +++ b/internal/mock/model/user_table_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/model/user_table_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./internal/model/user_table_model_gen.go -destination=./internal/mock/model/user_table_model_gen.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + model "app-cloudep-member-server/internal/model" + context "context" + sql "database/sql" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockuserTableModel is a mock of userTableModel interface. +type MockuserTableModel struct { + ctrl *gomock.Controller + recorder *MockuserTableModelMockRecorder +} + +// MockuserTableModelMockRecorder is the mock recorder for MockuserTableModel. +type MockuserTableModelMockRecorder struct { + mock *MockuserTableModel +} + +// NewMockuserTableModel creates a new mock instance. +func NewMockuserTableModel(ctrl *gomock.Controller) *MockuserTableModel { + mock := &MockuserTableModel{ctrl: ctrl} + mock.recorder = &MockuserTableModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockuserTableModel) EXPECT() *MockuserTableModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockuserTableModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockuserTableModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockuserTableModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockuserTableModel) FindOne(ctx context.Context, id int64) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockuserTableModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockuserTableModel)(nil).FindOne), ctx, id) +} + +// FindOneByUid mocks base method. +func (m *MockuserTableModel) FindOneByUid(ctx context.Context, uid string) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByUid", ctx, uid) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByUid indicates an expected call of FindOneByUid. +func (mr *MockuserTableModelMockRecorder) FindOneByUid(ctx, uid any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByUid", reflect.TypeOf((*MockuserTableModel)(nil).FindOneByUid), ctx, uid) +} + +// Insert mocks base method. +func (m *MockuserTableModel) Insert(ctx context.Context, data *model.UserTable) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockuserTableModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockuserTableModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockuserTableModel) Update(ctx context.Context, data *model.UserTable) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockuserTableModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockuserTableModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/usecase/uid_generate.go b/internal/mock/usecase/uid_generate.go new file mode 100644 index 0000000..235d1af --- /dev/null +++ b/internal/mock/usecase/uid_generate.go @@ -0,0 +1,55 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/domain/usecase/uid_generate.go +// +// Generated by this command: +// +// mockgen -source=./internal/domain/usecase/uid_generate.go -destination=./internal/mock/usecase/uid_generate.go -package=mock +// + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockUIDGenerateUseCase is a mock of UIDGenerateUseCase interface. +type MockUIDGenerateUseCase struct { + ctrl *gomock.Controller + recorder *MockUIDGenerateUseCaseMockRecorder +} + +// MockUIDGenerateUseCaseMockRecorder is the mock recorder for MockUIDGenerateUseCase. +type MockUIDGenerateUseCaseMockRecorder struct { + mock *MockUIDGenerateUseCase +} + +// NewMockUIDGenerateUseCase creates a new mock instance. +func NewMockUIDGenerateUseCase(ctrl *gomock.Controller) *MockUIDGenerateUseCase { + mock := &MockUIDGenerateUseCase{ctrl: ctrl} + mock.recorder = &MockUIDGenerateUseCaseMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockUIDGenerateUseCase) EXPECT() *MockUIDGenerateUseCaseMockRecorder { + return m.recorder +} + +// Generate mocks base method. +func (m *MockUIDGenerateUseCase) Generate(ctx context.Context) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Generate", ctx) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Generate indicates an expected call of Generate. +func (mr *MockUIDGenerateUseCaseMockRecorder) Generate(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockUIDGenerateUseCase)(nil).Generate), ctx) +} diff --git a/internal/model/mongo/auto_id_model.go b/internal/model/mongo/auto_id_model.go index bd5d619..93fc238 100644 --- a/internal/model/mongo/auto_id_model.go +++ b/internal/model/mongo/auto_id_model.go @@ -2,10 +2,10 @@ package model import ( "context" - "github.com/zeromicro/go-zero/core/stores/cache" - "github.com/zeromicro/go-zero/core/stores/monc" + "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" + "time" ) var _ AutoIdModel = (*customAutoIdModel)(nil) @@ -24,23 +24,26 @@ type ( ) // NewAutoIdModel returns a model for the mongo. -func NewAutoIdModel(url, db, collection string, c cache.CacheConf) AutoIdModel { - conn := monc.MustNewModel(url, db, collection, c) +func NewAutoIdModel(url, db, collection string) AutoIdModel { + conn := mon.MustNewModel(url, db, collection) return &customAutoIdModel{ defaultAutoIdModel: newDefaultAutoIdModel(conn), } } func (m *customAutoIdModel) Inc(ctx context.Context, data *AutoId) error { - filter := bson.M{"admin": "auto_id"} - update := bson.M{"$inc": bson.M{"counter": 1}} + // 定義查詢的條件 + filter := bson.M{"name": "auto_id"} - key := prefixAutoIdCacheKey + "count" - - err := m.conn.FindOneAndUpdate(ctx, key, data, filter, update, + // 定義更新的操作,包括自增和更新時間 + update := bson.M{ + "$inc": bson.M{"counter": 1}, // 自增 counter + "$set": bson.M{"updateAt": time.Now().UTC()}, // 設置 updateAt 為當前時間 + } + // 使用 FindOneAndUpdate 並將結果解碼到 data 中 + err := m.conn.FindOneAndUpdate(ctx, &data, filter, update, options.FindOneAndUpdate().SetUpsert(true), - options.FindOneAndUpdate().SetReturnDocument(options.After), - ) + options.FindOneAndUpdate().SetReturnDocument(options.After)) return err } diff --git a/internal/model/mongo/auto_id_model_gen.go b/internal/model/mongo/auto_id_model_gen.go index 5163d74..058a8cc 100644 --- a/internal/model/mongo/auto_id_model_gen.go +++ b/internal/model/mongo/auto_id_model_gen.go @@ -5,14 +5,12 @@ import ( "context" "time" - "github.com/zeromicro/go-zero/core/stores/monc" + "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" ) -var prefixAutoIdCacheKey = "cache:autoId:" - type autoIdModel interface { Insert(ctx context.Context, data *AutoId) error FindOne(ctx context.Context, id string) (*AutoId, error) @@ -21,22 +19,21 @@ type autoIdModel interface { } type defaultAutoIdModel struct { - conn *monc.Model + conn *mon.Model } -func newDefaultAutoIdModel(conn *monc.Model) *defaultAutoIdModel { +func newDefaultAutoIdModel(conn *mon.Model) *defaultAutoIdModel { return &defaultAutoIdModel{conn: conn} } func (m *defaultAutoIdModel) Insert(ctx context.Context, data *AutoId) error { if data.ID.IsZero() { data.ID = primitive.NewObjectID() - data.CreateAt = time.Now() - data.UpdateAt = time.Now() + data.CreateAt = time.Now().UTC() + data.UpdateAt = time.Now().UTC() } - key := prefixAutoIdCacheKey + data.ID.Hex() - _, err := m.conn.InsertOne(ctx, key, data) + _, err := m.conn.InsertOne(ctx, data) return err } @@ -47,12 +44,12 @@ func (m *defaultAutoIdModel) FindOne(ctx context.Context, id string) (*AutoId, e } var data AutoId - key := prefixAutoIdCacheKey + id - err = m.conn.FindOne(ctx, key, &data, bson.M{"_id": oid}) + + err = m.conn.FindOne(ctx, &data, bson.M{"_id": oid}) switch err { case nil: return &data, nil - case monc.ErrNotFound: + case mon.ErrNotFound: return nil, ErrNotFound default: return nil, err @@ -60,9 +57,9 @@ func (m *defaultAutoIdModel) FindOne(ctx context.Context, id string) (*AutoId, e } func (m *defaultAutoIdModel) Update(ctx context.Context, data *AutoId) (*mongo.UpdateResult, error) { - data.UpdateAt = time.Now() - key := prefixAutoIdCacheKey + data.ID.Hex() - res, err := m.conn.UpdateOne(ctx, key, bson.M{"_id": data.ID}, bson.M{"$set": data}) + data.UpdateAt = time.Now().UTC() + + res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data}) return res, err } @@ -71,7 +68,7 @@ func (m *defaultAutoIdModel) Delete(ctx context.Context, id string) (int64, erro if err != nil { return 0, ErrInvalidObjectId } - key := prefixAutoIdCacheKey + id - res, err := m.conn.DeleteOne(ctx, key, bson.M{"_id": oid}) + + res, err := m.conn.DeleteOne(ctx, bson.M{"_id": oid}) return res, err } diff --git a/internal/model/mongo/auto_id_types.go b/internal/model/mongo/auto_id_types.go index 3605d9d..34b5467 100644 --- a/internal/model/mongo/auto_id_types.go +++ b/internal/model/mongo/auto_id_types.go @@ -9,7 +9,7 @@ import ( type AutoId struct { ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"` Name string `bson:"name,omitempty" json:"name,omitempty"` - Count uint64 `bson:"count,omitempty" json:"count,omitempty"` + Counter uint64 `bson:"counter" json:"counter"` UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"` CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"` } diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 9146b2a..611a10a 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -36,11 +36,10 @@ func NewServiceContext(c config.Config) *ServiceContext { } mongo := mgo.NewAutoIdModel( fmt.Sprintf( - "%s://%s:%s@%s:%s", c.Mongo.Schema, - c.Mongo.User, c.Mongo.Password, c.Mongo.Host, c.Mongo.Port), + "%s://%s:%s", c.Mongo.Schema, + c.Mongo.Host, c.Mongo.Port), c.Mongo.Database, - c.Mongo.Collection, - c.Cache) + c.Mongo.Collection) return &ServiceContext{ Config: c, diff --git a/internal/usecase/uid_generate.go b/internal/usecase/uid_generate.go index 5f5458a..649abe4 100644 --- a/internal/usecase/uid_generate.go +++ b/internal/usecase/uid_generate.go @@ -25,14 +25,15 @@ func MustGenerateUseCase(param GenerateUseCaseParam) usecase.UIDGenerateUseCase } // Generate 利用 mongo 創立全局唯一的 ark id -// 如果之後有效能問題,扛在同一個 mongo 資料庫,在改成雪花算法 +// TODO 如果之後有效能問題,扛在同一個 mongo 資料庫,在改成雪花算法 func (g GenerateUseCase) Generate(ctx context.Context) (string, error) { var data mgo.AutoId err := g.generateUIDRepo.Inc(ctx, &data) if err != nil { return "", err } - uid := strconv.Itoa(int(domain.InitAutoId + data.Count)) + + uid := strconv.Itoa(int(domain.InitAutoId + data.Counter)) code, err := generateReferralCode(uid) if err != nil { return "", err @@ -53,7 +54,7 @@ func generateReferralCode(uid string) (string, error) { return "", usecase.UIDOutOfRangeErrorCodeError("uid encode out of range") } - encoded := encodeToBase(uidInt, len(domain.ConvertTable), domain.DefaultReferralCodeLen) + encoded := encodeToBase(uidInt, 10, domain.DefaultReferralCodeLen) return encoded, nil } diff --git a/internal/usecase/uid_generate_test.go b/internal/usecase/uid_generate_test.go new file mode 100644 index 0000000..355b341 --- /dev/null +++ b/internal/usecase/uid_generate_test.go @@ -0,0 +1,35 @@ +package usecase + +import ( + "testing" +) + +// 單元測試 +func TestEncodeToBase(t *testing.T) { + tests := []struct { + num int64 + base int + length int + want string + }{ + // 測試基礎情況 + {num: 0, base: 10, length: 6, want: "OOOOOO"}, + {num: 1, base: 10, length: 6, want: "OOOOOD"}, + + {num: 24, base: 10, length: 6, want: "OOOOWY"}, + {num: 25, base: 10, length: 6, want: "OOOOWG"}, + {num: 1, base: 10, length: 4, want: "OOOD"}, + {num: 24, base: 10, length: 4, want: "OOWY"}, + {num: 25, base: 10, length: 5, want: "OOOWG"}, + {num: 1234567890, base: 10, length: 10, want: "DWXYGBCHEO"}, // 測試大數情況 + } + + for _, tt := range tests { + t.Run("encodeToBase", func(t *testing.T) { + got := encodeToBase(tt.num, tt.base, tt.length) + if got != tt.want { + t.Errorf("encodeToBase(%d, %d, %d) = %s; want %s", tt.num, tt.base, tt.length, got, tt.want) + } + }) + } +} diff --git a/internal/utils/password.go b/internal/utils/password.go new file mode 100644 index 0000000..5f10af9 --- /dev/null +++ b/internal/utils/password.go @@ -0,0 +1,20 @@ +package utils + +import ( + "golang.org/x/crypto/bcrypt" +) + +func HashPassword(password string, cost int) (string, error) { + bytes, err := bcrypt.GenerateFromPassword([]byte(password), cost) + return string(bytes), err +} + +func CheckPasswordHash(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} + +func GetHashingCost(hashedPassword []byte) int { + cost, _ := bcrypt.Cost(hashedPassword) + return cost +} -- 2.40.1 From 994597cd94422ced06945ab797b97a25f1fe5411 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Thu, 22 Aug 2024 22:21:43 +0800 Subject: [PATCH 5/7] add uid generate --- Makefile | 4 +- .../mysql/20230529020013_user_table.up.sql | 1 + generate/protobuf/service.proto | 8 +- go.mod | 2 +- internal/model/account_model.go | 19 ++ internal/model/user_table_model.go | 186 ++++++++++++++++++ 6 files changed, 214 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 7953270..bb182f6 100644 --- a/Makefile +++ b/Makefile @@ -48,8 +48,8 @@ build-docker: .PHONY: gen-my-sql-model gen-my-sql-model: # 建立 rpc 資料庫 goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' - goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_account_uid_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' - goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020011_user_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020012_account_uid_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' + goctl model mysql ddl -c no -s ./generate/database/mysql/20230529020013_user_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' goctl model mysql ddl -c no -s ./generate/database/mysql/20230719061241_machine_node.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i '' @echo "Generate mysql model files successfully" diff --git a/generate/database/mysql/20230529020013_user_table.up.sql b/generate/database/mysql/20230529020013_user_table.up.sql index ce8a45d..0db127c 100644 --- a/generate/database/mysql/20230529020013_user_table.up.sql +++ b/generate/database/mysql/20230529020013_user_table.up.sql @@ -12,5 +12,6 @@ CREATE TABLE `user_table` ( `update_time` BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), INDEX `idx_create_time` (`create_time` ASC), + INDEX `idx_nick_name` (`nick_name` ASC), UNIQUE INDEX `uk_uid` (`uid` ASC) )ENGINE=InnoDB COMMENT='使用者資訊'; diff --git a/generate/protobuf/service.proto b/generate/protobuf/service.proto index 76819d1..19bcffe 100644 --- a/generate/protobuf/service.proto +++ b/generate/protobuf/service.proto @@ -85,9 +85,10 @@ message UpdateUserInfoReq { optional string language = 2; optional string currency = 3; optional string nick_name = 4; - optional VerifyType verify_type = 5; - optional AlarmType alarm_type = 6; - optional MemberStatus status = 7; + optional string avatar = 5; + optional VerifyType verify_type = 6; + optional AlarmType alarm_type = 7; + optional MemberStatus status = 8; } message GetUIDByAccountReq { @@ -102,6 +103,7 @@ message GetUidByAccountResp { message UpdateTokenReq { string account = 1; string token = 2; + int64 platform=3; } message GenerateRefreshCodeReq { diff --git a/go.mod b/go.mod index cb140e3..fdce8a4 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( go.mongodb.org/mongo-driver v1.16.0 go.uber.org/goleak v1.3.0 go.uber.org/mock v0.4.0 + golang.org/x/crypto v0.25.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 ) @@ -90,7 +91,6 @@ require ( go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect golang.org/x/sync v0.7.0 // indirect diff --git a/internal/model/account_model.go b/internal/model/account_model.go index 958d6dc..3a9dcdc 100755 --- a/internal/model/account_model.go +++ b/internal/model/account_model.go @@ -1,6 +1,9 @@ package model import ( + "context" + "database/sql" + "fmt" "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/sqlx" ) @@ -12,6 +15,7 @@ type ( // and implement the added methods in customAccountModel. AccountModel interface { accountModel + UpdateTokenByLoginID(ctx context.Context, account string, token string) error } customAccountModel struct { @@ -25,3 +29,18 @@ func NewAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) defaultAccountModel: newAccountModel(conn, c, opts...), } } + +func (m *defaultAccountModel) UpdateTokenByLoginID(ctx context.Context, account string, token string) error { + data, err := m.FindOneByAccount(ctx, account) + if err != nil { + return err + } + + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, data.Id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set `token` = ? where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, token, data.Id) + }, accountAccountKey, accountIdKey) + return err +} diff --git a/internal/model/user_table_model.go b/internal/model/user_table_model.go index 13f2b1d..85c3567 100755 --- a/internal/model/user_table_model.go +++ b/internal/model/user_table_model.go @@ -1,8 +1,15 @@ package model import ( + "app-cloudep-member-server/gen_result/pb/member" + "context" + "database/sql" + "fmt" "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" "github.com/zeromicro/go-zero/core/stores/sqlx" + "strings" + "time" ) var _ UserTableModel = (*customUserTableModel)(nil) @@ -12,11 +19,27 @@ type ( // and implement the added methods in customUserTableModel. UserTableModel interface { userTableModel + FindOneByNickName(ctx context.Context, uid string) (*UserTable, error) + ListMembers(ctx context.Context, params *UserQueryParams) ([]*UserTable, error) + Count(ctx context.Context) (int64, error) + UpdateStatus(ctx context.Context, uid string, status int32) error + UpdateSome(ctx context.Context, newData *member.UpdateUserInfoReq) error } customUserTableModel struct { *defaultUserTableModel } + + UserQueryParams struct { + RoleId *string + VerifyType *int32 + AlarmType *int32 + Status *int32 + CreateStartTime *int64 + CreateEndTime *int64 + PageSize int64 + PageIndex int64 + } ) // NewUserTableModel returns a model for the database table. @@ -25,3 +48,166 @@ func NewUserTableModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Optio defaultUserTableModel: newUserTableModel(conn, c, opts...), } } + +func (m *defaultUserTableModel) FindOneByNickName(ctx context.Context, nickName string) (*UserTable, error) { + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, nickName) + var resp UserTable + err := m.QueryRowIndexCtx(ctx, &resp, userTableUidKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `nick_name` = ? limit 1", userTableRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, nickName); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserTableModel) ListMembers(ctx context.Context, params *UserQueryParams) ([]*UserTable, error) { + query := fmt.Sprintf("select %s from %s", userTableRows, m.table) + var args = make([]any, 0, 10) + var conditions []string + + if params.RoleId != nil { + conditions = append(conditions, "role_id = ?") + args = append(args, *params.RoleId) + } + + if params.VerifyType != nil { + conditions = append(conditions, "verify_type = ?") + args = append(args, *params.VerifyType) + } + + if params.AlarmType != nil { + conditions = append(conditions, "alarm_type = ?") + args = append(args, *params.AlarmType) + } + + if params.Status != nil { + conditions = append(conditions, "status = ?") + args = append(args, *params.Status) + } + + if params.CreateStartTime != nil { + conditions = append(conditions, "create_time >= ?") + args = append(args, *params.CreateStartTime) + } + + if params.CreateEndTime != nil { + conditions = append(conditions, "create_time <= ?") + args = append(args, *params.CreateEndTime) + } + + // 加入條件到查詢語句中 + if len(conditions) > 0 { + query += " WHERE " + strings.Join(conditions, " AND ") + } + + // 分頁處理 + offset := (params.PageIndex - 1) * params.PageSize + query += " LIMIT ? OFFSET ?" + args = append(args, params.PageSize, offset) + + var users []*UserTable + fmt.Println("query:", query) + fmt.Println("args:", args) + err := m.QueryRowsNoCacheCtx(ctx, &users, query, args...) + if err != nil { + return nil, err + } + + return users, nil +} + +func (m *defaultUserTableModel) Count(ctx context.Context) (int64, error) { + var count int64 + query := fmt.Sprintf("select count(*) from %s", m.table) + err := m.QueryRowNoCacheCtx(ctx, &count, query) + if err != nil { + return 0, err + } + return count, nil +} + +func (m *defaultUserTableModel) UpdateStatus(ctx context.Context, uid string, status int32) error { + data, err := m.FindOneByUid(ctx, uid) + if err != nil { + return err + } + + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set `status` = ? where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, status, data.Id) + }, userTableIdKey, userTableUidKey) + return err +} + +func (m *defaultUserTableModel) UpdateSome(ctx context.Context, newData *member.UpdateUserInfoReq) error { + data, err := m.FindOneByUid(ctx, newData.Uid) + if err != nil { + return err + } + + // 初始化缓存键 + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + + query := fmt.Sprintf("update %s set ", m.table) + var args []interface{} + var updates []string + + if newData.VerifyType != nil { + updates = append(updates, "verify_type = ?") + args = append(args, *newData.VerifyType) + } + if newData.AlarmType != nil { + updates = append(updates, "alarm_type = ?") + args = append(args, *newData.AlarmType) + } + if newData.Status != nil { + updates = append(updates, "status = ?") + args = append(args, *newData.Status) + } + + if newData.Language != nil { + updates = append(updates, "language = ?") + args = append(args, *newData.Language) + } + if newData.Currency != nil { + updates = append(updates, "currency = ?") + args = append(args, *newData.Currency) + } + if newData.NickName != nil { + updates = append(updates, "nick_name = ?") + args = append(args, *newData.NickName) + } + if newData.Avatar != nil { + updates = append(updates, "avatar = ?") + args = append(args, *newData.Avatar) + } + + if len(updates) == 0 { + return nil + } + + update := time.Now().UTC().Unix() + updates = append(updates, "update_time = ?") + args = append(args, &update) + + query += strings.Join(updates, ", ") + " where `id` = ?" + args = append(args, data.Id) + + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + return conn.ExecCtx(ctx, query, args...) + }, userTableIdKey, userTableUidKey) + + return err +} -- 2.40.1 From fc547508a4f3f26ab2b6aee9c15ac51fd3315cee Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Thu, 22 Aug 2024 22:24:51 +0800 Subject: [PATCH 6/7] go fmt --- internal/lib/middleware/with_context.go | 5 +++-- internal/mock/lib/validate.go | 3 ++- internal/model/account_model.go | 1 + internal/model/mongo/auto_id_model.go | 3 ++- internal/model/user_table_model.go | 7 +++---- internal/svc/service_context.go | 3 ++- service.go | 5 +++-- 7 files changed, 16 insertions(+), 11 deletions(-) diff --git a/internal/lib/middleware/with_context.go b/internal/lib/middleware/with_context.go index 39d8a05..ba39f1a 100644 --- a/internal/lib/middleware/with_context.go +++ b/internal/lib/middleware/with_context.go @@ -1,12 +1,13 @@ package middleware import ( - ers "code.30cm.net/digimon/library-go/errors" "context" "errors" + "time" + + ers "code.30cm.net/digimon/library-go/errors" "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc" - "time" ) const defaultTimeout = 30 * time.Second diff --git a/internal/mock/lib/validate.go b/internal/mock/lib/validate.go index 2c01cc6..dd852f8 100644 --- a/internal/mock/lib/validate.go +++ b/internal/mock/lib/validate.go @@ -10,9 +10,10 @@ package lib import ( - required "code.30cm.net/digimon/library-go/validator" reflect "reflect" + required "code.30cm.net/digimon/library-go/validator" + gomock "go.uber.org/mock/gomock" ) diff --git a/internal/model/account_model.go b/internal/model/account_model.go index 3a9dcdc..2a63d72 100755 --- a/internal/model/account_model.go +++ b/internal/model/account_model.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/sqlx" ) diff --git a/internal/model/mongo/auto_id_model.go b/internal/model/mongo/auto_id_model.go index 93fc238..9a60ea3 100644 --- a/internal/model/mongo/auto_id_model.go +++ b/internal/model/mongo/auto_id_model.go @@ -2,10 +2,11 @@ package model import ( "context" + "time" + "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" - "time" ) var _ AutoIdModel = (*customAutoIdModel)(nil) diff --git a/internal/model/user_table_model.go b/internal/model/user_table_model.go index 85c3567..2242070 100755 --- a/internal/model/user_table_model.go +++ b/internal/model/user_table_model.go @@ -5,11 +5,12 @@ import ( "context" "database/sql" "fmt" + "strings" + "time" + "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/sqlc" "github.com/zeromicro/go-zero/core/stores/sqlx" - "strings" - "time" ) var _ UserTableModel = (*customUserTableModel)(nil) @@ -115,8 +116,6 @@ func (m *defaultUserTableModel) ListMembers(ctx context.Context, params *UserQue args = append(args, params.PageSize, offset) var users []*UserTable - fmt.Println("query:", query) - fmt.Println("args:", args) err := m.QueryRowsNoCacheCtx(ctx, &users, query, args...) if err != nil { return nil, err diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 611a10a..185c057 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -7,9 +7,10 @@ import ( "app-cloudep-member-server/internal/model" mgo "app-cloudep-member-server/internal/model/mongo" "app-cloudep-member-server/internal/usecase" + "fmt" + ers "code.30cm.net/digimon/library-go/errors" vi "code.30cm.net/digimon/library-go/validator" - "fmt" "github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/sqlx" ) diff --git a/service.go b/service.go index 19081ec..f6a8cc9 100644 --- a/service.go +++ b/service.go @@ -2,7 +2,8 @@ package main import ( "flag" - "fmt" + + "github.com/zeromicro/go-zero/core/logx" "app-cloudep-member-server/gen_result/pb/member" "app-cloudep-member-server/internal/config" @@ -34,6 +35,6 @@ func main() { }) defer s.Stop() - fmt.Printf("Starting rpc server at %s...\n", c.ListenOn) + logx.Info("Starting rpc server at %s...\n", c.ListenOn) s.Start() } -- 2.40.1 From 0ce0286da7d6cbd053dffc8566e17275b3914e20 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Thu, 22 Aug 2024 22:25:24 +0800 Subject: [PATCH 7/7] add cfg --- etc/service.example.yaml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 etc/service.example.yaml diff --git a/etc/service.example.yaml b/etc/service.example.yaml new file mode 100644 index 0000000..f144f35 --- /dev/null +++ b/etc/service.example.yaml @@ -0,0 +1,37 @@ +Name: member.rpc +ListenOn: 0.0.0.0:8080 +Etcd: + Hosts: + - 127.0.0.1:2379 + Key: member.rpc +DB: + DsnString: root:yytt@tcp(127.0.0.1:3306)/ark_member?charset=utf8mb4&parseTime=true&loc=Asia%2FTaipei +Cache: + - Host: 127.0.0.1:7001 + type: cluster + - Host: 127.0.0.1:7002 + type: cluster + - Host: 127.0.0.1:7003 + type: cluster + - Host: 127.0.0.1:7004 + type: cluster + - Host: 127.0.0.1:7005 + type: cluster + - Host: 127.0.0.1:7006 + type: cluster + +Bcrypt: + Cost: 10 + +RedisCluster: + Host: 127.0.0.1:7001 + Type: cluster + +Mongo: + Schema: mongodb + Host: 127.0.0.1 + User: "" + Password: "" + Port: "27017" + Database: digimon_member + Collection: count -- 2.40.1