Compare commits

..

459 Commits

Author SHA1 Message Date
Kevin Wan e31128650e Revert "🐞 fix(gen): pg gen of insert (#1591)" (#1598)
This reverts commit cc4c4928e0.
2022-03-01 20:27:59 +08:00
Kevin Wan 168740b64d chore: upgrade etcd (#1597) 2022-03-01 20:16:44 +08:00
toutou_o cc4c4928e0 🐞 fix(gen): pg gen of insert (#1591)
Co-authored-by: kurimi1 <d0n41df@gmail.com>
2022-03-01 19:53:23 +08:00
Fyn fba6543b23 fix: goctl api dart support form tag (#1596) 2022-03-01 16:17:37 +08:00
Kevin Wan 877eb6ac56 Update readme.md
add producthunt.
2022-03-01 16:11:17 +08:00
Kevin Wan 259a5a13e7 chore: fix data race (#1593) 2022-02-28 23:17:51 +08:00
Fyn cf7c7cb392 build: update goctl dependency ddl-parser to v1.0.3 (#1586)
* build: update goctl dependency ddl-parser to v1.0.3

* fix: race condition when testing logx

Resolves: #1587
2022-02-28 17:31:59 +08:00
ccx 86d01e2e99 test: add testcase for FIFO Queue in collection module (#1589)
cover the case of non-zero value for q.Header when q.Elements expands
2022-02-28 17:15:11 +08:00
Kevin Wan 7a28e19a27 Update readme-cn.md 2022-02-27 23:30:14 +08:00
Kevin Wan 900ea63d68 Update readme-cn.md
add migration notice.
2022-02-27 23:29:45 +08:00
Kevin Wan 87ab86cdd0 Update readme.md 2022-02-27 23:26:03 +08:00
Kevin Wan 0697494ffd Update readme.md
Add migrate steps.
2022-02-27 23:25:22 +08:00
anqiansong ffd69a2f5e Fix bug int overflow while build goctl on arch 386 (#1582)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-02-27 10:51:57 +08:00
Kevin Wan 66f10bb5e6 chore: add goctl command help (#1578) 2022-02-26 17:02:04 +08:00
Kevin Wan 8131a0e777 Update readme.md
update chat link.
2022-02-25 23:02:09 +08:00
Kevin Wan 32a557dff6 Update readme.md
add discord.
2022-02-25 23:01:15 +08:00
Fyn db949e40f1 feat: supports importValue for more path formats (#1569)
`importValueRegex` now can match more path formats

Resolves: #1568
2022-02-25 11:16:57 +08:00
Kevin Wan e0454138e0 update goctl to go 1.16 for io/fs usage (#1571)
* update goctl to go 1.16 for io/fs usage

* feat: support pg serial type for auto_increment (#1563)

* add correct example for pg's url

* 🐞 fix: merge

* 🐞 fix: pg default port

*  feat: support serial type

Co-authored-by: kurimi1 <d0n41df@gmail.com>

* chore: format code

Co-authored-by: toutou_o <33993460+kurimi1@users.noreply.github.com>
Co-authored-by: kurimi1 <d0n41df@gmail.com>
2022-02-24 13:58:53 +08:00
toutou_o 3b07ed1b97 feat: support pg serial type for auto_increment (#1563)
* add correct example for pg's url

* 🐞 fix: merge

* 🐞 fix: pg default port

*  feat: support serial type

Co-authored-by: kurimi1 <d0n41df@gmail.com>
2022-02-24 13:39:31 +08:00
anqiansong daa98f5a27 Feature: Add goctl env (#1557) 2022-02-21 10:19:33 +08:00
Kevin Wan 842656aa90 feat: log 404 requests with traceid (#1554) 2022-02-19 20:50:33 +08:00
Kevin Wan aa29036cb3 feat: support ctx in sql model generation (#1551) 2022-02-17 10:28:55 +08:00
Kevin Wan 607bae27fa feat: support ctx in sqlx/sqlc, listed in ROADMAP (#1535)
* feat: support ctx in sqlx/sqlc

* chore: update roadmap

* fix: context.Canceled should be acceptable

* use %w to wrap errors

* chore: remove unused vars
2022-02-16 19:31:43 +08:00
Kevin Wan 7c63676be4 docs: add go-zero users (#1546) 2022-02-16 12:02:52 +08:00
Kevin Wan 9e113909b3 ignore context.Canceled for redis breaker (#1545) 2022-02-15 21:31:30 +08:00
Kevin Wan bd105474ca chore: update help message (#1544) 2022-02-15 21:19:40 +08:00
Mikael a078f5d764 add the serviceAccount of deployment (#1543)
Co-authored-by: 977231903@qq.com <>
2022-02-15 20:57:14 +08:00
Kevin Wan b215fa3ee6 fix #1541 (#1542) 2022-02-15 18:40:26 +08:00
mlr3000 50b1928502 chore:use struct pointer (#1538) 2022-02-15 11:34:48 +08:00
Kevin Wan 493e3bcf4b docs: update roadmap (#1537) 2022-02-15 08:37:03 +08:00
Kevin Wan 6deb80625d fix issue of default migrate version (#1536)
* fix issue of default migrate version

* chore: update console colors
2022-02-14 23:09:32 +08:00
Kevin Wan 6ab051568c Update readme-cn.md
add go-zero users
2022-02-14 16:57:48 +08:00
Kevin Wan 2732d3cdae chore: refactor cache (#1532) 2022-02-13 18:04:31 +08:00
chenquan e8c307e4dc feat: support ctx in Cache (#1518)
* feature: support ctx in `Cache`

Signed-off-by: chenquan <chenquan.dev@foxmail.com>

* fix: `errors.Is` instead of `=`

Signed-off-by: chenquan <chenquan.dev@foxmail.com>
2022-02-13 17:28:14 +08:00
Kevin Wan 84ddc660c4 chore: goctl format issue (#1531) 2022-02-13 13:17:19 +08:00
Kevin Wan e60e707955 upgrade grpc version (#1530) 2022-02-12 23:58:41 +08:00
Kevin Wan cf4321b2d0 fix #1525 (#1527) 2022-02-11 23:04:57 +08:00
chenquan 1993faf2f8 fix: fix a typo (#1522)
Signed-off-by: chenquan <chenquan.dev@foxmail.com>
2022-02-11 21:15:45 +08:00
Kevin Wan 0ce85376bf chore: update goctl version to 1.3.2 (#1524) 2022-02-11 21:02:50 +08:00
Kevin Wan a40254156f refactor: refactor yaml unmarshaler (#1517) 2022-02-09 17:22:52 +08:00
chenquan 05cc62f5ff chore: optimize yaml unmarshaler (#1513) 2022-02-09 16:57:00 +08:00
chenquan 9c2c90e533 chore: make error clearer (#1514) 2022-02-09 14:40:05 +08:00
Kevin Wan 822ee2e1c5 feat: update go-redis to v8, support ctx in redis methods (#1507)
* feat: update go-redis to v8, support ctx in redis methods

* fix compile errors

* chore: remove unused const

* chore: add tracing log on redis
2022-02-09 11:06:06 +08:00
anqiansong 77482c8946 fixes typo (#1511)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-02-08 22:16:38 +08:00
Kevin Wan 7ef0ab3119 Update readme-cn.md 2022-02-08 11:47:33 +08:00
anqiansong 8bd89a297a feature: Add goctl completion (#1505)
* feature: Add `goctl completion`

* Update const

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-02-08 10:50:21 +08:00
Kevin Wan bb75cc796e test: change fuzz tests (#1504) 2022-02-05 09:44:01 +08:00
Kevin Wan 0fdd8f54eb ci: add test for win (#1503)
* ci: add test for win

* ci: update check names

* ci: use go build instead of go test to verify win test

* fix: windows test failure

* chore: disable logs in tests
2022-02-05 00:06:23 +08:00
anqiansong b1ffc464cd fix typo: goctl protoc usage (#1502)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-02-03 22:13:02 +08:00
Kevin Wan 50174960e4 chore: update command comment (#1501) 2022-02-02 22:02:08 +08:00
Kevin Wan 8f46eab977 fix: goctl not compile on windows (#1500) 2022-02-01 13:58:08 +08:00
Kevin Wan ec299085f5 docs: update tal-tech to zeromico in docs (#1498) 2022-02-01 13:03:30 +08:00
Kevin Wan 7727d70634 chore: update goctl version (#1497) 2022-02-01 09:50:26 +08:00
Kevin Wan 5f9d101bc6 feat: add runtime stats monitor (#1496) 2022-02-01 01:34:25 +08:00
Kevin Wan 6c2abe7474 fix: goroutine stuck on edge case (#1495)
* fix: goroutine stuck on edge case

* refactor: simplify mapreduce implementation
2022-01-30 13:09:21 +08:00
Kevin Wan 14a902c1a7 feat: handling panic in mapreduce, panic in calling goroutine, not inside goroutines (#1490)
* feat: handle panic

* chore: update fuzz test

* chore: optimize square sum algorithm
2022-01-28 10:59:41 +08:00
Kevin Wan 5ad6a6d229 Update readme-cn.md
add slogan
2022-01-27 17:16:30 +08:00
Kevin Wan 6f4b97864a chore: improve migrate confirmation (#1488) 2022-01-27 11:30:35 +08:00
Kevin Wan 0e0abc3a95 chore: update warning message (#1487) 2022-01-26 23:47:57 +08:00
anqiansong 696fda1db4 patch: goctl migrate (#1485)
* * Add signal check
* Add deprecated pkg check

* fix typo `replacementBuilderx`

* output to console if verbose

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-26 23:24:25 +08:00
Kevin Wan c1d2634427 chore: update go version for goctl (#1484) 2022-01-26 14:27:43 +08:00
Kevin Wan 4b7a680ac5 refactor: rename from tal-tech to zeromicro for goctl (#1481) 2022-01-25 23:15:07 +08:00
Kevin Wan b3e7d2901f Feature/trie ac automation (#1479)
* fix: trie ac automation issues

* fix: trie ac automation issues

* fix: trie ac automation issues

* fix: trie ac automation issues
2022-01-25 11:14:56 +08:00
anqiansong cdf7ec213c fix #1468 (#1478)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-24 22:23:20 +08:00
Kevin Wan f1102fb262 chore: optimize string search with Aho–Corasick algorithm (#1476)
* chore: optimize string search with Aho–Corasick algorithm

* chore: optimize keywords replacer

* fix: replacer bugs

* chore: reorder members
2022-01-23 23:37:02 +08:00
Keqi Huang 09d1fad6e0 Polish the words in readme.md (#1475) 2022-01-22 12:20:11 +08:00
Kevin Wan 379c65a3ef docs: add go-zero users (#1473) 2022-01-20 22:36:17 +08:00
Kevin Wan fdc7f64d6f chore: update unauthorized callback calling order (#1469)
* chore: update unauthorized callback calling order

* chore: add comments
2022-01-20 21:09:45 +08:00
anqiansong df0f8ed59e Fix/issue#1289 (#1460)
* fix #1289

* Add unit test case

* fix `jwtTransKey`

* fix `jwtTransKey`

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-18 11:52:30 +08:00
anqiansong c903966fc7 patch: save missing templates to disk (#1463)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-18 10:45:05 +08:00
anqiansong e57fa8ff53 Fix/issue#1447 (#1458)
* Add data for template to render

* fix #1447

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-18 10:36:38 +08:00
Kevin Wan bf2feee5b7 feat: implement console plain output for debug logs (#1456)
* feat: implement console plain output for debug logs

* chore: rename console encoding to plain

* chore: refactor names
2022-01-17 12:43:15 +08:00
Letian Jiang ce05c429fc chore: check interface satisfaction w/o allocating new variable (#1454) 2022-01-16 23:34:42 +08:00
Kevin Wan 272a3f347d chore: remove jwt deprecated (#1452) 2022-01-16 10:34:44 +08:00
shenbaise9527 13db7a1931 feat: 支持redis的LTrim方法 (#1443) 2022-01-16 10:27:34 +08:00
Kevin Wan 468c237189 chore: upgrade dependencies (#1444)
* chore: upgrade dependencies

* ci: upgrade go to 1.15
2022-01-14 11:01:02 +08:00
Kevin Wan b9b80c068b ci: add translator action (#1441) 2022-01-12 17:57:39 +08:00
anqiansong 9b592b3dee Feature rpc protoc (#1251)
* code generation by protoc

* generate pb by protoc direct

* support: grpc code generation by protoc directly

* format code

* check --go_out & --go-grpc_out

* fix typo

* Update version

* fix typo

* optimize: remove deprecated unit test

* format code

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-11 20:34:25 +08:00
Kevin Wan 2203809e5e chore: fix typo (#1437) 2022-01-11 20:23:59 +08:00
Kevin Wan 8d6d37f71e remove unnecessary drain, fix data race (#1435)
* remove unnecessary drain, fix data race

* chore: fix parameter order

* refactor: rename MapVoid to ForEach in mr
2022-01-11 16:17:51 +08:00
Kevin Wan ea4f2af67f fix: mr goroutine leak on context deadline (#1433)
* fix: mr goroutine leak on context deadline

* test: update fx test check
2022-01-10 22:06:10 +08:00
Kevin Wan 53af194ef9 chore: refactor periodlimit (#1428)
* chore: refactor periodlimit

* chore: add comments
2022-01-09 16:22:34 +08:00
Kevin Wan 5e0e2d2b14 docs: add go-zero users (#1425) 2022-01-08 21:41:27 +08:00
Kevin Wan 74c99184c5 docs: add go-zero users (#1424) 2022-01-08 17:08:44 +08:00
Kevin Wan eb4b86137a fix: golint issue (#1423) 2022-01-08 16:06:56 +08:00
Kevin Wan 9c4f4f3b4e update docs (#1421) 2022-01-07 12:08:45 +08:00
spectatorMrZ 240132e7c7 Fix pg model generation without tag (#1407)
1. fix pg model struct haven't tag
2. add pg command test from datasource
2022-01-07 10:45:26 +08:00
anqiansong 9d67fc4cfb feat: Add migrate (#1419)
* Add migrate

* Remove unused module

* refactor filename

* rename refactor to migrate

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-06 18:48:34 +08:00
Kevin Wan 892f93a716 docs: update install readme (#1417) 2022-01-05 12:31:49 +08:00
Kevin Wan ba6a7c9dc8 chore: refactor rest/timeouthandler (#1415) 2022-01-05 11:17:10 +08:00
Kevin Wan a91c3907a8 feat: rename module from tal-tech to zeromicro (#1413) 2022-01-04 15:51:32 +08:00
Kevin Wan e267d94ee1 chore: update go-zero to v1.2.5 (#1410) 2022-01-03 21:54:53 +08:00
anqiansong 89ce5e492b refactor file|path (#1409)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-03 21:32:40 +08:00
Kevin Wan 290de6aa96 docs: update roadmap (#1405) 2022-01-02 21:30:02 +08:00
Kevin Wan a7aeb8ac0e feat: support tls for etcd client (#1390)
* feat: support tls for etcd client

* chore: fix typo

* refactor: rename TrustedCAFile to CACertFile

* docs: add comments

* fix: missing tls registration

* feat: add InsecureSkipVerify config for testing
2022-01-02 20:23:50 +08:00
Kevin Wan a8e7fafebf refactor: optimize fx (#1404)
* refactor: optimize fx

* chore: add more comments

* ci: make test robust
2022-01-02 14:56:30 +08:00
Kevin Wan 7cc64070b1 docs: update goctl installation command (#1403) 2022-01-02 14:31:31 +08:00
Kevin Wan c19d2637ea feat: implement fx.NoneMatch, fx.First, fx.Last (#1402)
* chore: use workers from options in fx.unlimitedWalk

* feat: add fx.NoneMatch

* feat: add fx.First, fx.Last

* chore: add more comments

* docs: add mr readme
2022-01-02 13:33:15 +08:00
Kevin Wan fe1da14332 chore: simplify mapreduce (#1401) 2022-01-01 19:24:35 +08:00
anqiansong 8e9110cedf fix #1330 (#1382)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-12-30 20:44:04 +08:00
Kevin Wan d6ff30a570 chore: fix golint issues (#1396) 2021-12-30 17:44:15 +08:00
Kevin Wan b98d46bfd6 chore: update goctl version (#1394) 2021-12-30 15:30:16 +08:00
Kevin Wan 768936b256 ci: remove 386 binaries (#1393) 2021-12-30 15:18:24 +08:00
Kevin Wan c6eb1a9670 ci: remove windows 386 binary (#1392)
* ci: remove windows 386 binary

* chore: update go-zero

* chore: update go-zero
2021-12-30 14:47:53 +08:00
Kevin Wan e4ab518576 test: add more tests (#1391) 2021-12-30 14:21:55 +08:00
moyrne dfc67b5fac fix readme-cn (#1388) 2021-12-30 10:42:23 +08:00
Kevin Wan 62266d8f91 fix #1070 (#1389)
* fix #1070

* test: add more tests
2021-12-29 21:34:28 +08:00
anqiansong b8ea16a88e feat: Add --remote (#1387)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-12-29 18:16:42 +08:00
Kevin Wan 23deaf50e6 feat: support array in default and options tags (#1386)
* feat: support array in default and options tags

* feat: ignore spaces in tags

* test: add more tests
2021-12-29 17:37:36 +08:00
Kevin Wan 38a36ed8d3 docs: add go-zero users (#1381) 2021-12-28 17:12:51 +08:00
anqiansong 49bab23c54 fix #1376 (#1380)
* fix #1376

* fix #1376

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-12-28 16:40:26 +08:00
Leizhengzi 78ba00d3a7 fix: command system info missing go version (#1377) 2021-12-27 22:05:27 +08:00
Kevin Wan 787b046a70 docs: update slack invitation link (#1378) 2021-12-27 16:52:08 +08:00
Kevin Wan f827a7b985 chore: update goctl version to 1.2.4 for release tools/goctl/v1.2.4 (#1372) 2021-12-27 10:57:55 +08:00
行者 f5f2097d14 Updated MySQL生成表结构体遇到关键字db部分保持原字段名定义 (#1369) 2021-12-26 21:56:04 +08:00
Kevin Wan cfcfb87fd4 ci: add release action to auto build binaries (#1371) 2021-12-26 21:44:33 +08:00
Kevin Wan 1d223fc114 docs: update goctl markdown (#1370) 2021-12-26 20:32:31 +08:00
Kevin Wan c0647f0719 feat: support context in MapReduce (#1368) 2021-12-25 20:42:52 +08:00
Kevin Wan 8745ed9c61 chore: add 1s for tolerance in redislock (#1367) 2021-12-25 19:44:27 +08:00
种豆得豆 836726e710 fix redis try-lock bug (#1366)
#issue_id: 1338

Co-authored-by: zhangwei <>
2021-12-25 19:20:53 +08:00
JiangYiJun a67c118dcf go-zero tools ,fix a func,api new can not choose style (#1356) 2021-12-23 10:28:46 +08:00
Kevin Wan cd289465fd chore: coding style and comments (#1361)
* chore: coding style and comments

* chore: optimize `ParseJsonBody` (#1353)

* chore: optimize `ParseJsonBody`

* chore: optimize `ParseJsonBody`

* fix: fix a test

* chore: optimize `ParseJsonBody`

* fix a test

* chore: add comment

* chore: refactor

Co-authored-by: chenquan <chenquan.dev@foxmail.com>
2021-12-22 21:43:37 +08:00
chenquan 263e426ae1 chore: optimize ParseJsonBody (#1353)
* chore: optimize `ParseJsonBody`

* chore: optimize `ParseJsonBody`

* fix: fix a test

* chore: optimize `ParseJsonBody`

* fix a test

* chore: add comment
2021-12-22 20:24:55 +08:00
charliecen d5e493383a chose: cancel the assignment and judge later (#1359)
Co-authored-by: charliecen <chq@abierr.com>
2021-12-22 20:05:35 +08:00
Kevin Wan 6f1d27354a chore: put error message in error.log for verbose mode (#1355) 2021-12-21 11:36:01 +08:00
Kevin Wan 26101732d2 test: add more tests (#1352) 2021-12-20 22:42:36 +08:00
Kevin Wan 71d40e0c08 Revert "排除客户端中断导致的503错误 (#1343)" (#1351)
This reverts commit 2cdf5e7395.
2021-12-20 20:34:43 +08:00
Kevin Wan 4ba2ff7cdd feat: treat client closed requests as code 499 (#1350)
* feat: treat client closed requests as code 499

* chore: add comments
2021-12-20 19:43:38 +08:00
vic 2cdf5e7395 排除客户端中断导致的503错误 (#1343) 2021-12-20 19:43:13 +08:00
Kevin Wan 8315a55b3f Update FUNDING.yml
enable sponsorship.
2021-12-20 15:27:05 +08:00
Kevin Wan d1c2a31af7 chore: add tests & refactor (#1346)
* chore: add tests & refactor

* chore: refactor
2021-12-18 23:11:38 +08:00
MarkJoyMa 3e6c217408 Feature: support adding custom cache to mongoc and sqlc (#1313)
* merge

* Feature: support adding custom cache to mongoc and sqlc
2021-12-18 22:45:07 +08:00
Kevin Wan b299f350be chore: add comments (#1345) 2021-12-18 22:39:14 +08:00
Kevin Wan 8fd16c17dc chore: update goctl version to 1.2.5 (#1337) 2021-12-16 00:21:54 +08:00
anqiansong 5979b2aa0f Update template (#1335)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-12-15 23:24:32 +08:00
anqiansong 0b17e0e5d9 Feat goctl bug (#1332)
* Support goctl bug

* fix typo

* format code

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-12-15 22:43:58 +08:00
Kevin Wan 3d8ad5e4f6 feat: tidy mod, update go-zero to latest (#1334) 2021-12-15 22:34:58 +08:00
Kevin Wan ff1752dd39 feat: tidy mod, update go-zero to latest (#1333) 2021-12-15 22:23:06 +08:00
Kevin Wan 1becaeb7be chore: refactor (#1331) 2021-12-15 20:44:23 +08:00
yangkequn 171afaadb9 Update types.go (#1314) 2021-12-15 20:16:17 +08:00
Kevin Wan 776e6e647d feat: tidy mod, add go.mod for goctl (#1328) 2021-12-15 19:44:49 +08:00
Kevin Wan 4ccdf4ec72 chore: format code (#1327) 2021-12-15 13:43:05 +08:00
CrazyZard a7bd993c0c commit missing method for redis (#1325)
* commit `decr ` `decrby` `lindex` missing method for redis

* fix(store_test):TestRedis_DecrBy

* add unit tests for redis commands. And put the functions in alphabetical order

* put the functions in alphabetical order

* add `lindex` unit test

* sort func
2021-12-15 13:15:39 +08:00
Kevin Wan a290ff4486 docs: add go-zero users (#1323) 2021-12-14 13:37:49 +08:00
Kevin Wan 490ef13822 style: format code (#1322) 2021-12-14 11:29:44 +08:00
anqiansong 1b14de2ff9 fix: #1318 (#1321)
* fix #1318

* fix #1318

* remove never used code

* fix unit tes

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-12-13 22:55:11 +08:00
Kevin Wan 914692cc82 fix #1309 (#1317) 2021-12-13 11:58:58 +08:00
anqiansong 07191dc430 fix #1305 (#1307)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-12-07 22:24:18 +08:00
BYT0723 af3fb2b04d fix: go issue 16206 (#1298) 2021-12-07 15:52:37 +08:00
Kevin Wan 0240fa131a chore: rename service context from ctx to svcCtx (#1299) 2021-12-05 22:10:47 +08:00
Kevin Wan e96577dd38 docs: add go-zero users (#1294) 2021-12-03 22:32:35 +08:00
Kevin Wan 403dd7367a fix #1288 (#1292)
* fix #1288

* chore: make wrapup & shutdown callbacks run simulatenously
2021-12-02 22:41:57 +08:00
Kevin Wan 8086ad120b Revert "feat: reduce dependencies of framework by add go.mod in goctl (#1290)" (#1291)
This reverts commit 87a445689c.
2021-12-02 19:40:23 +08:00
Kevin Wan 87a445689c feat: reduce dependencies of framework by add go.mod in goctl (#1290) 2021-12-02 16:57:07 +08:00
Kevin Wan b6bda54870 chore: update cli version (#1287) 2021-12-01 23:33:23 +08:00
Kevin Wan 9d528dddd6 feat: support third party orm to interact with go-zero (#1286)
* fixes #987

* chore: fix test failure

* chore: add comments

* feat: support third party orm to interact with go-zero

* chore: refactor
2021-12-01 20:22:15 +08:00
Kevin Wan 543d590710 fixes #987 (#1283)
* fixes #987

* chore: fix test failure

* chore: add comments
2021-12-01 17:45:48 +08:00
anqiansong f1d70eb6b2 Feature api root path (#1261) 2021-12-01 10:09:07 +08:00
Kevin Wan d828c3f37e feat: add etcd resolver scheme, fix discov minor issue (#1281) 2021-11-28 20:08:18 +08:00
Kevin Wan 038491b7bc chore: cleanup zRPC retry code (#1280) 2021-11-27 18:39:52 +08:00
chenquan cf683411ee feature(retry): Delete retry mechanism (#1279) 2021-11-27 11:32:33 +08:00
Kevin Wan de5ed6a677 feat: support %w in logx.Errorf (#1278) 2021-11-26 15:57:23 +08:00
Kevin Wan 3dda557410 chore: only allow cors middleware to change headers (#1276) 2021-11-26 14:14:06 +08:00
Kevin Wan c800f6f723 chore: avoid superfluous WriteHeader call errors (#1275) 2021-11-26 11:09:57 +08:00
Kevin Wan 0395ba1816 feat: add rest.WithCustomCors to let caller customize the response (#1274) 2021-11-25 23:03:37 +08:00
Kevin Wan 86f9f63b46 Cli (#1272)
* Fix issue 1260 (#1262)

* Fix #1238 (#1266)

* docs: update readme to use goctl@cli (#1255)

* chore: update goctl version

* style: coding style

* docs: update readme to use goctl@cli

* fix #1238

* format code

* format code

Co-authored-by: Kevin Wan <wanjunfeng@gmail.com>
Co-authored-by: anqiansong <anqiansong@bytedance.com>

Co-authored-by: anqiansong <anqiansong@gmail.com>
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-11-25 11:08:49 +08:00
Kevin Wan a7a6753118 fixes #1257 (#1271)
* fixes #1257

* chore: format code

* test: add more tests
2021-11-25 10:26:16 +08:00
Kevin Wan 2e80d12d6a docs: update readme to use goctl@cli (#1255)
* chore: update goctl version

* style: coding style

* docs: update readme to use goctl@cli
2021-11-17 21:10:45 +08:00
Kevin Wan 417a96cbf2 chore: update goctl version (#1250)
* chore: update goctl version

* style: coding style
2021-11-16 21:57:55 +08:00
Kevin Wan 2d4c29ea7c Revert "Revert "feat: enable retry for zrpc (#1237)"" (#1246) 2021-11-16 10:29:31 +08:00
Kevin Wan 67db40ed4f Revert "feat: enable retry for zrpc (#1237)" (#1245)
This reverts commit 09eb53f308.
2021-11-15 23:30:31 +08:00
FabioCircle 11c485a5ed Duplicate temporary variable (#1244)
Co-authored-by: fabiowzhang <fabiowzhang@wesure.cn>
2021-11-15 23:14:54 +08:00
anqiansong b0573af9a9 Update template (#1243) 2021-11-15 21:02:11 +08:00
Kevin Wan 09eb53f308 feat: enable retry for zrpc (#1237) 2021-11-14 22:33:01 +08:00
Kevin Wan 11f85d1b80 chore: remove conf.CheckedDuration (#1235) 2021-11-13 23:34:30 +08:00
anqiansong 0cb86c6990 reset link goctl (#1232) 2021-11-13 18:39:07 +08:00
Kevin Wan 57d2f22c24 feat: disable grpc retry, enable it in v1.2.4 (#1233) 2021-11-13 15:38:43 +08:00
Kevin Wan fa0c364982 fixes #1169 (#1229) 2021-11-12 14:05:28 +08:00
Kevin Wan a6c8113419 chore: refactor, better goctl message (#1228) 2021-11-11 22:58:33 +08:00
Kevin Wan 4f5c30e083 chore: remove unused const (#1224) 2021-11-10 21:45:42 +08:00
Kevin Wan 9d0b51fa26 fixes #1222 (#1223) 2021-11-10 21:25:51 +08:00
Kevin Wan ba5f8045a2 Update FUNDING.yml
disable sponsor button.
2021-11-10 21:22:34 +08:00
an 3a510a9138 chore: redislock use stringx.randn replace randomStr func (#1220) 2021-11-10 21:14:21 +08:00
Kevin Wan d3bfa16813 feat: exit with non-zero code on errors (#1218)
* feat: exit with non-zero code on errors

* chore: use const for code
2021-11-09 22:42:44 +08:00
Kevin Wan 28409791fa feat: support CORS, better implementation (#1217)
* feat: support CORS, better implementation

* chore: refine code
2021-11-09 20:35:57 +08:00
Kevin Wan c1abe87953 Create FUNDING.yml
add sponsor button
2021-11-09 14:27:36 +08:00
Kevin Wan f8367856e8 chore: refine code (#1215) 2021-11-08 23:12:13 +08:00
Kevin Wan a72b0a689b docs: add go-zero users (#1214) 2021-11-08 16:13:24 +08:00
anqiansong 69a4d213a3 Fix issue 1205 (#1211)
* fix #1205

* move builder into stores

* remove xrom

* Remove unused code

* Remove unused code

* refactor builderx to builder

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-11-07 22:44:37 +08:00
Kevin Wan c28e01fed3 feat: support CORS by using rest.WithCors(...) (#1212)
* feat: support CORS by using rest.WithCors(...)

* chore: add comments

* refactor: lowercase unexported methods

* ci: fix lint errors
2021-11-07 22:42:40 +08:00
Kevin Wan e8efcef108 update dependencies. (#1210)
* chore: update dependencies

* chore: update dependencies

* chore: update dependencies

* chore: update dependencies

* chore: fix test failure
2021-11-07 16:38:20 +08:00
Kevin Wan d011316997 test: add more tests (#1209) 2021-11-07 11:41:24 +08:00
Kevin Wan 4d22b0c497 feat: ignore rest.WithPrefix on empty prefix (#1208) 2021-11-06 21:31:35 +08:00
晨曦中 539215d7df goctl docker command add -version (#1206)
* feature(优化): 优化goctl

goctl docker 命令新增version参数,指定builder golang 版本

* feature(优化): 优化goctl

goctl docker 命令新增version参数,指定builder golang 版本
2021-11-06 21:28:32 +08:00
Kevin Wan 3ede597a15 feat: support customizing timeout for specific route (#1203)
* feat: support customizing timeout for specific route

* test: add more tests
2021-11-03 22:20:32 +08:00
anqiansong 01786c5e63 Generate route with prefix (#1200)
* Generate route with prefix

* Update api convert

* Remove TrimSpace

* Update path join

* Format code

* Format code

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-11-03 20:57:03 +08:00
yedf2 6aba5f74fc feat: add NewSessionFromTx to interact with other orm (#1202)
Co-authored-by: yedongfu <dongfuye@163.com>
2021-11-03 20:56:02 +08:00
Kevin Wan 3c894a3fb7 feat: simplify the grpc tls authentication (#1199) 2021-11-02 20:42:22 +08:00
Kevin Wan 1ece3a498f feat: use WithBlock() by default, NonBlock can be set in config or WithNonBlock() (#1198) 2021-11-02 19:02:02 +08:00
Kevin Wan b76c7ae55d chore: remove semicolon for routes of services in api files (#1195) 2021-11-01 20:37:05 +08:00
Kevin Wan 91b10bd3b9 feat: add rest.WithPrefix to support route prefix (#1194) 2021-11-01 20:15:10 +08:00
Kevin Wan 7e3fe77e7b chore: update goctl version to 1.2.3, prepare for release (#1193)
* feat: slow threshold customizable in rest

* chore: update goctl version to 1.2.3, prepare for release
2021-11-01 18:26:08 +08:00
Kevin Wan ba43214dae feat: slow threshold customizable in zrpc (#1191)
* feat: slow threshold customizable in rest

* feat: slow threshold customizable in rest

* feat: slow threshold customizable in rest

* feat: slow threshold customizable in zrpc
2021-11-01 15:04:38 +08:00
Kevin Wan ebc90720ea feat: slow threshold customizable in rest (#1189)
* feat: slow threshold customizable in rest

* feat: slow threshold customizable in rest
2021-11-01 14:48:26 +08:00
Kevin Wan 785d100be9 feat: slow threshold customizable in sqlx (#1188) 2021-11-01 08:37:44 +08:00
Kevin Wan f13e6f1149 feat: slow threshold customizable in redis (#1187) 2021-11-01 08:20:35 +08:00
Kevin Wan 8be0f77d96 feat: slow threshold customizable in mongo (#1186) 2021-11-01 07:12:53 +08:00
Kevin Wan 429f85a9de feat: slow threshold customizable in redis (#1185)
* feat: slow threshold customizable in redis

* chore: improve config robustness
2021-10-31 22:14:20 +08:00
Kevin Wan b4d1c6da2c docs: update roadmap (#1184) 2021-10-31 21:00:34 +08:00
Kevin Wan 3c1cfd4c1e feat: support multiple trace agents (#1183)
* feat: support multiple trace agents

* feat: support multiple trace agents, let later calls run if error happens

* test: add more tests
2021-10-31 19:58:01 +08:00
Kevin Wan a71a210704 feat: let different services start prometheus on demand (#1182) 2021-10-31 18:54:13 +08:00
Kevin Wan 769d06c8ab refactor: simplify tls config in rest (#1181) 2021-10-31 14:10:47 +08:00
Howie cd1f8da13f [update] add plugin config (#1180)
Signed-off-by: lihaowei <haoweili35@gmail.com>
2021-10-31 12:56:25 +08:00
Kevin Wan 8230474667 test: add more tests (#1179) 2021-10-31 11:33:13 +08:00
Kevin Wan 27f553bf84 docs: update roadmap (#1178) 2021-10-31 11:13:45 +08:00
Kevin Wan d48bff8c8b docs: add go-zero users (#1176) 2021-10-31 10:02:46 +08:00
Kevin Wan 59b9687f31 feat: support auth account for etcd (#1174) 2021-10-31 09:05:38 +08:00
Kevin Wan c1a8ccda11 feat: support ssl on zrpc, simplify the config (#1175) 2021-10-30 23:15:39 +08:00
workman-Lu 9df6786b09 support RpcClient Vertify With Unilateralism and Mutual (#647)
Co-authored-by: Kevin Wan <wanjunfeng@gmail.com>
2021-10-30 22:07:15 +08:00
anqiansong bef5bd4e4f fix the package name of grpc client (#1170)
* fix the package name of grpc client

* Remove k8s/utils

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-10-30 21:35:05 +08:00
Kevin Wan 68acfb1891 docs: add go-zero users (#1172) 2021-10-29 21:39:28 +08:00
zeromake 9fd3f752d1 fix(goctl): repeat creation protoc-gen-goctl symlink (#1162) 2021-10-29 09:56:51 +08:00
anqiansong 9c48e9ceab Feature add template version (#1152) 2021-10-29 09:55:41 +08:00
Kevin Wan bd26783b33 test: add more tests (#1166)
* chore: reverse the order of stopping services

* chore: reverse the order of stopping services

* test: add more tests
2021-10-28 10:04:59 +08:00
Kevin Wan eda8230521 chore: reorg imports, format code, make MaxRetires default to 0 (#1165)
* chore: reverse the order of stopping services

* chore: reverse the order of stopping services

* chore: reorg imports, format code

* chore: format code, and refactor

* feat: change MaxRetries default to 0, disable retry
2021-10-27 20:57:18 +08:00
chenquan 462ddbb145 Add grpc retry (#1160)
* Add grpc retry

* Update grpc retry

* Add tests

* Fix a bug

* Add api && some tests

* Add comment

* Add double check

* Add server retry quota

* Update optimize code

* Fix bug

* Update optimize code

* Update optimize code

* Fix bug
2021-10-27 19:46:07 +08:00
Kevin Wan 496a2f341e test: add more tests (#1163)
* chore: reverse the order of stopping services

* chore: reverse the order of stopping services

* test: add more tests
2021-10-25 21:10:08 +08:00
Kevin Wan 7109d6d635 chore: reverse the order of stopping services (#1159)
* chore: reverse the order of stopping services

* chore: reverse the order of stopping services
2021-10-24 12:01:17 +08:00
Kevin Wan ca72241fa3 docs: update qr code (#1158) 2021-10-23 22:12:50 +08:00
Kevin Wan a6bdffd225 test: add more tests (#1154) 2021-10-21 21:16:18 +08:00
Kevin Wan 5636bf4955 test: add more tests (#1150) 2021-10-20 17:50:01 +08:00
anqiansong a944a7fd7e Mark deprecated syntax (#1148) 2021-10-20 10:58:25 +08:00
Kevin Wan a40fa405e4 test: add more tests (#1149) 2021-10-19 23:48:25 +08:00
Kevin Wan eab77e21dd test: add more tests (#1147)
* test: add more tests

* test: add more tests
2021-10-19 22:37:56 +08:00
Kevin Wan d41163f5c1 docs: add go-zero users (#1141) 2021-10-18 18:38:01 +08:00
Kevin Wan 265b1f2459 test: add more tests (#1138) 2021-10-15 16:27:30 +08:00
Kevin Wan c92ea59228 test: add more tests (#1137) 2021-10-15 16:07:38 +08:00
Kevin Wan afddfea093 docs: add go-zero users (#1135) 2021-10-14 12:50:25 +08:00
Kevin Wan fa4dc151ca test: add more tests (#1134) 2021-10-13 22:42:54 +08:00
anqiansong 44202acb18 Fix issue #1127 (#1131)
* fix #1127

* fix #1127

* fixed unit test

* add go keyword converter

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-10-13 20:48:47 +08:00
Kevin Wan cf00786209 docs: add go-zero users (#1130) 2021-10-12 22:34:13 +08:00
Kevin Wan 6a8638fc85 chore: refine rpc template in goctl (#1129) 2021-10-12 22:13:14 +08:00
Mikael 837a9ffa03 go-zero/core/hash/hash_test.go 增加测试 TestMd5Hex (#1128) 2021-10-12 21:57:07 +08:00
chenquan d28cfe5f20 Add opts ...grpc.CallOption in grpc client (#1122)
* Add `opts ...grpc.CallOption` in grpc client

* Update format

* Update format

* Add import package

* Update format
2021-10-12 21:52:50 +08:00
chenquan 022c100dc9 Add request method in http log (#1120)
* Add request method in http log

* Update log format
2021-10-12 21:50:30 +08:00
Kevin Wan 426b09c356 update goctl version to 1.2.2 (#1125) 2021-10-12 14:00:35 +08:00
Kevin Wan 40dc21e4cf add cncf landscape (#1123) 2021-10-11 15:31:29 +08:00
Kevin Wan 9b114e3251 test: add more tests (#1119) 2021-10-08 17:31:37 +08:00
Kevin Wan 4c6234f108 add more tests (#1115)
* add more tests

* fix lint errors
2021-10-04 21:08:44 +08:00
Kevin Wan 3cdfcb05f1 add more tests (#1114) 2021-10-04 20:02:25 +08:00
Kevin Wan 9f5bfa0088 add more tests (#1113) 2021-10-04 14:14:25 +08:00
Kevin Wan 2d42c8fa00 test: add more tests (#1112) 2021-10-03 21:30:48 +08:00
Kevin Wan 10e7922597 feat: opentelemetry integration, removed self designed tracing (#1111)
* feat: opentelemetry integration, removed self designed tracing

* feat: support zipkin on opentelemetry integration

* feat: support zipkin on opentelemetry integration, enable it in conf

* style: format code

* fix: support logx without exporter configured

* fix: check return values

* refactor: simplify code

* refactor: simplify opentelemetry integration

* ci: fix staticcheck errors
2021-10-03 20:53:50 +08:00
Kevin Wan 6e34b55ba7 docs: update roadmap (#1110) 2021-10-02 18:16:59 +08:00
Kevin Wan ed15ca04f4 fix: opentelemetry traceid not correct (#1108) 2021-10-01 22:44:37 +08:00
小小小下 295ec27e1b feat: reflection grpc service (#1107)
* feat: reflection grpc service

* feat: reflection grpc service
2021-10-01 22:02:04 +08:00
Kevin Wan d1e702e8a3 test: add more tests (#1106)
* style: format code

* test: add more tests

* fix: staticcheck errors
2021-10-01 10:03:56 +08:00
chenquan d1bfb5ef61 Fix the resources variable not reset after the resource manager is closed (#1105)
* Fix the resource variable not reset after the resource manager is closed

* Format code
2021-09-30 16:55:36 +08:00
Kevin Wan e43357164c chore: replace redis.NewRedis with redis.New (#1103) 2021-09-29 23:01:10 +08:00
Kevin Wan cd21c9fa74 chore: mark redis.NewRedis as Deprecated, use redis.New instead. (#1100)
* chore: mark redis.NewRedis as Deprecated

* chore: mark redis.NewRedis as Deprecated
2021-09-29 22:07:05 +08:00
Kevin Wan cdd2fcbbc9 update grpc package (#1099) 2021-09-29 19:30:06 +08:00
理工男 8d2db09d45 Update Makefile (#1098) 2021-09-29 18:04:08 +08:00
Kevin Wan 65905b914d ci: add reviewdog (#1096) 2021-09-29 13:09:20 +08:00
z-micro 80e3407be1 fix bug: generating dart code error (#1090) 2021-09-28 09:01:27 +08:00
Kevin Wan 657d27213a docs: update roadmap (#1094) 2021-09-26 17:41:19 +08:00
Kevin Wan 8ac18a9422 docs: update roadmap (#1093) 2021-09-26 17:38:49 +08:00
Kevin Wan d3ae9cfd49 ci: accurate error reporting on lint check (#1089) 2021-09-25 23:25:40 +08:00
Kevin Wan d7f42161fd update zero-doc links in readme (#1088) 2021-09-24 11:31:00 +08:00
Kevin Wan e03229cabe docs: change organization from tal-tech to zeromicro in readme (#1087) 2021-09-23 20:24:46 +08:00
Kevin Wan 8403ed16ae ci: add Lint check on commits (#1086)
* ci: add Lint check on commits

* ci: fix Lint script error

* test: fix go vet errors

* test: fix go vet errors, remove gofumpt to check go vet

* test: fix go vet errors, try gofumpt

* test: fix go vet errors, try gofumpt, round 1

* test: fix go vet errors, try gofumpt, round 2

* ci: fix Lint errors
2021-09-23 19:57:05 +08:00
Kevin Wan d87d203c3b Revert "chore: run unit test with go 1.14 (#1084)" (#1085)
This reverts commit 3ae6a882a7.
2021-09-23 15:34:10 +08:00
Kevin Wan 3ae6a882a7 chore: run unit test with go 1.14 (#1084) 2021-09-23 15:30:40 +08:00
Amor 41c980f00c update goctl api (#1052)
* update goctl api

* add LoadTemplate

* update new api template

* update
2021-09-23 14:31:11 +08:00
shenbaise9527 f34d81ca2c chore: when run goctl-rpc, the order of proto message aliases should be (#1078)
fixed

Co-authored-by: steven <steven.zhou@1quant.com>
2021-09-23 14:24:21 +08:00
NevS 004ee488a6 fix AtomicError panic when Set nil (#1049) (#1050) 2021-09-23 14:23:02 +08:00
Kevin Wan 2e12cd2c99 coding style (#1083) 2021-09-23 11:19:57 +08:00
neosu 2695c30886 we can use otel.ErrorHandlerFunc instead of custom struct when we update OpenTelemetry to 1.0.0 (#1081) 2021-09-23 10:42:45 +08:00
Kevin Wan c74fb988e0 update go.mod (#1079) 2021-09-22 21:54:54 +08:00
anqiansong e8a340c1c0 Create a symbol link file named protoc-gen-goctl from goctl (#1076) 2021-09-21 23:13:31 +08:00
Kevin Wan 06e114e5a3 update OpenTelemetry to 1.0.0 (#1075) 2021-09-21 23:11:36 +08:00
Kevin Wan 74ad681a66 update issue templates (#1074) 2021-09-21 14:13:28 +08:00
Kevin Wan e7bbc09093 Update issue templates 2021-09-21 13:58:21 +08:00
Kevin Wan 1eb1450c43 downgrade golang-jwt to support go 1.14 (#1073) 2021-09-21 13:42:45 +08:00
anqiansong 9a724fe907 Add MustTempDir (#1069) 2021-09-21 10:13:43 +08:00
Kevin Wan 30e49f2939 fix jwt security issue by using golang-jwt package (#1066) 2021-09-19 22:33:35 +08:00
Kevin Wan a5407479a6 upgrade grpc version & replace github.com/golang/protobuf/protoc-gen-go with google.golang.org/protobuf (#1065) 2021-09-19 21:37:55 +08:00
anqiansong 7fb5bab26b fix #1058 (#1064) 2021-09-19 08:53:41 +08:00
Kevin Wan 27249e021f add repo moving notice (#1062) 2021-09-18 22:24:45 +08:00
Kevin Wan d809795fec add go-zero users (#1061) 2021-09-18 22:01:15 +08:00
Kevin Wan c9db9588b7 chore: fix comment issues (#1056) 2021-09-17 17:11:03 +08:00
Kevin Wan 872c50b71a chore: make comment accurate (#1055) 2021-09-17 11:11:42 +08:00
Kevin Wan 7c83155e4f mention cncf landscape (#1054) 2021-09-17 10:44:42 +08:00
Kevin Wan 358d86b8ae add go-zero users (#1051) 2021-09-16 15:06:42 +08:00
Kevin Wan f4bb9f5635 fix test error on ubuntu (#1048) 2021-09-15 13:31:20 +08:00
Jerry Liang 5c6a3132eb fix typo parse.go error message (#1041) 2021-09-14 10:26:44 +08:00
Kevin Wan 2bd95aa007 update goctl version to 1.2.1 (#1042) 2021-09-14 08:32:56 +08:00
Kevin Wan e8376936d5 remove goctl config command (#1035) 2021-09-13 14:04:06 +08:00
Kevin Wan 71c0288023 fix symlink issue on windows for goctl (#1034)
* fix symlink issue on windows for goctl

* move readlink into separate file
2021-09-13 11:49:07 +08:00
Kevin Wan 9e2f07a842 update k8s.io/client-go etc to use go 1.15 (#1031) 2021-09-13 10:45:34 +08:00
Kevin Wan 24fd34413f fix golint issues (#1027) 2021-09-12 16:15:42 +08:00
Kevin Wan 3f47251892 fix proc.Done not found in windows (#1026) 2021-09-12 15:41:33 +08:00
Kevin Wan 0b6bc69afa reorg imports, format code (#1024) 2021-09-11 21:28:47 +08:00
anqiansong 5b9bdc8d02 Merge pull request #1023 from anqiansong/1014-rollback
revert changes
2021-09-11 20:58:42 +08:00
anqiansong ded22e296e revert changes 2021-09-11 20:57:58 +08:00
anqiansong f0ed2370a3 fix #1014 (#1018)
* fix #1014

* remove unused code

* * optimize generate pb.go on Windows
* format code
* optimize console.go

* version rollback

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-09-11 12:48:32 +08:00
Kevin Wan 6bf6cfdd01 add go-zero users (#1022) 2021-09-10 22:03:24 +08:00
Kevin Wan 5cc9eb0de4 rename sharedcalls to singleflight (#1017) 2021-09-09 18:06:27 +08:00
Kevin Wan f070d447ef refactor for better error reporting on sql error (#1016)
* refactor for better error reporting on sql error

* fix errors

* add docs
2021-09-09 15:43:33 +08:00
Kevin Wan f6d9e19ecb expose sql.DB to let orm operate on it (#1015)
* expose sql.DB to let orm operate on it

* add missing RawDB methods

* add NewSqlConnFromDB for cooperate with dtm
2021-09-09 11:40:28 +08:00
Kevin Wan 56807aabf6 fix golint issues, update codecov settings. (#1011)
* update codecov settings

* fix golint issues
2021-09-07 22:33:02 +08:00
Kevin Wan 861dcf2f36 update codecov settings (#1010) 2021-09-07 18:09:53 +08:00
Kevin Wan c837dc21bb refactoring tracing interceptors. (#1009)
* refactor tracing interceptors

* add stream tracing interceptor
2021-09-07 17:58:22 +08:00
Kevin Wan 96a35ecf1a fix #1006 (#1008)
* use sdktrace instead of trace for opentelemetry to avoid conflicts

* disable opentelemetry for right now

* use os.ModeSymlink instead of fs.ModeSymlink for backward compatibility
2021-09-07 15:38:40 +08:00
Kevin Wan bdec5f2349 use sdktrace instead of trace for opentelemetry to avoid conflicts (#1005)
* use sdktrace instead of trace for opentelemetry to avoid conflicts

* disable opentelemetry for right now
2021-09-07 12:02:41 +08:00
shenbaise9527 bc92b57bdb api文件中使用group时生成的handler和logic的包名应该为group的名字 (#545)
* api文件中使用group时生成的handler和logic的包名应该为group的名字

* Update genhandlers.go

fix errors.

Co-authored-by: Kevin Wan <wanjunfeng@gmail.com>
2021-09-07 11:03:04 +08:00
neosu d8905b9e9e add api template file (#1003) 2021-09-07 10:16:10 +08:00
neosu dec6309c55 add opentelemetry test (#1002) 2021-09-07 09:26:45 +08:00
Kevin Wan 10805577f5 reorg imports, format code (#1000) 2021-09-06 14:56:46 +08:00
SunJun a4d8286e36 开启otel后,tracelog自动获取otle的traceId和spanId (#946)
* 开启otel后,tracelog自动获取otle的traceId和spanId

* 去除opentelemetry判断

* 通过 IsRecording 判断span是否活跃
2021-09-06 14:31:54 +08:00
anqiansong 84d2b64e7c optimize unit test (#999) 2021-09-06 14:20:21 +08:00
Kevin Wan 6476da4a18 rest log with context (#998) 2021-09-05 22:58:42 +08:00
Kevin Wan 79eab0ea2f refactor to shorter config name (#997) 2021-09-05 22:43:15 +08:00
Allen Liu 3b683fd498 feat: change logger to traceLogger for getting traceId when recovering (#374) 2021-09-05 22:40:10 +08:00
toven tang d179b342b2 修复使用 postgres 数据库时,位置参数重复,导致参数与值不对应的问题。 (#960)
* 修复使用 postgres 数据库时,位置参数重复,导致参数与值不对应的问题。

* 修复使用 postgres 数据库时,位置参数重复,导致参数与值不对应的问题。

Co-authored-by: toven <toven@advan.onaliyun.com>
2021-09-05 22:27:59 +08:00
Kevin Wan 58874779e7 move opentelemetry into trace package, and refactoring (#996)
* move opentelemetry into trace package, and refactoring

* rename rewritten package names
2021-09-05 22:18:35 +08:00
anqiansong 8829c31c0d Feature goctl error wrap (#995)
* Add `Wrap` in file errorx.go

* Wrap error with `GoctlError`

* format code

* Refactor package `env` to `version`

* Refactor package `IsVersionGatherThan`

* fix typo

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2021-09-05 21:57:44 +08:00
Kevin Wan b42f3fa047 disable codecov github checks (#993) 2021-09-04 13:32:23 +08:00
Kevin Wan 9bdadf2381 fix golint issues (#992) 2021-09-04 12:16:30 +08:00
Kevin Wan 20f665ede8 implement k8s service discovery (#988)
* implement k8s service discovery

* simplify code

* use default namespace if not provided

* disable codecov bot comment

* ignore adhoc dir

* simplify building target in NewClient

* reformat code

* Fix filepath (#990)

* format code, and reorg imports (#991)

* add more unit test

Co-authored-by: anqiansong <anqiansong@gmail.com>
2021-09-04 10:27:08 +08:00
Kevin Wan 0325d8e92d format code, and reorg imports (#991) 2021-09-04 10:08:49 +08:00
anqiansong 2125977281 Fix filepath (#990) 2021-09-04 08:15:22 +08:00
Vee Zhang c26c187e11 remote handler blank line when .HasRequest is false (#986) 2021-09-03 07:25:04 +08:00
Kevin Wan 4ef1859f0b use codecov action v1 (#985) 2021-09-02 19:07:30 +08:00
Kevin Wan 407a6cbf9c format coding style (#983) 2021-09-01 19:52:56 +08:00
Vee Zhang 76fc1ef460 httpx.Error response without body (#982)
* httpx.Error support response without body

* fix doc
2021-09-01 19:33:33 +08:00
miaogaolin 423955c55f format code (#979) 2021-08-31 17:15:36 +08:00
Kevin Wan db95b3f0e3 configurable for load and stat statistics logs (#980) 2021-08-31 17:14:31 +08:00
Kevin Wan 4bee60eb7f add go-zero users (#978) 2021-08-31 16:08:33 +08:00
Kevin Wan 7618139dad refactor (#977) 2021-08-31 12:04:09 +08:00
Kevin Wan 6fd08027ff update go version to 1.14 for github workflow (#976) 2021-08-31 11:46:22 +08:00
chenquan b9e268aae8 Update Codecov action (#974) 2021-08-31 11:25:58 +08:00
Kevin Wan 4c1bb1148b fix #971 (#972) 2021-08-29 11:38:34 +08:00
Kevin Wan 50a6bbe6b9 format coding style (#970) 2021-08-28 12:11:11 +08:00
chenquan dfb3cb510a Fix context error in grpc (#962)
* Fix context error in rpc

* Add a test case

* Optimize judgment conditions

* Add customized breaker errors for the client and server

* Update method signature

* Delete customized breaker errors

* Delete the wrong test case
2021-08-28 12:07:14 +08:00
Kevin Wan 519db812b4 format coding style (#969) 2021-08-27 23:09:47 +08:00
anqiansong 3203f8e06b Fix issues (#965) 2021-08-27 15:05:54 +08:00
chenquan b71ac2042a Add a test case for database code generation tool (#961) 2021-08-27 06:50:09 +08:00
Kevin Wan d0f9e57022 fix #957 (#959) 2021-08-26 16:47:28 +08:00
SunJun aa68210cde 修复stream拦截器tracer名问题 (#944) 2021-08-24 15:17:53 +08:00
zhoushuguang 280e837c9e rest otel support (#943) 2021-08-24 10:04:12 +08:00
Kevin Wan f669e1226c fix #556 (#938) 2021-08-22 23:36:35 +08:00
Kevin Wan cd15c19250 fix lint errors (#937) 2021-08-22 10:24:32 +08:00
neosu 5b35fa17de add the opentelemetry tracing (#908)
* add the opentelemetry tracing

* fix the error sampler config

* 添加stream的链路跟踪

* fix the error field name
2021-08-22 10:03:56 +08:00
Kevin Wan 9672298fa8 make sure setting code happen before callback in rest (#936) 2021-08-22 09:27:20 +08:00
Kevin Wan bf3ce16823 fix #820 (#934) 2021-08-19 22:48:21 +08:00
anqiansong 189721da16 Fix issues (#931)
* fix #929

* fix #925

* add test case

* update model README

* fix #929

* fix #929

* fix #929

* refactor dir

* Adding todo comments

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-08-19 22:47:45 +08:00
Kevin Wan a523ab1f93 update slack invite url (#933) 2021-08-19 22:25:41 +08:00
Kevin Wan 7ea8b636d9 add go-zero users (#928) 2021-08-19 10:39:47 +08:00
anqiansong b2fea65faa Optimize model naming (#910)
* add unit test

* fix #907

* format code

* format code

* format code

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-08-18 17:09:34 +08:00
anqiansong a1fe8bf6cd fix missing updateMethodTemplateFile (#924) 2021-08-18 12:23:43 +08:00
Kevin Wan 67ee9e4391 add unit test (#921) 2021-08-17 17:09:26 +08:00
Kevin Wan 9c1ee50497 refactor (#920) 2021-08-17 10:24:12 +08:00
chenquan 7c842f22d0 Add traceId to the response headers (#919)
* Add traceId to the request headers

* Add test cases

* Update refactor code
2021-08-17 10:12:08 +08:00
anqiansong 14ec29991c fix #915 (#917) 2021-08-16 15:07:11 +08:00
Kevin Wan c7f5aad83a add stringx.FirstN with ellipsis (#916) 2021-08-16 12:08:33 +08:00
lucaq e77747cff8 redis.go,type StringCmd = red.StringCmd (#790)
* Add Sinter,Sinterstore; Modify TestRedis_Set

* type StringCmd

* redis.go,type StringCmd = red.StringCmd

Co-authored-by: lucq <lucq@toopsoon.com>
2021-08-16 09:52:16 +08:00
Kevin Wan f2612db4b1 add stringx.FirstN (#914) 2021-08-15 23:02:48 +08:00
Kevin Wan a21ff71373 fix #889 (#912) 2021-08-15 15:33:45 +08:00
Kevin Wan fc04ad7854 export pathvar for user-defined routers (#911)
* refactor

* export pathvar for user-defined routers
2021-08-14 22:57:28 +08:00
Kevin Wan fbf2eebc42 add Errorv/Infov/Slowv (#909) 2021-08-13 18:28:39 +08:00
anqiansong dc43430812 optimize grpc generation env check (#900)
* optimize grpc generation env check

* optimize grpc generation env check

* format code

* fix postgresql data type convert error

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-08-13 11:47:42 +08:00
Kevin Wan c6642bc2e6 add workflow for closing inactive issues (#906)
* add workflow for closing inactive issues

* add workflow for closing inactive issues, add newline
2021-08-12 15:28:29 +08:00
Phibe bdca24dd3b Update readme for better description. (#904) 2021-08-12 14:59:17 +08:00
Kevin Wan 00c5734021 format coding style (#905) 2021-08-12 14:58:37 +08:00
lovelly 33f87cf1f0 带下划线的项目,配置文件名字错误。 (#733) 2021-08-12 14:55:39 +08:00
Kevin Wan 69935c1ba3 refactor goctl, fix golint issues (#903) 2021-08-11 18:08:01 +08:00
Kevin Wan 1fb356f328 refactor goctl (#902) 2021-08-11 18:04:42 +08:00
市民233 0b0406f41a fix: 解决golint 部分警告 (#897)
* feat:  解决goreportcard的警报
ps: warning: if block ends with a return statement, so drop this else and outdent its block (golint)

* feat: 优化golint警告,将processFieldPrimitiveWithJsonNumber 改成 processFieldPrimitiveWithJSONNumber
unmarshaler.go:248:23: method processFieldPrimitiveWithJsonNumber should be processFieldPrimitiveWithJSONNumber

* feat: 添加 WithCanonicalKeyFunc 注释

* feat: 添加DisableStat的注释

* feat: 添加 RegisterGoctlHome 注释

* feat: 添加 PostgreSqlJoin 注释

* feat: 解决goline警告should not use basic type string as key in context.WithValue问题

* feat: 解决golint警告信息: should not use basic type string as key in context.WithValue

* fix: 定义自定义字段类型,导致go test fail 问题

* update: 恢复原有测试用例

* fix golint warning
2021-08-11 17:57:20 +08:00
_ksco cc264dcf55 refactor (#878)
* refactor(tools ): refactor cod

Improve code readability and performance

* fix(tools ): fix len bug

Co-authored-by: ksco <hyang@33.cn>
2021-08-11 17:33:18 +08:00
Kevin Wan e024aebb66 fix golint issues (#899) 2021-08-11 11:38:55 +08:00
Phibe f204729482 remove unnecessary chars. (#898) 2021-08-11 10:51:28 +08:00
Phibe d20cf56a69 simplify type definition in readme (#896)
* better text rendering

* simplify type definition in readme
2021-08-10 18:02:11 +08:00
Kevin Wan 54d57c7d4b refactor rest code (#895) 2021-08-10 17:59:33 +08:00
voidint 28a7c9d38f fix http header binding failure bug #885 (#887) 2021-08-10 17:38:03 +08:00
Kevin Wan 872e75e10d add logx.DisableStat() to disable stat logs (#893)
* add logx.DisableStat() to disable stat logs

* refactor logx code
2021-08-10 16:55:38 +08:00
Phibe af1730079e better text rendering (#892) 2021-08-10 15:13:09 +08:00
Kevin Wan 04521e2d24 format code (#888) 2021-08-09 23:03:08 +08:00
Kevin Wan 02adcccbf4 format code (#884) 2021-08-09 18:11:08 +08:00
anqiansong a74aaf1823 optimize mongo generation without cache (fix #881) (#882)
* fix #881

* fix #881

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-08-09 11:33:01 +08:00
Kevin Wan 1eb2089c69 add go-zero users (#883) 2021-08-09 08:37:43 +08:00
Kevin Wan f7f3730e1a update goctl version to 1.1.10 (#874) 2021-08-04 19:29:40 +08:00
Kevin Wan 0ee7654407 fix #792 (#873) 2021-08-04 18:45:05 +08:00
neosu 16cc990fdd fix context missing (#872)
Co-authored-by: suzhenpeng <suzhenpeng@ecoplants.tech>
2021-08-04 17:46:51 +08:00
neosu 00061c2e5b add goctl rpc template home flag (#871)
Co-authored-by: suzhenpeng <suzhenpeng@ecoplants.tech>
2021-08-04 15:54:43 +08:00
Kevin Wan 6793f7a1de fix bug that proc.SetTimeToForceQuit not working in windows (#869) 2021-08-04 11:31:33 +08:00
anqiansong c8428a7f65 fix issue #861 (#862)
* fix issue #861

* fix issue #861

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-08-01 23:00:57 +08:00
toutou_o a5e1d0d0dc add correct example for pg's url (#857) 2021-07-30 13:58:44 +08:00
anqiansong 8270c7deed optimize typo (#855) 2021-07-29 21:53:16 +08:00
anqiansong 9f4a882a1b fix issue #831 (#850)
* fix issue #831

* fix typo

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-07-28 16:32:15 +08:00
anqiansong cb7b7cb72e fix issue #836 (#849)
Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-07-27 22:13:17 +08:00
Kevin Wan 603c93aa4a upgrade grpc package (#845) 2021-07-24 22:29:02 +08:00
masonchen2014 cb8d9d413a simplify timeoutinterceptor (#840)
Co-authored-by: chenmusheng <chenmusheng@laoyuegou.com>
2021-07-24 21:51:46 +08:00
Kevin Wan ff7443c6a7 fix #796 (#844) 2021-07-24 12:58:14 +08:00
fangjianwei b812e74d6f Fixed http listener error. (#843) 2021-07-24 12:57:56 +08:00
anqiansong 089cdaa75f Feature model postgresql (#842)
* Support postgresql generate

* Update template Var

* Support to generate postgresql model

* Support to generate postgresql model

* Update template

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-07-23 11:45:15 +08:00
fangjianwei 476026e393 Added database prefix of cache key. (#835) 2021-07-22 11:29:09 +08:00
Kevin Wan 75952308f9 remove faq for old versions (#828) 2021-07-19 22:54:21 +08:00
Kevin Wan df0550d6dc add go-zero users, update faq (#827) 2021-07-19 17:13:33 +08:00
neosu e481b63b21 Fix the error stream method name (#826) 2021-07-18 22:05:28 +08:00
Kevin Wan e47079f0f4 go format with extra rules (#821) 2021-07-17 20:51:23 +08:00
anqiansong 9b2a279948 Fix issues: #725, #740 (#813)
* Fix issues: #725, #740

* Update filed sort

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-07-16 22:55:39 +08:00
anqiansong db87fd3239 To generate grpc stream, fix issue #616 (#815)
Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-07-16 22:54:07 +08:00
aaffo 598fda0c97 optimized (#819) 2021-07-15 23:50:44 +08:00
Chen Quan b0e335e7b0 Fix rpc generator bug (#799)
* Fix rpc自动生成generate bug

* Delete mock
2021-07-10 13:12:52 +08:00
anqiansong efdf475da4 Add --go_opt flag to adapt to the version after 1.4.0 of protoc-gen-go (#767)
Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-07-08 10:11:11 +08:00
Chen Quan 22a1315136 [WIP]Add parse headers info (#805)
* Add parse headers info

* Update parse headers info
2021-07-07 23:20:09 +08:00
Kevin Wan 5b22823018 fix bug that empty query in transaction (#801) 2021-06-29 23:18:32 +08:00
Kevin Wan 9ccb997ed8 refactor mapping (#782) 2021-06-23 14:57:37 +08:00
skykiss 01c92a6bc5 fix: Fix problems with non support for multidimensional arrays and basic type pointer arrays (#778)
Co-authored-by: shaoqian <shaoqian.zhang@appshahe.com>
2021-06-23 10:58:01 +08:00
lucaq c9a2a60e28 Add Sinter,Sinterstore & Modify TestRedis_Set (#779)
* Add Sinter,Sinterstore; Modify TestRedis_Set

* Update redis_test.go

fix test failure

Co-authored-by: lucq <lucq@toopsoon.com>
Co-authored-by: Kevin Wan <wanjunfeng@gmail.com>
2021-06-23 10:46:16 +08:00
Kevin Wan b0739d63c0 update readme images (#776) 2021-06-21 16:45:44 +08:00
Kevin Wan c22f84cb5f update image rendering in readme (#775) 2021-06-21 16:34:14 +08:00
Kevin Wan 60450bab02 disable load & stat logs for goctl (#773) 2021-06-21 14:25:33 +08:00
Kevin Wan 3e8cec5c78 upgrade grpc & etcd dependencies (#771) 2021-06-21 09:05:20 +08:00
Kevin Wan 74ee163761 fix bug that etcd stream cancelled without re-watch (#770) 2021-06-17 18:46:16 +08:00
anqiansong ea4f680052 Fix issue #747 (#765)
Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-06-15 18:54:41 +08:00
heyanfu 58cdba2c5d remove useless annotation (#761) 2021-06-14 16:00:47 +08:00
Kevin Wan a2fbc14c70 add roadmap (#764) 2021-06-13 11:59:30 +08:00
Kevin Wan 158df8c270 fix broken link (#763) 2021-06-13 11:35:19 +08:00
Kevin Wan 30ec236a87 add contributing guid (#762) 2021-06-13 11:33:29 +08:00
Kevin Wan ac3653b3f9 add code of conduct (#760) 2021-06-12 22:17:00 +08:00
Kevin Wan 8520db4fd9 refactor fx (#759)
* refactor fx

* refactor fx, format code
2021-06-10 19:57:36 +08:00
Chen Quan 14141fed62 Add some stream features (#712)
* Add some stream features

* Update empty

* Fix initialization loop

* Delete ForeachOrdered && Fix FindFirst

* Add test case && Delete redundant code

* Update test case

* Delete SplitSteam

* Delete redundant code
2021-06-10 18:20:40 +08:00
Kevin Wan 5d86cc2f20 add go-zero users (#756) 2021-06-07 14:08:54 +08:00
Kevin Wan 8a6e4b7580 add go-zero users (#751) 2021-06-03 15:07:21 +08:00
anqiansong 453f949638 replace cache key with colon (#746)
Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
2021-06-02 10:37:49 +08:00
Kevin Wan 75a330184d add go-zero users (#739) 2021-05-29 23:58:43 +08:00
kingxt 546fcd8bab fix #736 (#738)
* optimize performance

* rename

* rename

* revert
2021-05-29 23:01:02 +08:00
Xavier Cheng 3022f93b6d Fix a typo (#729)
alread -> already
2021-05-28 23:39:07 +08:00
Kevin Wan 8ffc392c66 add go-zero users, update slack invite link (#728) 2021-05-28 14:32:47 +08:00
Kevin Wan ae7d85dadf add go-zero users (#726) 2021-05-28 10:50:33 +08:00
Kevin Wan e89268ac37 add go-zero users. (#723)
* add go-zero users

* add go-zero users
2021-05-27 22:53:55 +08:00
Kevin Wan aaa3623404 optimize nested conditional (#709) 2021-05-22 23:18:38 +08:00
heyanfu 8998f16054 optimize nested conditional (#708)
Co-authored-by: heyanfu <heyanfu@kingsoft.com>
2021-05-22 22:56:06 +08:00
anqiansong 94417be018 Add document & comment for spec (#703)
* Add document & comment for spec

* remove duplicate field

* use alias
2021-05-21 10:40:59 +08:00
Kevin Wan f300408fc0 fix golint issues, and optimize code (#705) 2021-05-21 10:38:38 +08:00
Kevin Wan aaa39e17a3 print entire sql statements in logx if necessary (#704) 2021-05-20 16:14:44 +08:00
Bo-Yi Wu 73906f996d chore(format): change by gofumpt tool (#697)
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2021-05-18 14:43:09 +08:00
Kevin Wan 73417f54db update goctl version to 1.1.8 (#696) 2021-05-17 15:13:48 +08:00
Kevin Wan 491213afb8 fix #683 (#690)
* fix #683

* fix errors
2021-05-15 15:37:24 +08:00
Julian-Chu edf743cd72 fix invalid link (#689) 2021-05-15 15:37:10 +08:00
Kevin Wan 78a88be787 add go-zero users (#688) 2021-05-14 22:52:19 +08:00
anqiansong 9f6a574f97 resolve #610 (#684) 2021-05-13 18:42:05 +08:00
anqiansong ea01cc78f0 Optimize model nl (#686) 2021-05-12 12:28:23 +08:00
Kevin Wan a87978568a fix #676 (#682) 2021-05-10 23:10:57 +08:00
Kevin Wan 14cecb9b31 update readme for documents links (#681) 2021-05-10 22:22:32 +08:00
_ksco 0ce54100a4 fix zh_cn document url (#678) 2021-05-10 22:18:33 +08:00
anqiansong d28ac35ff7 fix issue: https://github.com/zeromicro/goctl-swagger/issues/6 (#680) 2021-05-10 19:57:12 +08:00
heyanfu a5962f677f fix some typo (#677) 2021-05-10 00:09:00 +08:00
651 changed files with 26486 additions and 11813 deletions
+2 -3
View File
@@ -1,4 +1,3 @@
comment: false
ignore:
- "doc"
- "example"
- "tools"
- "tools"
+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://gitee.com/kevwan/static/raw/master/images/sponsor.jpg
+40
View File
@@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior, if applicable:
1. The code is
```go
```
2. The error is
```
```
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environments (please complete the following information):**
- OS: [e.g. Linux]
- go-zero version [e.g. 1.2.1]
- goctl version [e.g. 1.2.1, optional]
**More description**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+10
View File
@@ -0,0 +1,10 @@
---
name: Question
about: Ask a question on using go-zero or goctl
title: ''
labels: ''
assignees: ''
---
+40 -18
View File
@@ -7,28 +7,50 @@ on:
branches: [ master ]
jobs:
build:
name: Build
test-linux:
name: Linux
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
id: go
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.13
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Get dependencies
run: |
go get -v -t -d ./...
- name: Get dependencies
run: |
go get -v -t -d ./...
- name: Lint
run: |
go vet -stdmethods=false $(go list ./...)
go install mvdan.cc/gofumpt@latest
test -z "$(gofumpt -s -l -extra .)" || echo "Please run 'gofumpt -l -w -extra .'"
- name: Test
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
- name: Test
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
- name: Codecov
uses: codecov/codecov-action@v1.0.6
with:
token: ${{secrets.CODECOV_TOKEN}}
- name: Codecov
uses: codecov/codecov-action@v2
test-win:
name: Windows
runs-on: windows-latest
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
- name: Checkout codebase
uses: actions/checkout@v2
- name: Test
run: |
go mod verify
go mod download
go test -v -race ./...
cd tools/goctl && go build -v goctl.go
+18
View File
@@ -0,0 +1,18 @@
name: 'issue-translator'
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: tomsun28/issues-translate-action@v2.6
with:
IS_MODIFY_TITLE: true
# not require, default false, . Decide whether to modify the issue title
# if true, the robot account @Issues-translate-bot must have modification permissions, invite @Issues-translate-bot to your project or use your custom bot.
CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿
# not require. Customize the translation robot prefix message.
+19
View File
@@ -0,0 +1,19 @@
name: Close inactive issues
on:
schedule:
- cron: "30 1 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
days-before-issue-stale: 30
days-before-issue-close: 14
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}
+19
View File
@@ -0,0 +1,19 @@
name: reviewdog
on: [pull_request]
jobs:
staticcheck:
name: runner / staticcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: reviewdog/action-staticcheck@v1
with:
github_token: ${{ secrets.github_token }}
# Change reviewdog reporter if you need [github-pr-check,github-check,github-pr-review].
reporter: github-pr-review
# Report all results.
filter_mode: nofilter
# Exit with 1 when it find at least one finding.
fail_on_error: true
# Set staticcheck flags
staticcheck_flags: -checks=inherit,-SA1019,-SA1029,-SA5008
+5
View File
@@ -10,10 +10,15 @@
!*/
!api
# ignore
.idea
**/.DS_Store
**/logs
# for test purpose
**/adhoc
**/testdata
# gitlab ci
.cache
+102
View File
@@ -0,0 +1,102 @@
# Contributing
Welcome to go-zero!
- [Before you get started](#before-you-get-started)
- [Code of Conduct](#code-of-conduct)
- [Community Expectations](#community-expectations)
- [Getting started](#getting-started)
- [Your First Contribution](#your-first-contribution)
- [Find something to work on](#find-something-to-work-on)
- [Find a good first topic](#find-a-good-first-topic)
- [Work on an Issue](#work-on-an-issue)
- [File an Issue](#file-an-issue)
- [Contributor Workflow](#contributor-workflow)
- [Creating Pull Requests](#creating-pull-requests)
- [Code Review](#code-review)
- [Testing](#testing)
# Before you get started
## Code of Conduct
Please make sure to read and observe our [Code of Conduct](/code-of-conduct.md).
## Community Expectations
go-zero is a community project driven by its community which strives to promote a healthy, friendly and productive environment.
go-zero is a web and rpc framework written in Go. It's born to ensure the stability of the busy sites with resilient design. Builtin goctl greatly improves the development productivity.
# Getting started
- Fork the repository on GitHub.
- Make your changes on your fork repository.
- Submit a PR.
# Your First Contribution
We will help you to contribute in different areas like filing issues, developing features, fixing critical bugs and
getting your work reviewed and merged.
If you have questions about the development process,
feel free to [file an issue](https://github.com/zeromicro/go-zero/issues/new/choose).
## Find something to work on
We are always in need of help, be it fixing documentation, reporting bugs or writing some code.
Look at places where you feel best coding practices aren't followed, code refactoring is needed or tests are missing.
Here is how you get started.
### Find a good first topic
[go-zero](https://github.com/zeromicro/go-zero) has beginner-friendly issues that provide a good first issue.
For example, [go-zero](https://github.com/zeromicro/go-zero) has
[help wanted](https://github.com/zeromicro/go-zero/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) and
[good first issue](https://github.com/zeromicro/go-zero/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
labels for issues that should not need deep knowledge of the system.
We can help new contributors who wish to work on such issues.
Another good way to contribute is to find a documentation improvement, such as a missing/broken link.
Please see [Contributing](#contributing) below for the workflow.
#### Work on an issue
When you are willing to take on an issue, just reply on the issue. The maintainer will assign it to you.
### File an Issue
While we encourage everyone to contribute code, it is also appreciated when someone reports an issue.
Please follow the prompted submission guidelines while opening an issue.
# Contributor Workflow
Please do not ever hesitate to ask a question or send a pull request.
This is a rough outline of what a contributor's workflow looks like:
- Create a topic branch from where to base the contribution. This is usually master.
- Make commits of logical units.
- Push changes in a topic branch to a personal fork of the repository.
- Submit a pull request to [go-zero](https://github.com/zeromicro/go-zero).
## Creating Pull Requests
Pull requests are often called simply "PR".
go-zero generally follows the standard [github pull request](https://help.github.com/articles/about-pull-requests/) process.
To submit a proposed change, please develop the code/fix and add new test cases.
After that, run these local verifications before submitting pull request to predict the pass or
fail of continuous integration.
* Format the code with `gofmt`
* Run the test with data race enabled `go test -race ./...`
## Code Review
To make it easier for your PR to receive reviews, consider the reviewers will need you to:
* follow [good coding guidelines](https://github.com/golang/go/wiki/CodeReviewComments).
* write [good commit messages](https://chris.beams.io/posts/git-commit/).
* break large changes into a logical series of smaller patches which individually make easily understandable changes, and in aggregate solve a broader issue.
+28
View File
@@ -0,0 +1,28 @@
# go-zero Roadmap
This document defines a high level roadmap for go-zero development and upcoming releases.
Community and contributor involvement is vital for successfully implementing all desired items for each release.
We hope that the items listed below will inspire further engagement from the community to keep go-zero progressing and shipping exciting and valuable features.
## 2021 Q2
- [x] Support service discovery through K8S client api
- [x] Log full sql statements for easier sql problem solving
## 2021 Q3
- [x] Support `goctl model pg` to support PostgreSQL code generation
- [x] Adapt builtin tracing mechanism to opentracing solutions
## 2021 Q4
- [x] Support `username/password` authentication in ETCD
- [x] Support `SSL/TLS` in ETCD
- [x] Support `SSL/TLS` in `zRPC`
- [x] Support `TLS` in redis connections
- [x] Support `goctl bug` to report bugs conveniently
## 2022
- [x] Support `context` in redis related methods for timeout and tracing
- [x] Support `context` in sql related methods for timeout and tracing
- [ ] Support `context` in mongodb related methods for timeout and tracing
- [ ] Add `httpx.Client` with governance, like circuit breaker etc.
- [ ] Support `goctl doctor` command to report potential issues for given service
- [ ] Support `goctl mock` command to start a mocking server with given `.api` file
+76
View File
@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"errors"
"strconv"
"github.com/tal-tech/go-zero/core/hash"
"github.com/tal-tech/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/hash"
"github.com/zeromicro/go-zero/core/stores/redis"
)
const (
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stores/redis/redistest"
"github.com/zeromicro/go-zero/core/stores/redis/redistest"
)
func TestRedisBitSet_New_Set_Test(t *testing.T) {
+5 -5
View File
@@ -6,11 +6,11 @@ import (
"strings"
"sync"
"github.com/tal-tech/go-zero/core/mathx"
"github.com/tal-tech/go-zero/core/proc"
"github.com/tal-tech/go-zero/core/stat"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/mathx"
"github.com/zeromicro/go-zero/core/proc"
"github.com/zeromicro/go-zero/core/stat"
"github.com/zeromicro/go-zero/core/stringx"
"github.com/zeromicro/go-zero/core/timex"
)
const (
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stat"
"github.com/zeromicro/go-zero/core/stat"
)
func init() {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stat"
"github.com/zeromicro/go-zero/core/stat"
)
func init() {
+3 -3
View File
@@ -4,8 +4,8 @@ import (
"math"
"time"
"github.com/tal-tech/go-zero/core/collection"
"github.com/tal-tech/go-zero/core/mathx"
"github.com/zeromicro/go-zero/core/collection"
"github.com/zeromicro/go-zero/core/mathx"
)
const (
@@ -94,7 +94,7 @@ func (b *googleBreaker) markFailure() {
b.stat.Add(0)
}
func (b *googleBreaker) history() (accepts int64, total int64) {
func (b *googleBreaker) history() (accepts, total int64) {
b.stat.Reduce(func(b *collection.Bucket) {
accepts += int64(b.Sum)
total += b.Count
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/collection"
"github.com/tal-tech/go-zero/core/mathx"
"github.com/tal-tech/go-zero/core/stat"
"github.com/zeromicro/go-zero/core/collection"
"github.com/zeromicro/go-zero/core/mathx"
"github.com/zeromicro/go-zero/core/stat"
)
const (
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/iox"
"github.com/tal-tech/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/iox"
"github.com/zeromicro/go-zero/core/lang"
)
func TestEnterToContinue(t *testing.T) {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"encoding/base64"
"errors"
"github.com/tal-tech/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/logx"
)
// ErrPaddingSize indicates bad padding size.
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/fs"
"github.com/zeromicro/go-zero/core/fs"
)
const (
+5 -5
View File
@@ -6,9 +6,9 @@ import (
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/mathx"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mathx"
"github.com/zeromicro/go-zero/core/syncx"
)
const (
@@ -34,7 +34,7 @@ type (
expire time.Duration
timingWheel *TimingWheel
lruCache lru
barrier syncx.SharedCalls
barrier syncx.SingleFlight
unstableExpiry mathx.Unstable
stats *cacheStat
}
@@ -46,7 +46,7 @@ func NewCache(expire time.Duration, opts ...CacheOption) (*Cache, error) {
data: make(map[string]interface{}),
expire: expire,
lruCache: emptyLruCache,
barrier: syncx.NewSharedCalls(),
barrier: syncx.NewSingleFlight(),
unstableExpiry: mathx.NewUnstable(expiryDeviation),
}
+38
View File
@@ -61,3 +61,41 @@ func TestPutMore(t *testing.T) {
assert.Equal(t, string(element), string(body.([]byte)))
}
}
func TestPutMoreWithHeaderNotZero(t *testing.T) {
elements := [][]byte{
[]byte("hello"),
[]byte("world"),
[]byte("again"),
}
queue := NewQueue(4)
for i := range elements {
queue.Put(elements[i])
}
// take 1
body, ok := queue.Take()
assert.True(t, ok)
element, ok := body.([]byte)
assert.True(t, ok)
assert.Equal(t, element, []byte("hello"))
// put more
queue.Put([]byte("b4"))
queue.Put([]byte("b5")) // will store in elements[0]
queue.Put([]byte("b6")) // cause expansion
results := [][]byte{
[]byte("world"),
[]byte("again"),
[]byte("b4"),
[]byte("b5"),
[]byte("b6"),
}
for _, element := range results {
body, ok := queue.Take()
assert.True(t, ok)
assert.Equal(t, string(element), string(body.([]byte)))
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"sync"
"time"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/timex"
)
type (
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/zeromicro/go-zero/core/stringx"
)
const duration = time.Millisecond * 50
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/zeromicro/go-zero/core/stringx"
)
func TestSafeMap(t *testing.T) {
+7 -17
View File
@@ -1,8 +1,8 @@
package collection
import (
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/logx"
)
const (
@@ -106,9 +106,7 @@ func (s *Set) KeysInt() []int {
var keys []int
for key := range s.data {
if intKey, ok := key.(int); !ok {
continue
} else {
if intKey, ok := key.(int); ok {
keys = append(keys, intKey)
}
}
@@ -121,9 +119,7 @@ func (s *Set) KeysInt64() []int64 {
var keys []int64
for key := range s.data {
if intKey, ok := key.(int64); !ok {
continue
} else {
if intKey, ok := key.(int64); ok {
keys = append(keys, intKey)
}
}
@@ -136,9 +132,7 @@ func (s *Set) KeysUint() []uint {
var keys []uint
for key := range s.data {
if intKey, ok := key.(uint); !ok {
continue
} else {
if intKey, ok := key.(uint); ok {
keys = append(keys, intKey)
}
}
@@ -151,9 +145,7 @@ func (s *Set) KeysUint64() []uint64 {
var keys []uint64
for key := range s.data {
if intKey, ok := key.(uint64); !ok {
continue
} else {
if intKey, ok := key.(uint64); ok {
keys = append(keys, intKey)
}
}
@@ -166,9 +158,7 @@ func (s *Set) KeysStr() []string {
var keys []string
for key := range s.data {
if strKey, ok := key.(string); !ok {
continue
} else {
if strKey, ok := key.(string); ok {
keys = append(keys, strKey)
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/logx"
)
func init() {
+4 -4
View File
@@ -5,9 +5,9 @@ import (
"fmt"
"time"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/threading"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/threading"
"github.com/zeromicro/go-zero/core/timex"
)
const drainWorkers = 8
@@ -151,7 +151,7 @@ func (tw *TimingWheel) drainAll(fn func(key, value interface{})) {
}
}
func (tw *TimingWheel) getPositionAndCircle(d time.Duration) (pos int, circle int) {
func (tw *TimingWheel) getPositionAndCircle(d time.Duration) (pos, circle int) {
steps := int(d / tw.interval)
pos = (tw.tickedPos + steps) % tw.numSlots
circle = (steps - 1) / tw.numSlots
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/stringx"
"github.com/zeromicro/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/timex"
)
const (
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"os"
"path"
"github.com/tal-tech/go-zero/core/mapping"
"github.com/zeromicro/go-zero/core/mapping"
)
var loaders = map[string]func([]byte, interface{}) error{
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/fs"
"github.com/tal-tech/go-zero/core/hash"
"github.com/zeromicro/go-zero/core/fs"
"github.com/zeromicro/go-zero/core/hash"
)
func TestLoadConfig_notExists(t *testing.T) {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"strings"
"sync"
"github.com/tal-tech/go-zero/core/iox"
"github.com/zeromicro/go-zero/core/iox"
)
// PropertyError represents a configuration error message.
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/fs"
"github.com/zeromicro/go-zero/core/fs"
)
func TestProperties(t *testing.T) {
+1 -1
View File
@@ -3,7 +3,7 @@ package contextx
import (
"context"
"github.com/tal-tech/go-zero/core/mapping"
"github.com/zeromicro/go-zero/core/mapping"
)
const contextTagKey = "ctx"
+3 -1
View File
@@ -47,9 +47,11 @@ func TestUnmarshalContextWithMissing(t *testing.T) {
Name string `ctx:"name"`
Age int `ctx:"age"`
}
type name string
const PersonNameKey name = "name"
ctx := context.Background()
ctx = context.WithValue(ctx, "name", "kevin")
ctx = context.WithValue(ctx, PersonNameKey, "kevin")
var person Person
err := For(ctx, &person)
+3 -1
View File
@@ -9,7 +9,9 @@ import (
)
func TestContextCancel(t *testing.T) {
c := context.WithValue(context.Background(), "key", "value")
type key string
var nameKey key = "name"
c := context.WithValue(context.Background(), nameKey, "value")
c1, cancel := context.WithCancel(c)
o := ValueOnlyFrom(c1)
c2, cancel2 := context.WithCancel(o)
+14
View File
@@ -0,0 +1,14 @@
package discov
import "github.com/zeromicro/go-zero/core/discov/internal"
// RegisterAccount registers the username/password to the given etcd cluster.
func RegisterAccount(endpoints []string, user, pass string) {
internal.AddAccount(endpoints, user, pass)
}
// RegisterTLS registers the CertFile/CertKeyFile/CACertFile to the given etcd.
func RegisterTLS(endpoints []string, certFile, certKeyFile, caFile string,
insecureSkipVerify bool) error {
return internal.AddTLS(endpoints, certFile, certKeyFile, caFile, insecureSkipVerify)
}
+21
View File
@@ -0,0 +1,21 @@
package discov
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/stringx"
)
func TestRegisterAccount(t *testing.T) {
endpoints := []string{
"localhost:2379",
}
user := "foo" + stringx.Rand()
RegisterAccount(endpoints, user, "bar")
account, ok := internal.GetAccount(endpoints)
assert.True(t, ok)
assert.Equal(t, user, account.User)
assert.Equal(t, "bar", account.Pass)
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"github.com/tal-tech/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/discov/internal"
)
const (
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/discov/internal"
)
var mockLock sync.Mutex
+27 -4
View File
@@ -2,18 +2,41 @@ package discov
import "errors"
var (
// errEmptyEtcdHosts indicates that etcd hosts are empty.
errEmptyEtcdHosts = errors.New("empty etcd hosts")
// errEmptyEtcdKey indicates that etcd key is empty.
errEmptyEtcdKey = errors.New("empty etcd key")
)
// EtcdConf is the config item with the given key on etcd.
type EtcdConf struct {
Hosts []string
Key string
Hosts []string
Key string
User string `json:",optional"`
Pass string `json:",optional"`
CertFile string `json:",optional"`
CertKeyFile string `json:",optional=CertFile"`
CACertFile string `json:",optional=CertFile"`
InsecureSkipVerify bool `json:",optional"`
}
// HasAccount returns if account provided.
func (c EtcdConf) HasAccount() bool {
return len(c.User) > 0 && len(c.Pass) > 0
}
// HasTLS returns if TLS CertFile/CertKeyFile/CACertFile are provided.
func (c EtcdConf) HasTLS() bool {
return len(c.CertFile) > 0 && len(c.CertKeyFile) > 0 && len(c.CACertFile) > 0
}
// Validate validates c.
func (c EtcdConf) Validate() error {
if len(c.Hosts) == 0 {
return errors.New("empty etcd hosts")
return errEmptyEtcdHosts
} else if len(c.Key) == 0 {
return errors.New("empty etcd key")
return errEmptyEtcdKey
} else {
return nil
}
+36
View File
@@ -44,3 +44,39 @@ func TestConfig(t *testing.T) {
}
}
}
func TestEtcdConf_HasAccount(t *testing.T) {
tests := []struct {
EtcdConf
hasAccount bool
}{
{
EtcdConf: EtcdConf{
Hosts: []string{"any"},
Key: "key",
},
hasAccount: false,
},
{
EtcdConf: EtcdConf{
Hosts: []string{"any"},
Key: "key",
User: "foo",
},
hasAccount: false,
},
{
EtcdConf: EtcdConf{
Hosts: []string{"any"},
Key: "key",
User: "foo",
Pass: "bar",
},
hasAccount: true,
},
}
for _, test := range tests {
assert.Equal(t, test.hasAccount, test.EtcdConf.HasAccount())
}
}
+75
View File
@@ -0,0 +1,75 @@
package internal
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"sync"
)
var (
accounts = make(map[string]Account)
tlsConfigs = make(map[string]*tls.Config)
lock sync.RWMutex
)
// Account holds the username/password for an etcd cluster.
type Account struct {
User string
Pass string
}
// AddAccount adds the username/password for the given etcd cluster.
func AddAccount(endpoints []string, user, pass string) {
lock.Lock()
defer lock.Unlock()
accounts[getClusterKey(endpoints)] = Account{
User: user,
Pass: pass,
}
}
// AddTLS adds the tls cert files for the given etcd cluster.
func AddTLS(endpoints []string, certFile, certKeyFile, caFile string, insecureSkipVerify bool) error {
cert, err := tls.LoadX509KeyPair(certFile, certKeyFile)
if err != nil {
return err
}
caData, err := ioutil.ReadFile(caFile)
if err != nil {
return err
}
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(caData)
lock.Lock()
defer lock.Unlock()
tlsConfigs[getClusterKey(endpoints)] = &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: pool,
InsecureSkipVerify: insecureSkipVerify,
}
return nil
}
// GetAccount gets the username/password for the given etcd cluster.
func GetAccount(endpoints []string) (Account, bool) {
lock.RLock()
defer lock.RUnlock()
account, ok := accounts[getClusterKey(endpoints)]
return account, ok
}
// GetTLS gets the tls config for the given etcd cluster.
func GetTLS(endpoints []string) (*tls.Config, bool) {
lock.RLock()
defer lock.RUnlock()
cfg, ok := tlsConfigs[getClusterKey(endpoints)]
return cfg, ok
}
@@ -0,0 +1,34 @@
package internal
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/stringx"
)
func TestAccount(t *testing.T) {
endpoints := []string{
"192.168.0.2:2379",
"192.168.0.3:2379",
"192.168.0.4:2379",
}
username := "foo" + stringx.Rand()
password := "bar"
anotherPassword := "any"
_, ok := GetAccount(endpoints)
assert.False(t, ok)
AddAccount(endpoints, username, password)
account, ok := GetAccount(endpoints)
assert.True(t, ok)
assert.Equal(t, username, account.User)
assert.Equal(t, password, account.Pass)
AddAccount(endpoints, username, anotherPassword)
account, ok = GetAccount(endpoints)
assert.True(t, ok)
assert.Equal(t, username, account.User)
assert.Equal(t, anotherPassword, account.Pass)
}
+1 -1
View File
@@ -5,7 +5,7 @@ package internal
import (
"context"
"go.etcd.io/etcd/clientv3"
clientv3 "go.etcd.io/etcd/client/v3"
"google.golang.org/grpc"
)
+4 -3
View File
@@ -6,10 +6,11 @@ package internal
import (
context "context"
gomock "github.com/golang/mock/gomock"
clientv3 "go.etcd.io/etcd/clientv3"
grpc "google.golang.org/grpc"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
clientv3 "go.etcd.io/etcd/client/v3"
grpc "google.golang.org/grpc"
)
// MockEtcdClient is a mock of EtcdClient interface
+1 -1
View File
@@ -2,5 +2,5 @@ package internal
// Listener interface wraps the OnUpdate method.
type Listener interface {
OnUpdate(keys []string, values []string, newKey string)
OnUpdate(keys, values []string, newKey string)
}
+61 -21
View File
@@ -9,12 +9,12 @@ import (
"sync"
"time"
"github.com/tal-tech/go-zero/core/contextx"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/tal-tech/go-zero/core/threading"
"go.etcd.io/etcd/clientv3"
"github.com/zeromicro/go-zero/core/contextx"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/threading"
clientv3 "go.etcd.io/etcd/client/v3"
)
var (
@@ -37,25 +37,35 @@ func GetRegistry() *Registry {
// GetConn returns an etcd client connection associated with given endpoints.
func (r *Registry) GetConn(endpoints []string) (EtcdClient, error) {
return r.getCluster(endpoints).getClient()
c, _ := r.getCluster(endpoints)
return c.getClient()
}
// Monitor monitors the key on given etcd endpoints, notify with the given UpdateListener.
func (r *Registry) Monitor(endpoints []string, key string, l UpdateListener) error {
return r.getCluster(endpoints).monitor(key, l)
c, exists := r.getCluster(endpoints)
// if exists, the existing values should be updated to the listener.
if exists {
kvs := c.getCurrent(key)
for _, kv := range kvs {
l.OnAdd(kv)
}
}
return c.monitor(key, l)
}
func (r *Registry) getCluster(endpoints []string) *cluster {
func (r *Registry) getCluster(endpoints []string) (c *cluster, exists bool) {
clusterKey := getClusterKey(endpoints)
r.lock.Lock()
defer r.lock.Unlock()
c, ok := r.clusters[clusterKey]
if !ok {
c, exists = r.clusters[clusterKey]
if !exists {
c = newCluster(endpoints)
r.clusters[clusterKey] = c
}
return c
return
}
type cluster struct {
@@ -94,6 +104,21 @@ func (c *cluster) getClient() (EtcdClient, error) {
return val.(EtcdClient), nil
}
func (c *cluster) getCurrent(key string) []KV {
c.lock.Lock()
defer c.lock.Unlock()
var kvs []KV
for k, v := range c.values[key] {
kvs = append(kvs, KV{
Key: k,
Val: v,
})
}
return kvs
}
func (c *cluster) handleChanges(key string, kvs []KV) {
var add []KV
var remove []KV
@@ -197,14 +222,12 @@ func (c *cluster) load(cli EtcdClient, key string) {
}
var kvs []KV
c.lock.Lock()
for _, ev := range resp.Kvs {
kvs = append(kvs, KV{
Key: string(ev.Key),
Val: string(ev.Value),
})
}
c.lock.Unlock()
c.handleChanges(key, kvs)
}
@@ -260,26 +283,34 @@ func (c *cluster) reload(cli EtcdClient) {
}
func (c *cluster) watch(cli EtcdClient, key string) {
for {
if c.watchStream(cli, key) {
return
}
}
}
func (c *cluster) watchStream(cli EtcdClient, key string) bool {
rch := cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key), clientv3.WithPrefix())
for {
select {
case wresp, ok := <-rch:
if !ok {
logx.Error("etcd monitor chan has been closed")
return
return false
}
if wresp.Canceled {
logx.Error("etcd monitor chan has been canceled")
return
logx.Errorf("etcd monitor chan has been canceled, error: %v", wresp.Err())
return false
}
if wresp.Err() != nil {
logx.Error(fmt.Sprintf("etcd monitor chan error: %v", wresp.Err()))
return
return false
}
c.handleWatchEvents(key, wresp.Events)
case <-c.done:
return
return true
}
}
}
@@ -294,14 +325,23 @@ func (c *cluster) watchConnState(cli EtcdClient) {
// DialClient dials an etcd cluster with given endpoints.
func DialClient(endpoints []string) (EtcdClient, error) {
return clientv3.New(clientv3.Config{
cfg := clientv3.Config{
Endpoints: endpoints,
AutoSyncInterval: autoSyncInterval,
DialTimeout: DialTimeout,
DialKeepAliveTime: dialKeepAliveTime,
DialKeepAliveTimeout: DialTimeout,
RejectOldCluster: true,
})
}
if account, ok := GetAccount(endpoints); ok {
cfg.Username = account.User
cfg.Password = account.Pass
}
if tlsCfg, ok := GetTLS(endpoints); ok {
cfg.TLS = tlsCfg
}
return clientv3.New(cfg)
}
func getClusterKey(endpoints []string) string {
+16 -10
View File
@@ -7,11 +7,12 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/contextx"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/stringx"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/mvcc/mvccpb"
"github.com/zeromicro/go-zero/core/contextx"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stringx"
"go.etcd.io/etcd/api/v3/mvccpb"
clientv3 "go.etcd.io/etcd/client/v3"
)
var mockLock sync.Mutex
@@ -32,9 +33,10 @@ func setMockClient(cli EtcdClient) func() {
}
func TestGetCluster(t *testing.T) {
c1 := GetRegistry().getCluster([]string{"first"})
c2 := GetRegistry().getCluster([]string{"second"})
c3 := GetRegistry().getCluster([]string{"first"})
AddAccount([]string{"first"}, "foo", "bar")
c1, _ := GetRegistry().getCluster([]string{"first"})
c2, _ := GetRegistry().getCluster([]string{"second"})
c3, _ := GetRegistry().getCluster([]string{"first"})
assert.Equal(t, c1, c3)
assert.NotEqual(t, c1, c2)
}
@@ -202,11 +204,13 @@ func TestClusterWatch_RespFailures(t *testing.T) {
restore := setMockClient(cli)
defer restore()
ch := make(chan clientv3.WatchResponse)
cli.EXPECT().Watch(gomock.Any(), "any/", gomock.Any()).Return(ch)
cli.EXPECT().Watch(gomock.Any(), "any/", gomock.Any()).Return(ch).AnyTimes()
cli.EXPECT().Ctx().Return(context.Background()).AnyTimes()
c := new(cluster)
c.done = make(chan lang.PlaceholderType)
go func() {
ch <- resp
close(c.done)
}()
c.watch(cli, "any")
})
@@ -220,11 +224,13 @@ func TestClusterWatch_CloseChan(t *testing.T) {
restore := setMockClient(cli)
defer restore()
ch := make(chan clientv3.WatchResponse)
cli.EXPECT().Watch(gomock.Any(), "any/", gomock.Any()).Return(ch)
cli.EXPECT().Watch(gomock.Any(), "any/", gomock.Any()).Return(ch).AnyTimes()
cli.EXPECT().Ctx().Return(context.Background()).AnyTimes()
c := new(cluster)
c.done = make(chan lang.PlaceholderType)
go func() {
close(ch)
close(c.done)
}()
c.watch(cli, "any")
}
+2 -1
View File
@@ -6,9 +6,10 @@ package internal
import (
context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
connectivity "google.golang.org/grpc/connectivity"
reflect "reflect"
)
// MocketcdConn is a mock of etcdConn interface
+2 -1
View File
@@ -5,8 +5,9 @@
package internal
import (
gomock "github.com/golang/mock/gomock"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
)
// MockUpdateListener is a mock of UpdateListener interface
+25 -11
View File
@@ -1,18 +1,18 @@
package discov
import (
"github.com/tal-tech/go-zero/core/discov/internal"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/proc"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/tal-tech/go-zero/core/threading"
"go.etcd.io/etcd/clientv3"
"github.com/zeromicro/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/proc"
"github.com/zeromicro/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/threading"
clientv3 "go.etcd.io/etcd/client/v3"
)
type (
// PublisherOption defines the method to customize a Publisher.
PublisherOption func(client *Publisher)
// PubOption defines the method to customize a Publisher.
PubOption func(client *Publisher)
// A Publisher can be used to publish the value to an etcd cluster on the given key.
Publisher struct {
@@ -32,7 +32,7 @@ type (
// endpoints is the hosts of the etcd cluster.
// key:value are a pair to be published.
// opts are used to customize the Publisher.
func NewPublisher(endpoints []string, key, value string, opts ...PublisherOption) *Publisher {
func NewPublisher(endpoints []string, key, value string, opts ...PubOption) *Publisher {
publisher := &Publisher{
endpoints: endpoints,
key: key,
@@ -146,8 +146,22 @@ func (p *Publisher) revoke(cli internal.EtcdClient) {
}
// WithId customizes a Publisher with the id.
func WithId(id int64) PublisherOption {
func WithId(id int64) PubOption {
return func(publisher *Publisher) {
publisher.id = id
}
}
// WithPubEtcdAccount provides the etcd username/password.
func WithPubEtcdAccount(user, pass string) PubOption {
return func(pub *Publisher) {
RegisterAccount(pub.endpoints, user, pass)
}
}
// WithPubEtcdTLS provides the etcd CertFile/CertKeyFile/CACertFile.
func WithPubEtcdTLS(certFile, certKeyFile, caFile string, insecureSkipVerify bool) PubOption {
return func(pub *Publisher) {
logx.Must(RegisterTLS(pub.endpoints, certFile, certKeyFile, caFile, insecureSkipVerify))
}
}
+7 -5
View File
@@ -8,10 +8,11 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/discov/internal"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/logx"
"go.etcd.io/etcd/clientv3"
"github.com/zeromicro/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stringx"
clientv3 "go.etcd.io/etcd/client/v3"
)
func init() {
@@ -30,7 +31,8 @@ func TestPublisher_register(t *testing.T) {
ID: id,
}, nil)
cli.EXPECT().Put(gomock.Any(), makeEtcdKey("thekey", id), "thevalue", gomock.Any())
pub := NewPublisher(nil, "thekey", "thevalue")
pub := NewPublisher(nil, "thekey", "thevalue",
WithPubEtcdAccount(stringx.Rand(), "bar"))
_, err := pub.register(cli)
assert.Nil(t, err)
}
+29 -16
View File
@@ -4,21 +4,20 @@ import (
"sync"
"sync/atomic"
"github.com/tal-tech/go-zero/core/discov/internal"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/syncx"
)
type (
subOptions struct {
exclusive bool
}
// SubOption defines the method to customize a Subscriber.
SubOption func(opts *subOptions)
SubOption func(sub *Subscriber)
// A Subscriber is used to subscribe the given key on a etcd cluster.
Subscriber struct {
items *container
endpoints []string
exclusive bool
items *container
}
)
@@ -27,14 +26,14 @@ type (
// key is the key to subscribe.
// opts are used to customize the Subscriber.
func NewSubscriber(endpoints []string, key string, opts ...SubOption) (*Subscriber, error) {
var subOpts subOptions
for _, opt := range opts {
opt(&subOpts)
}
sub := &Subscriber{
items: newContainer(subOpts.exclusive),
endpoints: endpoints,
}
for _, opt := range opts {
opt(sub)
}
sub.items = newContainer(sub.exclusive)
if err := internal.GetRegistry().Monitor(endpoints, key, sub.items); err != nil {
return nil, err
}
@@ -55,8 +54,22 @@ func (s *Subscriber) Values() []string {
// Exclusive means that key value can only be 1:1,
// which means later added value will remove the keys associated with the same value previously.
func Exclusive() SubOption {
return func(opts *subOptions) {
opts.exclusive = true
return func(sub *Subscriber) {
sub.exclusive = true
}
}
// WithSubEtcdAccount provides the etcd username/password.
func WithSubEtcdAccount(user, pass string) SubOption {
return func(sub *Subscriber) {
RegisterAccount(sub.endpoints, user, pass)
}
}
// WithSubEtcdTLS provides the etcd CertFile/CertKeyFile/CACertFile.
func WithSubEtcdTLS(certFile, certKeyFile, caFile string, insecureSkipVerify bool) SubOption {
return func(sub *Subscriber) {
logx.Must(RegisterTLS(sub.endpoints, certFile, certKeyFile, caFile, insecureSkipVerify))
}
}
+16 -5
View File
@@ -5,7 +5,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/discov/internal"
"github.com/zeromicro/go-zero/core/stringx"
)
const (
@@ -201,11 +202,9 @@ func TestContainer(t *testing.T) {
}
func TestSubscriber(t *testing.T) {
var opt subOptions
Exclusive()(&opt)
sub := new(Subscriber)
sub.items = newContainer(opt.exclusive)
Exclusive()(sub)
sub.items = newContainer(sub.exclusive)
var count int32
sub.AddListener(func() {
atomic.AddInt32(&count, 1)
@@ -214,3 +213,15 @@ func TestSubscriber(t *testing.T) {
assert.Empty(t, sub.Values())
assert.Equal(t, int32(1), atomic.LoadInt32(&count))
}
func TestWithSubEtcdAccount(t *testing.T) {
endpoints := []string{"localhost:2379"}
user := stringx.Rand()
WithSubEtcdAccount(user, "bar")(&Subscriber{
endpoints: endpoints,
})
account, ok := internal.GetAccount(endpoints)
assert.True(t, ok)
assert.Equal(t, user, account.User)
assert.Equal(t, "bar", account.Pass)
}
+3 -1
View File
@@ -9,7 +9,9 @@ type AtomicError struct {
// Set sets the error.
func (ae *AtomicError) Set(err error) {
ae.err.Store(err)
if err != nil {
ae.err.Store(err)
}
}
// Load returns the error.
+9
View File
@@ -17,6 +17,15 @@ func TestAtomicError(t *testing.T) {
assert.Equal(t, errDummy, err.Load())
}
func TestAtomicErrorSetNil(t *testing.T) {
var (
errNil error
err AtomicError
)
err.Set(errNil)
assert.Equal(t, errNil, err.Load())
}
func TestAtomicErrorNil(t *testing.T) {
var err AtomicError
assert.Nil(t, err.Load())
+6 -4
View File
@@ -11,10 +11,12 @@ type (
errorArray []error
)
// Add adds err to be.
func (be *BatchError) Add(err error) {
if err != nil {
be.errs = append(be.errs, err)
// Add adds errs to be, nil errors are ignored.
func (be *BatchError) Add(errs ...error) {
for _, err := range errs {
if err != nil {
be.errs = append(be.errs, err)
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"sync"
"time"
"github.com/tal-tech/go-zero/core/threading"
"github.com/zeromicro/go-zero/core/threading"
)
// A DelayExecutor delays a tasks on given delay interval.
+2 -2
View File
@@ -3,8 +3,8 @@ package executors
import (
"time"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/timex"
)
// A LessExecutor is an executor to limit execution once within given time interval.
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/timex"
)
func TestLessExecutor_DoOrDiscard(t *testing.T) {
+5 -5
View File
@@ -6,11 +6,11 @@ import (
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/proc"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/tal-tech/go-zero/core/threading"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/proc"
"github.com/zeromicro/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/threading"
"github.com/zeromicro/go-zero/core/timex"
)
const idleRound = 10
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/timex"
)
const threshold = 10
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/fs"
"github.com/zeromicro/go-zero/core/fs"
)
const (
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/fs"
"github.com/zeromicro/go-zero/core/fs"
)
func TestSplitLineChunks(t *testing.T) {
+4 -1
View File
@@ -5,6 +5,9 @@ import (
"os"
)
// errExceedFileSize indicates that the file size is exceeded.
var errExceedFileSize = errors.New("exceed file size")
// A RangeReader is used to read a range of content from a file.
type RangeReader struct {
file *os.File
@@ -29,7 +32,7 @@ func (rr *RangeReader) Read(p []byte) (n int, err error) {
}
if rr.stop < rr.start || rr.start >= stat.Size() {
return 0, errors.New("exceed file size")
return 0, errExceedFileSize
}
if rr.stop-rr.start < int64(len(p)) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/fs"
"github.com/zeromicro/go-zero/core/fs"
)
func TestRangeReader(t *testing.T) {
+1
View File
@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package fs
+1
View File
@@ -1,3 +1,4 @@
//go:build linux || darwin
// +build linux darwin
package fs
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"io/ioutil"
"os"
"github.com/tal-tech/go-zero/core/hash"
"github.com/zeromicro/go-zero/core/hash"
)
// TempFileWithText creates the temporary file with the given content,
+1 -1
View File
@@ -1,6 +1,6 @@
package fx
import "github.com/tal-tech/go-zero/core/threading"
import "github.com/zeromicro/go-zero/core/threading"
// Parallel runs fns parallelly and waits for done.
func Parallel(fns ...func()) {
+1 -1
View File
@@ -1,6 +1,6 @@
package fx
import "github.com/tal-tech/go-zero/core/errorx"
import "github.com/zeromicro/go-zero/core/errorx"
const defaultRetryTimes = 3
+191 -63
View File
@@ -4,9 +4,9 @@ import (
"sort"
"sync"
"github.com/tal-tech/go-zero/core/collection"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/threading"
"github.com/zeromicro/go-zero/core/collection"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/threading"
)
const (
@@ -49,6 +49,11 @@ type (
}
)
// Concat returns a concatenated Stream.
func Concat(s Stream, others ...Stream) Stream {
return s.Concat(others...)
}
// From constructs a Stream from the given GenerateFunc.
func From(generate GenerateFunc) Stream {
source := make(chan interface{})
@@ -79,16 +84,46 @@ func Range(source <-chan interface{}) Stream {
}
}
// AllMach returns whether all elements of this stream match the provided predicate.
// May not evaluate the predicate on all elements if not necessary for determining the result.
// If the stream is empty then true is returned and the predicate is not evaluated.
func (s Stream) AllMach(predicate func(item interface{}) bool) bool {
for item := range s.source {
if !predicate(item) {
// make sure the former goroutine not block, and current func returns fast.
go drain(s.source)
return false
}
}
return true
}
// AnyMach returns whether any elements of this stream match the provided predicate.
// May not evaluate the predicate on all elements if not necessary for determining the result.
// If the stream is empty then false is returned and the predicate is not evaluated.
func (s Stream) AnyMach(predicate func(item interface{}) bool) bool {
for item := range s.source {
if predicate(item) {
// make sure the former goroutine not block, and current func returns fast.
go drain(s.source)
return true
}
}
return false
}
// Buffer buffers the items into a queue with size n.
// It can balance the producer and the consumer if their processing throughput don't match.
func (p Stream) Buffer(n int) Stream {
func (s Stream) Buffer(n int) Stream {
if n < 0 {
n = 0
}
source := make(chan interface{}, n)
go func() {
for item := range p.source {
for item := range s.source {
source <- item
}
close(source)
@@ -97,23 +132,51 @@ func (p Stream) Buffer(n int) Stream {
return Range(source)
}
// Concat returns a Stream that concatenated other streams
func (s Stream) Concat(others ...Stream) Stream {
source := make(chan interface{})
go func() {
group := threading.NewRoutineGroup()
group.Run(func() {
for item := range s.source {
source <- item
}
})
for _, each := range others {
each := each
group.Run(func() {
for item := range each.source {
source <- item
}
})
}
group.Wait()
close(source)
}()
return Range(source)
}
// Count counts the number of elements in the result.
func (p Stream) Count() (count int) {
for range p.source {
func (s Stream) Count() (count int) {
for range s.source {
count++
}
return
}
// Distinct removes the duplicated items base on the given KeyFunc.
func (p Stream) Distinct(fn KeyFunc) Stream {
func (s Stream) Distinct(fn KeyFunc) Stream {
source := make(chan interface{})
threading.GoSafe(func() {
defer close(source)
keys := make(map[interface{}]lang.PlaceholderType)
for item := range p.source {
for item := range s.source {
key := fn(item)
if _, ok := keys[key]; !ok {
source <- item
@@ -126,36 +189,48 @@ func (p Stream) Distinct(fn KeyFunc) Stream {
}
// Done waits all upstreaming operations to be done.
func (p Stream) Done() {
for range p.source {
}
func (s Stream) Done() {
drain(s.source)
}
// Filter filters the items by the given FilterFunc.
func (p Stream) Filter(fn FilterFunc, opts ...Option) Stream {
return p.Walk(func(item interface{}, pipe chan<- interface{}) {
func (s Stream) Filter(fn FilterFunc, opts ...Option) Stream {
return s.Walk(func(item interface{}, pipe chan<- interface{}) {
if fn(item) {
pipe <- item
}
}, opts...)
}
// First returns the first item, nil if no items.
func (s Stream) First() interface{} {
for item := range s.source {
// make sure the former goroutine not block, and current func returns fast.
go drain(s.source)
return item
}
return nil
}
// ForAll handles the streaming elements from the source and no later streams.
func (p Stream) ForAll(fn ForAllFunc) {
fn(p.source)
func (s Stream) ForAll(fn ForAllFunc) {
fn(s.source)
// avoid goroutine leak on fn not consuming all items.
go drain(s.source)
}
// ForEach seals the Stream with the ForEachFunc on each item, no successive operations.
func (p Stream) ForEach(fn ForEachFunc) {
for item := range p.source {
func (s Stream) ForEach(fn ForEachFunc) {
for item := range s.source {
fn(item)
}
}
// Group groups the elements into different groups based on their keys.
func (p Stream) Group(fn KeyFunc) Stream {
func (s Stream) Group(fn KeyFunc) Stream {
groups := make(map[interface{}][]interface{})
for item := range p.source {
for item := range s.source {
key := fn(item)
groups[key] = append(groups[key], item)
}
@@ -172,7 +247,7 @@ func (p Stream) Group(fn KeyFunc) Stream {
}
// Head returns the first n elements in p.
func (p Stream) Head(n int64) Stream {
func (s Stream) Head(n int64) Stream {
if n < 1 {
panic("n must be greater than 0")
}
@@ -180,18 +255,21 @@ func (p Stream) Head(n int64) Stream {
source := make(chan interface{})
go func() {
for item := range p.source {
for item := range s.source {
n--
if n >= 0 {
source <- item
}
if n == 0 {
// let successive method go ASAP even we have more items to skip
// why we don't just break the loop, because if break,
// this former goroutine will block forever, which will cause goroutine leak.
close(source)
// why we don't just break the loop, and drain to consume all items.
// because if breaks, this former goroutine will block forever,
// which will cause goroutine leak.
drain(s.source)
}
}
// not enough items in s.source, but we need to let successive method to go ASAP.
if n > 0 {
close(source)
}
@@ -200,17 +278,24 @@ func (p Stream) Head(n int64) Stream {
return Range(source)
}
// Last returns the last item, or nil if no items.
func (s Stream) Last() (item interface{}) {
for item = range s.source {
}
return
}
// Map converts each item to another corresponding item, which means it's a 1:1 model.
func (p Stream) Map(fn MapFunc, opts ...Option) Stream {
return p.Walk(func(item interface{}, pipe chan<- interface{}) {
func (s Stream) Map(fn MapFunc, opts ...Option) Stream {
return s.Walk(func(item interface{}, pipe chan<- interface{}) {
pipe <- fn(item)
}, opts...)
}
// Merge merges all the items into a slice and generates a new stream.
func (p Stream) Merge() Stream {
func (s Stream) Merge() Stream {
var items []interface{}
for item := range p.source {
for item := range s.source {
items = append(items, item)
}
@@ -221,22 +306,37 @@ func (p Stream) Merge() Stream {
return Range(source)
}
// NoneMatch returns whether all elements of this stream don't match the provided predicate.
// May not evaluate the predicate on all elements if not necessary for determining the result.
// If the stream is empty then true is returned and the predicate is not evaluated.
func (s Stream) NoneMatch(predicate func(item interface{}) bool) bool {
for item := range s.source {
if predicate(item) {
// make sure the former goroutine not block, and current func returns fast.
go drain(s.source)
return false
}
}
return true
}
// Parallel applies the given ParallelFunc to each item concurrently with given number of workers.
func (p Stream) Parallel(fn ParallelFunc, opts ...Option) {
p.Walk(func(item interface{}, pipe chan<- interface{}) {
func (s Stream) Parallel(fn ParallelFunc, opts ...Option) {
s.Walk(func(item interface{}, pipe chan<- interface{}) {
fn(item)
}, opts...).Done()
}
// Reduce is a utility method to let the caller deal with the underlying channel.
func (p Stream) Reduce(fn ReduceFunc) (interface{}, error) {
return fn(p.source)
func (s Stream) Reduce(fn ReduceFunc) (interface{}, error) {
return fn(s.source)
}
// Reverse reverses the elements in the stream.
func (p Stream) Reverse() Stream {
func (s Stream) Reverse() Stream {
var items []interface{}
for item := range p.source {
for item := range s.source {
items = append(items, item)
}
// reverse, official method
@@ -248,10 +348,36 @@ func (p Stream) Reverse() Stream {
return Just(items...)
}
// Skip returns a Stream that skips size elements.
func (s Stream) Skip(n int64) Stream {
if n < 0 {
panic("n must not be negative")
}
if n == 0 {
return s
}
source := make(chan interface{})
go func() {
for item := range s.source {
n--
if n >= 0 {
continue
} else {
source <- item
}
}
close(source)
}()
return Range(source)
}
// Sort sorts the items from the underlying source.
func (p Stream) Sort(less LessFunc) Stream {
func (s Stream) Sort(less LessFunc) Stream {
var items []interface{}
for item := range p.source {
for item := range s.source {
items = append(items, item)
}
sort.Slice(items, func(i, j int) bool {
@@ -263,7 +389,7 @@ func (p Stream) Sort(less LessFunc) Stream {
// Split splits the elements into chunk with size up to n,
// might be less than n on tailing elements.
func (p Stream) Split(n int) Stream {
func (s Stream) Split(n int) Stream {
if n < 1 {
panic("n should be greater than 0")
}
@@ -271,7 +397,7 @@ func (p Stream) Split(n int) Stream {
source := make(chan interface{})
go func() {
var chunk []interface{}
for item := range p.source {
for item := range s.source {
chunk = append(chunk, item)
if len(chunk) == n {
source <- chunk
@@ -288,7 +414,7 @@ func (p Stream) Split(n int) Stream {
}
// Tail returns the last n elements in p.
func (p Stream) Tail(n int64) Stream {
func (s Stream) Tail(n int64) Stream {
if n < 1 {
panic("n should be greater than 0")
}
@@ -297,7 +423,7 @@ func (p Stream) Tail(n int64) Stream {
go func() {
ring := collection.NewRing(int(n))
for item := range p.source {
for item := range s.source {
ring.Add(item)
}
for _, item := range ring.Take() {
@@ -310,31 +436,28 @@ func (p Stream) Tail(n int64) Stream {
}
// Walk lets the callers handle each item, the caller may write zero, one or more items base on the given item.
func (p Stream) Walk(fn WalkFunc, opts ...Option) Stream {
func (s Stream) Walk(fn WalkFunc, opts ...Option) Stream {
option := buildOptions(opts...)
if option.unlimitedWorkers {
return p.walkUnlimited(fn, option)
return s.walkUnlimited(fn, option)
}
return p.walkLimited(fn, option)
return s.walkLimited(fn, option)
}
func (p Stream) walkLimited(fn WalkFunc, option *rxOptions) Stream {
func (s Stream) walkLimited(fn WalkFunc, option *rxOptions) Stream {
pipe := make(chan interface{}, option.workers)
go func() {
var wg sync.WaitGroup
pool := make(chan lang.PlaceholderType, option.workers)
for {
for item := range s.source {
// important, used in another goroutine
val := item
pool <- lang.Placeholder
item, ok := <-p.source
if !ok {
<-pool
break
}
wg.Add(1)
// better to safely run caller defined method
threading.GoSafe(func() {
defer func() {
@@ -342,7 +465,7 @@ func (p Stream) walkLimited(fn WalkFunc, option *rxOptions) Stream {
<-pool
}()
fn(item, pipe)
fn(val, pipe)
})
}
@@ -353,23 +476,20 @@ func (p Stream) walkLimited(fn WalkFunc, option *rxOptions) Stream {
return Range(pipe)
}
func (p Stream) walkUnlimited(fn WalkFunc, option *rxOptions) Stream {
pipe := make(chan interface{}, defaultWorkers)
func (s Stream) walkUnlimited(fn WalkFunc, option *rxOptions) Stream {
pipe := make(chan interface{}, option.workers)
go func() {
var wg sync.WaitGroup
for {
item, ok := <-p.source
if !ok {
break
}
for item := range s.source {
// important, used in another goroutine
val := item
wg.Add(1)
// better to safely run caller defined method
threading.GoSafe(func() {
defer wg.Done()
fn(item, pipe)
fn(val, pipe)
})
}
@@ -380,14 +500,14 @@ func (p Stream) walkUnlimited(fn WalkFunc, option *rxOptions) Stream {
return Range(pipe)
}
// UnlimitedWorkers lets the caller to use as many workers as the tasks.
// UnlimitedWorkers lets the caller use as many workers as the tasks.
func UnlimitedWorkers() Option {
return func(opts *rxOptions) {
opts.unlimitedWorkers = true
}
}
// WithWorkers lets the caller to customize the concurrent workers.
// WithWorkers lets the caller customize the concurrent workers.
func WithWorkers(workers int) Option {
return func(opts *rxOptions) {
if workers < minWorkers {
@@ -398,6 +518,7 @@ func WithWorkers(workers int) Option {
}
}
// buildOptions returns a rxOptions with given customizations.
func buildOptions(opts ...Option) *rxOptions {
options := newOptions()
for _, opt := range opts {
@@ -407,6 +528,13 @@ func buildOptions(opts ...Option) *rxOptions {
return options
}
// drain drains the given channel.
func drain(channel <-chan interface{}) {
for range channel {
}
}
// newOptions returns a default rxOptions.
func newOptions() *rxOptions {
return &rxOptions{
workers: defaultWorkers,
+450 -235
View File
@@ -3,331 +3,527 @@ package fx
import (
"io/ioutil"
"log"
"math/rand"
"reflect"
"runtime"
"sort"
"sync"
"sync/atomic"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/zeromicro/go-zero/core/stringx"
"go.uber.org/goleak"
)
func TestBuffer(t *testing.T) {
const N = 5
var count int32
var wait sync.WaitGroup
wait.Add(1)
From(func(source chan<- interface{}) {
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
runCheckedTest(t, func(t *testing.T) {
const N = 5
var count int32
var wait sync.WaitGroup
wait.Add(1)
From(func(source chan<- interface{}) {
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
for i := 0; i < 2*N; i++ {
select {
case source <- i:
atomic.AddInt32(&count, 1)
case <-ticker.C:
wait.Done()
return
for i := 0; i < 2*N; i++ {
select {
case source <- i:
atomic.AddInt32(&count, 1)
case <-ticker.C:
wait.Done()
return
}
}
}
}).Buffer(N).ForAll(func(pipe <-chan interface{}) {
wait.Wait()
// why N+1, because take one more to wait for sending into the channel
assert.Equal(t, int32(N+1), atomic.LoadInt32(&count))
}).Buffer(N).ForAll(func(pipe <-chan interface{}) {
wait.Wait()
// why N+1, because take one more to wait for sending into the channel
assert.Equal(t, int32(N+1), atomic.LoadInt32(&count))
})
})
}
func TestBufferNegative(t *testing.T) {
var result int
Just(1, 2, 3, 4).Buffer(-1).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4).Buffer(-1).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, 10, result)
})
assert.Equal(t, 10, result)
}
func TestCount(t *testing.T) {
tests := []struct {
name string
elements []interface{}
}{
{
name: "no elements with nil",
},
{
name: "no elements",
elements: []interface{}{},
},
{
name: "1 element",
elements: []interface{}{1},
},
{
name: "multiple elements",
elements: []interface{}{1, 2, 3},
},
}
runCheckedTest(t, func(t *testing.T) {
tests := []struct {
name string
elements []interface{}
}{
{
name: "no elements with nil",
},
{
name: "no elements",
elements: []interface{}{},
},
{
name: "1 element",
elements: []interface{}{1},
},
{
name: "multiple elements",
elements: []interface{}{1, 2, 3},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
val := Just(test.elements...).Count()
assert.Equal(t, len(test.elements), val)
})
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
val := Just(test.elements...).Count()
assert.Equal(t, len(test.elements), val)
})
}
})
}
func TestDone(t *testing.T) {
var count int32
Just(1, 2, 3).Walk(func(item interface{}, pipe chan<- interface{}) {
time.Sleep(time.Millisecond * 100)
atomic.AddInt32(&count, int32(item.(int)))
}).Done()
assert.Equal(t, int32(6), count)
runCheckedTest(t, func(t *testing.T) {
var count int32
Just(1, 2, 3).Walk(func(item interface{}, pipe chan<- interface{}) {
time.Sleep(time.Millisecond * 100)
atomic.AddInt32(&count, int32(item.(int)))
}).Done()
assert.Equal(t, int32(6), count)
})
}
func TestJust(t *testing.T) {
var result int
Just(1, 2, 3, 4).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, 10, result)
})
assert.Equal(t, 10, result)
}
func TestDistinct(t *testing.T) {
var result int
Just(4, 1, 3, 2, 3, 4).Distinct(func(item interface{}) interface{} {
return item
}).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
runCheckedTest(t, func(t *testing.T) {
var result int
Just(4, 1, 3, 2, 3, 4).Distinct(func(item interface{}) interface{} {
return item
}).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, 10, result)
})
assert.Equal(t, 10, result)
}
func TestFilter(t *testing.T) {
var result int
Just(1, 2, 3, 4).Filter(func(item interface{}) bool {
return item.(int)%2 == 0
}).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4).Filter(func(item interface{}) bool {
return item.(int)%2 == 0
}).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, 6, result)
})
}
func TestFirst(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
assert.Nil(t, Just().First())
assert.Equal(t, "foo", Just("foo").First())
assert.Equal(t, "foo", Just("foo", "bar").First())
})
assert.Equal(t, 6, result)
}
func TestForAll(t *testing.T) {
var result int
Just(1, 2, 3, 4).Filter(func(item interface{}) bool {
return item.(int)%2 == 0
}).ForAll(func(pipe <-chan interface{}) {
for item := range pipe {
result += item.(int)
}
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4).Filter(func(item interface{}) bool {
return item.(int)%2 == 0
}).ForAll(func(pipe <-chan interface{}) {
for item := range pipe {
result += item.(int)
}
})
assert.Equal(t, 6, result)
})
assert.Equal(t, 6, result)
}
func TestGroup(t *testing.T) {
var groups [][]int
Just(10, 11, 20, 21).Group(func(item interface{}) interface{} {
v := item.(int)
return v / 10
}).ForEach(func(item interface{}) {
v := item.([]interface{})
var group []int
for _, each := range v {
group = append(group, each.(int))
}
groups = append(groups, group)
})
runCheckedTest(t, func(t *testing.T) {
var groups [][]int
Just(10, 11, 20, 21).Group(func(item interface{}) interface{} {
v := item.(int)
return v / 10
}).ForEach(func(item interface{}) {
v := item.([]interface{})
var group []int
for _, each := range v {
group = append(group, each.(int))
}
groups = append(groups, group)
})
assert.Equal(t, 2, len(groups))
for _, group := range groups {
assert.Equal(t, 2, len(group))
assert.True(t, group[0]/10 == group[1]/10)
}
assert.Equal(t, 2, len(groups))
for _, group := range groups {
assert.Equal(t, 2, len(group))
assert.True(t, group[0]/10 == group[1]/10)
}
})
}
func TestHead(t *testing.T) {
var result int
Just(1, 2, 3, 4).Head(2).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4).Head(2).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, 3, result)
})
assert.Equal(t, 3, result)
}
func TestHeadZero(t *testing.T) {
assert.Panics(t, func() {
Just(1, 2, 3, 4).Head(0).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
return nil, nil
runCheckedTest(t, func(t *testing.T) {
assert.Panics(t, func() {
Just(1, 2, 3, 4).Head(0).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
return nil, nil
})
})
})
}
func TestHeadMore(t *testing.T) {
var result int
Just(1, 2, 3, 4).Head(6).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4).Head(6).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, 10, result)
})
}
func TestLast(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
goroutines := runtime.NumGoroutine()
assert.Nil(t, Just().Last())
assert.Equal(t, "foo", Just("foo").Last())
assert.Equal(t, "bar", Just("foo", "bar").Last())
// let scheduler schedule first
runtime.Gosched()
assert.Equal(t, goroutines, runtime.NumGoroutine())
})
assert.Equal(t, 10, result)
}
func TestMap(t *testing.T) {
log.SetOutput(ioutil.Discard)
runCheckedTest(t, func(t *testing.T) {
log.SetOutput(ioutil.Discard)
tests := []struct {
mapper MapFunc
expect int
}{
{
mapper: func(item interface{}) interface{} {
v := item.(int)
return v * v
tests := []struct {
mapper MapFunc
expect int
}{
{
mapper: func(item interface{}) interface{} {
v := item.(int)
return v * v
},
expect: 30,
},
expect: 30,
},
{
mapper: func(item interface{}) interface{} {
v := item.(int)
if v%2 == 0 {
return 0
}
return v * v
},
expect: 10,
},
{
mapper: func(item interface{}) interface{} {
v := item.(int)
if v%2 == 0 {
panic(v)
}
return v * v
},
expect: 10,
},
}
// Map(...) works even WithWorkers(0)
for i, test := range tests {
t.Run(stringx.Rand(), func(t *testing.T) {
var result int
var workers int
if i%2 == 0 {
workers = 0
} else {
workers = runtime.NumCPU()
}
From(func(source chan<- interface{}) {
for i := 1; i < 5; i++ {
source <- i
}
}).Map(test.mapper, WithWorkers(workers)).Reduce(
func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
{
mapper: func(item interface{}) interface{} {
v := item.(int)
if v%2 == 0 {
return 0
}
return result, nil
})
return v * v
},
expect: 10,
},
{
mapper: func(item interface{}) interface{} {
v := item.(int)
if v%2 == 0 {
panic(v)
}
return v * v
},
expect: 10,
},
}
assert.Equal(t, test.expect, result)
})
}
// Map(...) works even WithWorkers(0)
for i, test := range tests {
t.Run(stringx.Rand(), func(t *testing.T) {
var result int
var workers int
if i%2 == 0 {
workers = 0
} else {
workers = runtime.NumCPU()
}
From(func(source chan<- interface{}) {
for i := 1; i < 5; i++ {
source <- i
}
}).Map(test.mapper, WithWorkers(workers)).Reduce(
func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, test.expect, result)
})
}
})
}
func TestMerge(t *testing.T) {
Just(1, 2, 3, 4).Merge().ForEach(func(item interface{}) {
assert.ElementsMatch(t, []interface{}{1, 2, 3, 4}, item.([]interface{}))
runCheckedTest(t, func(t *testing.T) {
Just(1, 2, 3, 4).Merge().ForEach(func(item interface{}) {
assert.ElementsMatch(t, []interface{}{1, 2, 3, 4}, item.([]interface{}))
})
})
}
func TestParallelJust(t *testing.T) {
var count int32
Just(1, 2, 3).Parallel(func(item interface{}) {
time.Sleep(time.Millisecond * 100)
atomic.AddInt32(&count, int32(item.(int)))
}, UnlimitedWorkers())
assert.Equal(t, int32(6), count)
runCheckedTest(t, func(t *testing.T) {
var count int32
Just(1, 2, 3).Parallel(func(item interface{}) {
time.Sleep(time.Millisecond * 100)
atomic.AddInt32(&count, int32(item.(int)))
}, UnlimitedWorkers())
assert.Equal(t, int32(6), count)
})
}
func TestReverse(t *testing.T) {
Just(1, 2, 3, 4).Reverse().Merge().ForEach(func(item interface{}) {
assert.ElementsMatch(t, []interface{}{4, 3, 2, 1}, item.([]interface{}))
runCheckedTest(t, func(t *testing.T) {
Just(1, 2, 3, 4).Reverse().Merge().ForEach(func(item interface{}) {
assert.ElementsMatch(t, []interface{}{4, 3, 2, 1}, item.([]interface{}))
})
})
}
func TestSort(t *testing.T) {
var prev int
Just(5, 3, 7, 1, 9, 6, 4, 8, 2).Sort(func(a, b interface{}) bool {
return a.(int) < b.(int)
}).ForEach(func(item interface{}) {
next := item.(int)
assert.True(t, prev < next)
prev = next
runCheckedTest(t, func(t *testing.T) {
var prev int
Just(5, 3, 7, 1, 9, 6, 4, 8, 2).Sort(func(a, b interface{}) bool {
return a.(int) < b.(int)
}).ForEach(func(item interface{}) {
next := item.(int)
assert.True(t, prev < next)
prev = next
})
})
}
func TestSplit(t *testing.T) {
assert.Panics(t, func() {
Just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).Split(0).Done()
runCheckedTest(t, func(t *testing.T) {
assert.Panics(t, func() {
Just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).Split(0).Done()
})
var chunks [][]interface{}
Just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).Split(4).ForEach(func(item interface{}) {
chunk := item.([]interface{})
chunks = append(chunks, chunk)
})
assert.EqualValues(t, [][]interface{}{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10},
}, chunks)
})
var chunks [][]interface{}
Just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).Split(4).ForEach(func(item interface{}) {
chunk := item.([]interface{})
chunks = append(chunks, chunk)
})
assert.EqualValues(t, [][]interface{}{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10},
}, chunks)
}
func TestTail(t *testing.T) {
var result int
Just(1, 2, 3, 4).Tail(2).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4).Tail(2).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
for item := range pipe {
result += item.(int)
}
return result, nil
})
assert.Equal(t, 7, result)
})
assert.Equal(t, 7, result)
}
func TestTailZero(t *testing.T) {
assert.Panics(t, func() {
Just(1, 2, 3, 4).Tail(0).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
return nil, nil
runCheckedTest(t, func(t *testing.T) {
assert.Panics(t, func() {
Just(1, 2, 3, 4).Tail(0).Reduce(func(pipe <-chan interface{}) (interface{}, error) {
return nil, nil
})
})
})
}
func TestWalk(t *testing.T) {
var result int
Just(1, 2, 3, 4, 5).Walk(func(item interface{}, pipe chan<- interface{}) {
if item.(int)%2 != 0 {
pipe <- item
}
}, UnlimitedWorkers()).ForEach(func(item interface{}) {
result += item.(int)
runCheckedTest(t, func(t *testing.T) {
var result int
Just(1, 2, 3, 4, 5).Walk(func(item interface{}, pipe chan<- interface{}) {
if item.(int)%2 != 0 {
pipe <- item
}
}, UnlimitedWorkers()).ForEach(func(item interface{}) {
result += item.(int)
})
assert.Equal(t, 9, result)
})
assert.Equal(t, 9, result)
}
func TestStream_AnyMach(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
assetEqual(t, false, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return item.(int) == 4
}))
assetEqual(t, false, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return item.(int) == 0
}))
assetEqual(t, true, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return item.(int) == 2
}))
assetEqual(t, true, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return item.(int) == 2
}))
})
}
func TestStream_AllMach(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
assetEqual(
t, true, Just(1, 2, 3).AllMach(func(item interface{}) bool {
return true
}),
)
assetEqual(
t, false, Just(1, 2, 3).AllMach(func(item interface{}) bool {
return false
}),
)
assetEqual(
t, false, Just(1, 2, 3).AllMach(func(item interface{}) bool {
return item.(int) == 1
}),
)
})
}
func TestStream_NoneMatch(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
assetEqual(
t, true, Just(1, 2, 3).NoneMatch(func(item interface{}) bool {
return false
}),
)
assetEqual(
t, false, Just(1, 2, 3).NoneMatch(func(item interface{}) bool {
return true
}),
)
assetEqual(
t, true, Just(1, 2, 3).NoneMatch(func(item interface{}) bool {
return item.(int) == 4
}),
)
})
}
func TestConcat(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
a1 := []interface{}{1, 2, 3}
a2 := []interface{}{4, 5, 6}
s1 := Just(a1...)
s2 := Just(a2...)
stream := Concat(s1, s2)
var items []interface{}
for item := range stream.source {
items = append(items, item)
}
sort.Slice(items, func(i, j int) bool {
return items[i].(int) < items[j].(int)
})
ints := make([]interface{}, 0)
ints = append(ints, a1...)
ints = append(ints, a2...)
assetEqual(t, ints, items)
})
}
func TestStream_Skip(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
assetEqual(t, 3, Just(1, 2, 3, 4).Skip(1).Count())
assetEqual(t, 1, Just(1, 2, 3, 4).Skip(3).Count())
assetEqual(t, 4, Just(1, 2, 3, 4).Skip(0).Count())
equal(t, Just(1, 2, 3, 4).Skip(3), []interface{}{4})
assert.Panics(t, func() {
Just(1, 2, 3, 4).Skip(-1)
})
})
}
func TestStream_Concat(t *testing.T) {
runCheckedTest(t, func(t *testing.T) {
stream := Just(1).Concat(Just(2), Just(3))
var items []interface{}
for item := range stream.source {
items = append(items, item)
}
sort.Slice(items, func(i, j int) bool {
return items[i].(int) < items[j].(int)
})
assetEqual(t, []interface{}{1, 2, 3}, items)
just := Just(1)
equal(t, just.Concat(just), []interface{}{1})
})
}
func BenchmarkParallelMapReduce(b *testing.B) {
b.ReportAllocs()
mapper := func(v interface{}) interface{} {
return v.(int64) * v.(int64)
}
reducer := func(input <-chan interface{}) (interface{}, error) {
var result int64
for v := range input {
result += v.(int64)
}
return result, nil
}
b.ResetTimer()
From(func(input chan<- interface{}) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
input <- int64(rand.Int())
}
})
}).Map(mapper).Reduce(reducer)
}
func BenchmarkMapReduce(b *testing.B) {
@@ -343,12 +539,31 @@ func BenchmarkMapReduce(b *testing.B) {
}
return result, nil
}
b.ResetTimer()
From(func(input chan<- interface{}) {
for i := 0; i < b.N; i++ {
input <- int64(rand.Int())
}
}).Map(mapper).Reduce(reducer)
}
for i := 0; i < b.N; i++ {
From(func(input chan<- interface{}) {
for j := 0; j < 2; j++ {
input <- int64(j)
}
}).Map(mapper).Reduce(reducer)
func assetEqual(t *testing.T, except, data interface{}) {
if !reflect.DeepEqual(except, data) {
t.Errorf(" %v, want %v", data, except)
}
}
func equal(t *testing.T, stream Stream, data []interface{}) {
items := make([]interface{}, 0)
for item := range stream.source {
items = append(items, item)
}
if !reflect.DeepEqual(items, data) {
t.Errorf(" %v, want %v", items, data)
}
}
func runCheckedTest(t *testing.T, fn func(t *testing.T)) {
defer goleak.VerifyNone(t)
fn(t)
}
+5 -1
View File
@@ -2,6 +2,9 @@ package fx
import (
"context"
"fmt"
"runtime/debug"
"strings"
"time"
)
@@ -30,7 +33,8 @@ func DoWithTimeout(fn func() error, timeout time.Duration, opts ...DoOption) err
go func() {
defer func() {
if p := recover(); p != nil {
panicChan <- p
// attach call stack to avoid missing in different goroutine
panicChan <- fmt.Sprintf("%+v\n\n%s", p, strings.TrimSpace(string(debug.Stack())))
}
}()
done <- fn()
+3 -3
View File
@@ -6,8 +6,8 @@ import (
"strconv"
"sync"
"github.com/tal-tech/go-zero/core/lang"
"github.com/tal-tech/go-zero/core/mapping"
"github.com/zeromicro/go-zero/core/lang"
"github.com/zeromicro/go-zero/core/mapping"
)
const (
@@ -83,7 +83,7 @@ func (h *ConsistentHash) AddWithReplicas(node interface{}, replicas int) {
h.ring[hash] = append(h.ring[hash], node)
}
sort.Slice(h.keys, func(i int, j int) bool {
sort.Slice(h.keys, func(i, j int) bool {
return h.keys[i] < h.keys[j]
})
}
+4 -4
View File
@@ -6,7 +6,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/mathx"
"github.com/zeromicro/go-zero/core/mathx"
)
const (
@@ -74,12 +74,12 @@ func TestConsistentHashIncrementalTransfer(t *testing.T) {
laterCh := create()
laterCh.AddWithWeight(node, 10*(i+1))
for i := 0; i < requestSize; i++ {
key, ok := laterCh.Get(requestSize + i)
for j := 0; j < requestSize; j++ {
key, ok := laterCh.Get(requestSize + j)
assert.True(t, ok)
assert.NotNil(t, key)
value := key.(string)
assert.True(t, value == keys[i] || value == node)
assert.True(t, value == keys[j] || value == node)
}
}
}
+5
View File
@@ -20,6 +20,11 @@ func TestMd5(t *testing.T) {
assert.Equal(t, md5Digest, actual)
}
func TestMd5Hex(t *testing.T) {
actual := Md5Hex([]byte(text))
assert.Equal(t, md5Digest, actual)
}
func BenchmarkHashFnv(b *testing.B) {
for i := 0; i < b.N; i++ {
h := fnv.New32()
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/fs"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/zeromicro/go-zero/core/fs"
"github.com/zeromicro/go-zero/core/stringx"
)
func TestReadText(t *testing.T) {
+18
View File
@@ -5,6 +5,7 @@ import (
"testing"
"time"
"github.com/globalsign/mgo/bson"
"github.com/stretchr/testify/assert"
)
@@ -106,3 +107,20 @@ func TestMilliTime_UnmarshalJSON(t *testing.T) {
})
}
}
func TestUnmarshalWithError(t *testing.T) {
var mt MilliTime
assert.NotNil(t, mt.UnmarshalJSON([]byte("hello")))
}
func TestSetBSON(t *testing.T) {
data, err := bson.Marshal(time.Now())
assert.Nil(t, err)
var raw bson.Raw
assert.Nil(t, bson.Unmarshal(data, &raw))
var mt MilliTime
assert.Nil(t, mt.SetBSON(raw))
assert.NotNil(t, mt.SetBSON(bson.Raw{}))
}
+1 -1
View File
@@ -51,5 +51,5 @@ func unmarshalUseNumber(decoder *json.Decoder, v interface{}) error {
}
func formatError(v string, err error) error {
return fmt.Errorf("string: `%s`, error: `%s`", v, err.Error())
return fmt.Errorf("string: `%s`, error: `%w`", v, err)
}
+2 -2
View File
@@ -4,8 +4,8 @@ package lang
var Placeholder PlaceholderType
type (
// GenericType can be used to hold any type.
GenericType = interface{}
// AnyType can be used to hold any type.
AnyType = interface{}
// PlaceholderType represents a placeholder type.
PlaceholderType = struct{}
)
+8 -7
View File
@@ -5,12 +5,11 @@ import (
"strconv"
"time"
"github.com/tal-tech/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/redis"
)
const (
// to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key
periodScript = `local limit = tonumber(ARGV[1])
// to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key
const periodScript = `local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = redis.call("INCRBY", KEYS[1], 1)
if current == 1 then
@@ -23,8 +22,6 @@ elseif current == limit then
else
return 0
end`
zoneDiff = 3600 * 8 // GMT+8 for our services
)
const (
// Unknown means not initialized state.
@@ -104,7 +101,9 @@ func (h *PeriodLimit) Take(key string) (int, error) {
func (h *PeriodLimit) calcExpireSeconds() int {
if h.align {
unix := time.Now().Unix() + zoneDiff
now := time.Now()
_, offset := now.Zone()
unix := now.Unix() + int64(offset)
return h.period - int(unix%int64(h.period))
}
@@ -112,6 +111,8 @@ func (h *PeriodLimit) calcExpireSeconds() int {
}
// Align returns a func to customize a PeriodLimit with alignment.
// For example, if we want to limit end users with 5 sms verification messages every day,
// we need to align with the local timezone and the start of the day.
func Align() PeriodOption {
return func(l *PeriodLimit) {
l.align = true
+3 -4
View File
@@ -5,8 +5,8 @@ import (
"github.com/alicebob/miniredis/v2"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stores/redis"
"github.com/tal-tech/go-zero/core/stores/redis/redistest"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/redis/redistest"
)
func TestPeriodLimit_Take(t *testing.T) {
@@ -23,10 +23,9 @@ func TestPeriodLimit_RedisUnavailable(t *testing.T) {
const (
seconds = 1
total = 100
quota = 5
)
l := NewPeriodLimit(seconds, quota, redis.NewRedis(s.Addr(), redis.NodeType), "periodlimit")
l := NewPeriodLimit(seconds, quota, redis.New(s.Addr()), "periodlimit")
s.Close()
val, err := l.Take("first")
assert.NotNil(t, err)
+6 -5
View File
@@ -7,8 +7,8 @@ import (
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis"
xrate "golang.org/x/time/rate"
)
@@ -85,8 +85,8 @@ func (lim *TokenLimiter) Allow() bool {
}
// AllowN reports whether n events may happen at time now.
// Use this method if you intend to drop / skip events that exceed the rate rate.
// Otherwise use Reserve or Wait.
// Use this method if you intend to drop / skip events that exceed the rate.
// Otherwise, use Reserve or Wait.
func (lim *TokenLimiter) AllowN(now time.Time, n int) bool {
return lim.reserveN(now, n)
}
@@ -112,7 +112,8 @@ func (lim *TokenLimiter) reserveN(now time.Time, n int) bool {
// Lua boolean false -> r Nil bulk reply
if err == redis.Nil {
return false
} else if err != nil {
}
if err != nil {
logx.Errorf("fail to use rate limiter: %s, use in-process limiter for rescue", err)
lim.startMonitor()
return lim.rescueLimiter.AllowN(now, n)
+4 -4
View File
@@ -6,9 +6,9 @@ import (
"github.com/alicebob/miniredis/v2"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/stores/redis"
"github.com/tal-tech/go-zero/core/stores/redis/redistest"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/redis/redistest"
)
func init() {
@@ -24,7 +24,7 @@ func TestTokenLimit_Rescue(t *testing.T) {
rate = 5
burst = 10
)
l := NewTokenLimiter(rate, burst, redis.NewRedis(s.Addr(), redis.NodeType), "tokenlimit")
l := NewTokenLimiter(rate, burst, redis.New(s.Addr()), "tokenlimit")
s.Close()
var allowed int
+12 -5
View File
@@ -7,11 +7,11 @@ import (
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/collection"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/stat"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/collection"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stat"
"github.com/zeromicro/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/timex"
)
const (
@@ -31,6 +31,8 @@ var (
// default to be enabled
enabled = syncx.ForAtomicBool(true)
// default to be enabled
logEnabled = syncx.ForAtomicBool(true)
// make it a variable for unit test
systemOverloadChecker = func(cpuThreshold int64) bool {
return stat.CpuUsage() >= cpuThreshold
@@ -80,6 +82,11 @@ func Disable() {
enabled.Set(false)
}
// DisableLog disables the stat logs for load shedding.
func DisableLog() {
logEnabled.Set(false)
}
// NewAdaptiveShedder returns an adaptive shedder.
// opts can be used to customize the Shedder.
func NewAdaptiveShedder(opts ...ShedderOption) Shedder {
+6 -5
View File
@@ -8,11 +8,11 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/collection"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/mathx"
"github.com/tal-tech/go-zero/core/stat"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/collection"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mathx"
"github.com/zeromicro/go-zero/core/stat"
"github.com/zeromicro/go-zero/core/syncx"
)
const (
@@ -25,6 +25,7 @@ func init() {
}
func TestAdaptiveShedder(t *testing.T) {
DisableLog()
shedder := NewAdaptiveShedder(WithWindow(bucketDuration), WithBuckets(buckets), WithCpuThreshold(100))
var wg sync.WaitGroup
var drop int64
+1 -1
View File
@@ -3,7 +3,7 @@ package load
import (
"io"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/syncx"
)
// A ShedderGroup is a manager to manage key based shedders.
+23 -13
View File
@@ -4,8 +4,8 @@ import (
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/stat"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stat"
)
type (
@@ -48,6 +48,25 @@ func (s *SheddingStat) IncrementDrop() {
atomic.AddInt64(&s.drop, 1)
}
func (s *SheddingStat) loop(c <-chan time.Time) {
for range c {
st := s.reset()
if !logEnabled.True() {
continue
}
c := stat.CpuUsage()
if st.Drop == 0 {
logx.Statf("(%s) shedding_stat [1m], cpu: %d, total: %d, pass: %d, drop: %d",
s.name, c, st.Total, st.Pass, st.Drop)
} else {
logx.Statf("(%s) shedding_stat_drop [1m], cpu: %d, total: %d, pass: %d, drop: %d",
s.name, c, st.Total, st.Pass, st.Drop)
}
}
}
func (s *SheddingStat) reset() snapshot {
return snapshot{
Total: atomic.SwapInt64(&s.total, 0),
@@ -59,15 +78,6 @@ func (s *SheddingStat) reset() snapshot {
func (s *SheddingStat) run() {
ticker := time.NewTicker(time.Minute)
defer ticker.Stop()
for range ticker.C {
c := stat.CpuUsage()
st := s.reset()
if st.Drop == 0 {
logx.Statf("(%s) shedding_stat [1m], cpu: %d, total: %d, pass: %d, drop: %d",
s.name, c, st.Total, st.Pass, st.Drop)
} else {
logx.Statf("(%s) shedding_stat_drop [1m], cpu: %d, total: %d, pass: %d, drop: %d",
s.name, c, st.Total, st.Pass, st.Drop)
}
}
s.loop(ticker.C)
}
+30
View File
@@ -2,6 +2,7 @@ package load
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
@@ -22,3 +23,32 @@ func TestSheddingStat(t *testing.T) {
assert.Equal(t, int64(5), result.Pass)
assert.Equal(t, int64(7), result.Drop)
}
func TestLoopTrue(t *testing.T) {
ch := make(chan time.Time, 1)
ch <- time.Now()
close(ch)
st := new(SheddingStat)
logEnabled.Set(true)
st.loop(ch)
}
func TestLoopTrueAndDrop(t *testing.T) {
ch := make(chan time.Time, 1)
ch <- time.Now()
close(ch)
st := new(SheddingStat)
st.IncrementDrop()
logEnabled.Set(true)
st.loop(ch)
}
func TestLoopFalseAndDrop(t *testing.T) {
ch := make(chan time.Time, 1)
ch <- time.Now()
close(ch)
st := new(SheddingStat)
st.IncrementDrop()
logEnabled.Set(false)
st.loop(ch)
}
+3 -2
View File
@@ -3,10 +3,11 @@ package logx
// A LogConf is a logging config.
type LogConf struct {
ServiceName string `json:",optional"`
Mode string `json:",default=console,options=console|file|volume"`
Mode string `json:",default=console,options=[console,file,volume]"`
Encoding string `json:",default=json,options=[json,plain]"`
TimeFormat string `json:",optional"`
Path string `json:",default=logs"`
Level string `json:",default=info,options=info|error|severe"`
Level string `json:",default=info,options=[info,error,severe]"`
Compress bool `json:",optional"`
KeepDays int `json:",optional"`
StackCooldownMillis int `json:",default=100"`
+38 -12
View File
@@ -3,9 +3,10 @@ package logx
import (
"fmt"
"io"
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/timex"
)
const durationCallerDepth = 3
@@ -20,49 +21,74 @@ func WithDuration(d time.Duration) Logger {
}
func (l *durationLogger) Error(v ...interface{}) {
if shouldLog(ErrorLevel) {
if shallLog(ErrorLevel) {
l.write(errorLog, levelError, formatWithCaller(fmt.Sprint(v...), durationCallerDepth))
}
}
func (l *durationLogger) Errorf(format string, v ...interface{}) {
if shouldLog(ErrorLevel) {
if shallLog(ErrorLevel) {
l.write(errorLog, levelError, formatWithCaller(fmt.Sprintf(format, v...), durationCallerDepth))
}
}
func (l *durationLogger) Errorv(v interface{}) {
if shallLog(ErrorLevel) {
l.write(errorLog, levelError, v)
}
}
func (l *durationLogger) Info(v ...interface{}) {
if shouldLog(InfoLevel) {
if shallLog(InfoLevel) {
l.write(infoLog, levelInfo, fmt.Sprint(v...))
}
}
func (l *durationLogger) Infof(format string, v ...interface{}) {
if shouldLog(InfoLevel) {
if shallLog(InfoLevel) {
l.write(infoLog, levelInfo, fmt.Sprintf(format, v...))
}
}
func (l *durationLogger) Infov(v interface{}) {
if shallLog(InfoLevel) {
l.write(infoLog, levelInfo, v)
}
}
func (l *durationLogger) Slow(v ...interface{}) {
if shouldLog(ErrorLevel) {
if shallLog(ErrorLevel) {
l.write(slowLog, levelSlow, fmt.Sprint(v...))
}
}
func (l *durationLogger) Slowf(format string, v ...interface{}) {
if shouldLog(ErrorLevel) {
if shallLog(ErrorLevel) {
l.write(slowLog, levelSlow, fmt.Sprintf(format, v...))
}
}
func (l *durationLogger) Slowv(v interface{}) {
if shallLog(ErrorLevel) {
l.write(slowLog, levelSlow, v)
}
}
func (l *durationLogger) WithDuration(duration time.Duration) Logger {
l.Duration = timex.ReprOfDuration(duration)
return l
}
func (l *durationLogger) write(writer io.Writer, level, content string) {
l.Timestamp = getTimestamp()
l.Level = level
l.Content = content
outputJson(writer, logEntry(*l))
func (l *durationLogger) write(writer io.Writer, level string, val interface{}) {
switch atomic.LoadUint32(&encoding) {
case plainEncodingType:
writePlainAny(writer, level, val, l.Duration)
default:
outputJson(writer, &durationLogger{
Timestamp: getTimestamp(),
Level: level,
Content: val,
Duration: l.Duration,
})
}
}
+35
View File
@@ -3,6 +3,7 @@ package logx
import (
"log"
"strings"
"sync/atomic"
"testing"
"time"
@@ -23,6 +24,13 @@ func TestWithDurationErrorf(t *testing.T) {
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
}
func TestWithDurationErrorv(t *testing.T) {
var builder strings.Builder
log.SetOutput(&builder)
WithDuration(time.Second).Errorv("foo")
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
}
func TestWithDurationInfo(t *testing.T) {
var builder strings.Builder
log.SetOutput(&builder)
@@ -30,6 +38,19 @@ func TestWithDurationInfo(t *testing.T) {
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
}
func TestWithDurationInfoConsole(t *testing.T) {
old := atomic.LoadUint32(&encoding)
atomic.StoreUint32(&encoding, plainEncodingType)
defer func() {
atomic.StoreUint32(&encoding, old)
}()
var builder strings.Builder
log.SetOutput(&builder)
WithDuration(time.Second).Info("foo")
assert.True(t, strings.Contains(builder.String(), "ms"), builder.String())
}
func TestWithDurationInfof(t *testing.T) {
var builder strings.Builder
log.SetOutput(&builder)
@@ -37,6 +58,13 @@ func TestWithDurationInfof(t *testing.T) {
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
}
func TestWithDurationInfov(t *testing.T) {
var builder strings.Builder
log.SetOutput(&builder)
WithDuration(time.Second).Infov("foo")
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
}
func TestWithDurationSlow(t *testing.T) {
var builder strings.Builder
log.SetOutput(&builder)
@@ -50,3 +78,10 @@ func TestWithDurationSlowf(t *testing.T) {
WithDuration(time.Second).WithDuration(time.Hour).Slowf("foo")
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
}
func TestWithDurationSlowv(t *testing.T) {
var builder strings.Builder
log.SetOutput(&builder)
WithDuration(time.Second).WithDuration(time.Hour).Slowv("foo")
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
}
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/syncx"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/syncx"
"github.com/zeromicro/go-zero/core/timex"
)
type limitedExecutor struct {
+62
View File
@@ -0,0 +1,62 @@
package logx
import (
"sync/atomic"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/timex"
)
func TestLimitedExecutor_logOrDiscard(t *testing.T) {
tests := []struct {
name string
threshold time.Duration
lastTime time.Duration
discarded uint32
executed bool
}{
{
name: "nil executor",
executed: true,
},
{
name: "regular",
threshold: time.Hour,
lastTime: timex.Now(),
discarded: 10,
executed: false,
},
{
name: "slow",
threshold: time.Duration(1),
lastTime: -1000,
discarded: 10,
executed: true,
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
executor := newLimitedExecutor(0)
executor.threshold = test.threshold
executor.discarded = test.discarded
executor.lastTime.Set(test.lastTime)
var run int32
executor.logOrDiscard(func() {
atomic.AddInt32(&run, 1)
})
if test.executed {
assert.Equal(t, int32(1), atomic.LoadInt32(&run))
} else {
assert.Equal(t, int32(0), atomic.LoadInt32(&run))
assert.Equal(t, test.discarded+1, atomic.LoadUint32(&executor.discarded))
}
})
}
}
+189 -49
View File
@@ -1,6 +1,7 @@
package logx
import (
"bytes"
"encoding/json"
"errors"
"fmt"
@@ -17,9 +18,9 @@ import (
"sync/atomic"
"time"
"github.com/tal-tech/go-zero/core/iox"
"github.com/tal-tech/go-zero/core/sysx"
"github.com/tal-tech/go-zero/core/timex"
"github.com/zeromicro/go-zero/core/iox"
"github.com/zeromicro/go-zero/core/sysx"
"github.com/zeromicro/go-zero/core/timex"
)
const (
@@ -31,6 +32,15 @@ const (
SevereLevel
)
const (
jsonEncodingType = iota
plainEncodingType
jsonEncoding = "json"
plainEncoding = "plain"
plainEncodingSep = '\t'
)
const (
accessFilename = "access.log"
errorFilename = "error.log"
@@ -62,15 +72,18 @@ var (
// ErrLogServiceNameNotSet is an error that indicates that the service name is not set.
ErrLogServiceNameNotSet = errors.New("log service name must be set")
timeFormat = "2006-01-02T15:04:05.000Z07"
timeFormat = "2006-01-02T15:04:05.000Z07:00"
writeConsole bool
logLevel uint32
infoLog io.WriteCloser
errorLog io.WriteCloser
severeLog io.WriteCloser
slowLog io.WriteCloser
statLog io.WriteCloser
stackLog io.Writer
encoding uint32 = jsonEncodingType
// use uint32 for atomic operations
disableStat uint32
infoLog io.WriteCloser
errorLog io.WriteCloser
severeLog io.WriteCloser
slowLog io.WriteCloser
statLog io.WriteCloser
stackLog io.Writer
once sync.Once
initialized uint32
@@ -79,10 +92,10 @@ var (
type (
logEntry struct {
Timestamp string `json:"@timestamp"`
Level string `json:"level"`
Duration string `json:"duration,omitempty"`
Content string `json:"content"`
Timestamp string `json:"@timestamp"`
Level string `json:"level"`
Duration string `json:"duration,omitempty"`
Content interface{} `json:"content"`
}
logOptions struct {
@@ -98,10 +111,13 @@ type (
Logger interface {
Error(...interface{})
Errorf(string, ...interface{})
Errorv(interface{})
Info(...interface{})
Infof(string, ...interface{})
Infov(interface{})
Slow(...interface{})
Slowf(string, ...interface{})
Slowv(interface{})
WithDuration(time.Duration) Logger
}
)
@@ -119,6 +135,12 @@ func SetUp(c LogConf) error {
if len(c.TimeFormat) > 0 {
timeFormat = c.TimeFormat
}
switch c.Encoding {
case plainEncoding:
atomic.StoreUint32(&encoding, plainEncodingType)
default:
atomic.StoreUint32(&encoding, jsonEncodingType)
}
switch c.Mode {
case consoleMode:
@@ -133,7 +155,7 @@ func SetUp(c LogConf) error {
// Alert alerts v in alert level, and the message is written to error log.
func Alert(v string) {
output(errorLog, levelAlert, v)
outputText(errorLog, levelAlert, v)
}
// Close closes the logging.
@@ -195,24 +217,29 @@ func Disable() {
})
}
// DisableStat disables the stat logs.
func DisableStat() {
atomic.StoreUint32(&disableStat, 1)
}
// Error writes v into error log.
func Error(v ...interface{}) {
ErrorCaller(1, v...)
}
// Errorf writes v with format into error log.
func Errorf(format string, v ...interface{}) {
ErrorCallerf(1, format, v...)
}
// ErrorCaller writes v with context into error log.
func ErrorCaller(callDepth int, v ...interface{}) {
errorSync(fmt.Sprint(v...), callDepth+callerInnerDepth)
errorTextSync(fmt.Sprint(v...), callDepth+callerInnerDepth)
}
// ErrorCallerf writes v with context in format into error log.
func ErrorCallerf(callDepth int, format string, v ...interface{}) {
errorSync(fmt.Sprintf(format, v...), callDepth+callerInnerDepth)
errorTextSync(fmt.Errorf(format, v...).Error(), callDepth+callerInnerDepth)
}
// Errorf writes v with format into error log.
func Errorf(format string, v ...interface{}) {
ErrorCallerf(1, format, v...)
}
// ErrorStack writes v along with call stack into error log.
@@ -227,14 +254,25 @@ func ErrorStackf(format string, v ...interface{}) {
stackSync(fmt.Sprintf(format, v...))
}
// Errorv writes v into error log with json content.
// No call stack attached, because not elegant to pack the messages.
func Errorv(v interface{}) {
errorAnySync(v)
}
// Info writes v into access log.
func Info(v ...interface{}) {
infoSync(fmt.Sprint(v...))
infoTextSync(fmt.Sprint(v...))
}
// Infof writes v with format into access log.
func Infof(format string, v ...interface{}) {
infoSync(fmt.Sprintf(format, v...))
infoTextSync(fmt.Sprintf(format, v...))
}
// Infov writes v into access log with json content.
func Infov(v interface{}) {
infoAnySync(v)
}
// Must checks if err is nil, otherwise logs the err and exits.
@@ -242,7 +280,7 @@ func Must(err error) {
if err != nil {
msg := formatWithCaller(err.Error(), 3)
log.Print(msg)
output(severeLog, levelFatal, msg)
outputText(severeLog, levelFatal, msg)
os.Exit(1)
}
}
@@ -264,12 +302,17 @@ func Severef(format string, v ...interface{}) {
// Slow writes v into slow log.
func Slow(v ...interface{}) {
slowSync(fmt.Sprint(v...))
slowTextSync(fmt.Sprint(v...))
}
// Slowf writes v with format into slow log.
func Slowf(format string, v ...interface{}) {
slowSync(fmt.Sprintf(format, v...))
slowTextSync(fmt.Sprintf(format, v...))
}
// Slowv writes v into slow log with json content.
func Slowv(v interface{}) {
slowAnySync(v)
}
// Stat writes v into stat log.
@@ -312,8 +355,14 @@ func createOutput(path string) (io.WriteCloser, error) {
options.gzipEnabled), options.gzipEnabled)
}
func errorSync(msg string, callDepth int) {
if shouldLog(ErrorLevel) {
func errorAnySync(v interface{}) {
if shallLog(ErrorLevel) {
outputAny(errorLog, levelError, v)
}
}
func errorTextSync(msg string, callDepth int) {
if shallLog(ErrorLevel) {
outputError(errorLog, msg, callDepth)
}
}
@@ -362,24 +411,49 @@ func handleOptions(opts []LogOption) {
}
}
func infoSync(msg string) {
if shouldLog(InfoLevel) {
output(infoLog, levelInfo, msg)
func infoAnySync(val interface{}) {
if shallLog(InfoLevel) {
outputAny(infoLog, levelInfo, val)
}
}
func output(writer io.Writer, level, msg string) {
info := logEntry{
Timestamp: getTimestamp(),
Level: level,
Content: msg,
func infoTextSync(msg string) {
if shallLog(InfoLevel) {
outputText(infoLog, levelInfo, msg)
}
}
func outputAny(writer io.Writer, level string, val interface{}) {
switch atomic.LoadUint32(&encoding) {
case plainEncodingType:
writePlainAny(writer, level, val)
default:
info := logEntry{
Timestamp: getTimestamp(),
Level: level,
Content: val,
}
outputJson(writer, info)
}
}
func outputText(writer io.Writer, level, msg string) {
switch atomic.LoadUint32(&encoding) {
case plainEncodingType:
writePlainText(writer, level, msg)
default:
info := logEntry{
Timestamp: getTimestamp(),
Level: level,
Content: msg,
}
outputJson(writer, info)
}
outputJson(writer, info)
}
func outputError(writer io.Writer, msg string, callDepth int) {
content := formatWithCaller(msg, callDepth)
output(writer, levelError, content)
outputText(writer, levelError, content)
}
func outputJson(writer io.Writer, info interface{}) {
@@ -481,30 +555,96 @@ func setupWithVolume(c LogConf) error {
}
func severeSync(msg string) {
if shouldLog(SevereLevel) {
output(severeLog, levelSevere, fmt.Sprintf("%s\n%s", msg, string(debug.Stack())))
if shallLog(SevereLevel) {
outputText(severeLog, levelSevere, fmt.Sprintf("%s\n%s", msg, string(debug.Stack())))
}
}
func shouldLog(level uint32) bool {
func shallLog(level uint32) bool {
return atomic.LoadUint32(&logLevel) <= level
}
func slowSync(msg string) {
if shouldLog(ErrorLevel) {
output(slowLog, levelSlow, msg)
func shallLogStat() bool {
return atomic.LoadUint32(&disableStat) == 0
}
func slowAnySync(v interface{}) {
if shallLog(ErrorLevel) {
outputAny(slowLog, levelSlow, v)
}
}
func slowTextSync(msg string) {
if shallLog(ErrorLevel) {
outputText(slowLog, levelSlow, msg)
}
}
func stackSync(msg string) {
if shouldLog(ErrorLevel) {
output(stackLog, levelError, fmt.Sprintf("%s\n%s", msg, string(debug.Stack())))
if shallLog(ErrorLevel) {
outputText(stackLog, levelError, fmt.Sprintf("%s\n%s", msg, string(debug.Stack())))
}
}
func statSync(msg string) {
if shouldLog(InfoLevel) {
output(statLog, levelStat, msg)
if shallLogStat() && shallLog(InfoLevel) {
outputText(statLog, levelStat, msg)
}
}
func writePlainAny(writer io.Writer, level string, val interface{}, fields ...string) {
switch v := val.(type) {
case string:
writePlainText(writer, level, v, fields...)
case error:
writePlainText(writer, level, v.Error(), fields...)
case fmt.Stringer:
writePlainText(writer, level, v.String(), fields...)
default:
var buf bytes.Buffer
buf.WriteString(getTimestamp())
buf.WriteByte(plainEncodingSep)
buf.WriteString(level)
for _, item := range fields {
buf.WriteByte(plainEncodingSep)
buf.WriteString(item)
}
buf.WriteByte(plainEncodingSep)
if err := json.NewEncoder(&buf).Encode(val); err != nil {
log.Println(err.Error())
return
}
buf.WriteByte('\n')
if atomic.LoadUint32(&initialized) == 0 || writer == nil {
log.Println(buf.String())
return
}
if _, err := writer.Write(buf.Bytes()); err != nil {
log.Println(err.Error())
}
}
}
func writePlainText(writer io.Writer, level, msg string, fields ...string) {
var buf bytes.Buffer
buf.WriteString(getTimestamp())
buf.WriteByte(plainEncodingSep)
buf.WriteString(level)
for _, item := range fields {
buf.WriteByte(plainEncodingSep)
buf.WriteString(item)
}
buf.WriteByte(plainEncodingSep)
buf.WriteString(msg)
buf.WriteByte('\n')
if atomic.LoadUint32(&initialized) == 0 || writer == nil {
log.Println(buf.String())
return
}
if _, err := writer.Write(buf.Bytes()); err != nil {
log.Println(err.Error())
}
}

Some files were not shown because too many files have changed in this diff Show More