Compare commits

...

89 Commits

Author SHA1 Message Date
1244c5bb4d Merge pull request #65 from unistack-org/master
merge changes from master
2021-11-24 00:59:00 +03:00
4ccc8a9c85 Merge pull request #64 from unistack-org/minor_changes
minor changes
2021-11-24 00:58:21 +03:00
8a2e84d489 minor changes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-11-24 00:57:59 +03:00
d29363b78d codec: add NewFrame helper
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-11-19 09:22:13 +03:00
734f751055 Merge pull request #63 from unistack-org/master
util/http: add type alias
2021-11-19 03:04:55 +03:00
55d8a9ee20 util/http: add type alias
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-11-19 03:04:08 +03:00
07c93042ba Merge pull request #62 from unistack-org/master
merge stable
2021-11-18 16:01:10 +03:00
b9bbfdf159 config: add watch option helper
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-11-18 15:57:14 +03:00
fbad257acc config: add helpers to load/save options (#60) 2021-11-18 15:46:30 +03:00
1829febb6e util/http: fix lint issues
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-11-09 17:07:52 +03:00
7838fa62a8 util/trie: import some code from chi router
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-11-09 16:34:05 +03:00
332803d8de update workflows
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-27 22:52:48 +03:00
11c868d476 Merge branch 'v3' 2021-10-27 22:51:58 +03:00
38d6e482d7 util/reflect: fix StructFields
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-27 22:51:35 +03:00
07d4085201 util/reflect: fix reflect methods
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-27 12:55:48 +03:00
45f30c0be3 util/reflect: ZeroFieldByPath and SetFieldByPath
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-26 14:12:37 +03:00
bcaea675a7 util/reflect: add method to zero struct field
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-25 14:41:19 +03:00
3087ba1d73 regen
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-23 23:45:53 +03:00
3f5b19497c meter: add Clone method
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-09 23:50:57 +03:00
37d937d7ae meter: add missing options
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-09 19:16:45 +03:00
7d68f2396e tracer: dont return noop from context
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-07 22:46:47 +03:00
0854a7ea72 micro: add simple test
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-07 20:59:27 +03:00
5eb0e56373 move all imports to own domain
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-02 19:55:07 +03:00
6af837fd25 fixup workflows
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-02 18:42:20 +03:00
ada59119cc util/http: add test case
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-02 18:34:22 +03:00
8abc913b28 codec: add MarshalAppend func
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-10-01 01:08:24 +03:00
3247d144a8 lint fixes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-30 21:13:13 +03:00
7b2e3cc8aa lint fixes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-30 21:00:02 +03:00
8688179acd lint fixes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-30 20:32:59 +03:00
3e40bac5f4 config: add helper funcs
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-30 01:24:16 +03:00
e3fee6f8a6 util/http: add trie case insesitive matching
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-29 13:41:47 +03:00
15c020fac5 fix lint
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-29 13:19:07 +03:00
3bc046e5d4 broker/memory: simplify code
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-29 13:10:11 +03:00
542f36cfa5 util/reflect: fix tests, lint fixes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-29 13:09:48 +03:00
8237e6a08e util/router: drop google copy of pattern matcher in favour of util/http trie
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-29 13:09:22 +03:00
ecb60e4dc5 fix lint
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-28 23:43:43 +03:00
a1999ff81c util/http: trie add more tests
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-28 01:02:28 +03:00
d0f2bc8346 util/http: add trie matching func
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-27 23:30:53 +03:00
dependabot[bot]
dd29bf457e chore(deps): bump actions/github-script from 4 to 5 (#58)
Bumps [actions/github-script](https://github.com/actions/github-script) from 4 to 5.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-27 09:33:25 +03:00
d062c248e3 codec: fieldaligment
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-22 17:09:26 +03:00
875f66d36e codec: implement proto v1 message for Frame
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-22 16:59:52 +03:00
818a0e6356 codec: add context helper funcs
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-22 01:07:27 +03:00
56e02ec463 codec: add ability to pass codec options
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-22 00:57:10 +03:00
6ca851401d update workflow
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-21 21:46:23 +03:00
bd8216b397 update workflows
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-17 07:47:23 +03:00
2b13b3f128 Revert "update workflows"
This reverts commit 9957380b6d.
2021-09-17 07:42:46 +03:00
9957380b6d update workflows
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-17 07:41:17 +03:00
e10f8c0fa0 util/id: move tests to micro-tests repo
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-16 15:31:01 +03:00
45252fe4a6 enable automerge
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-16 10:30:59 +03:00
faad082efe util/rand: add Shuffle func
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-15 17:51:25 +03:00
8ab35cbd9b update dependabot
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-12 16:17:28 +03:00
ad58ab6943 fix codeql issue
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-06 10:51:13 +03:00
0e97049e1d Create SECURITY.md 2021-09-06 10:49:18 +03:00
edb0bbf9cf add codeql
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-09-06 10:30:21 +03:00
dependabot[bot]
1b01bd22a6 build(deps): bump github.com/unistack-org/micro-proto (#57) 2021-09-06 06:56:44 +00:00
2fbaa26f0f logger: add Clone method
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-30 16:21:01 +03:00
35d3e4b332 logger: breaking changes to log level parsing
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-30 16:21:01 +03:00
dependabot[bot]
e98a93d530 build(deps): bump github.com/unistack-org/micro-proto (#56)
Bumps [github.com/unistack-org/micro-proto](https://github.com/unistack-org/micro-proto) from 0.0.5 to 0.0.8.
- [Release notes](https://github.com/unistack-org/micro-proto/releases)
- [Commits](https://github.com/unistack-org/micro-proto/compare/v0.0.5...v0.0.8)

---
updated-dependencies:
- dependency-name: github.com/unistack-org/micro-proto
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-30 16:20:10 +03:00
e3545532e8 minor changes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-21 01:00:10 +03:00
09653c2fb2 util/id: specify default size for uuid behaviour
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-20 22:48:03 +03:00
70adfeab0d fix flow
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-20 22:44:17 +03:00
a45b672c98 drop uuid and use modified nanoid
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-20 22:40:48 +03:00
4509323cae update and regen all
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-16 23:56:50 +03:00
b3f4c670d5 regen all
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-16 18:57:19 +03:00
778dd449e2 logger: add NewStdLogger and RedirectStdLogger
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-06 13:45:11 +03:00
1d16983b67 logger: add NewStdLogger that can be used as std *log.Logger
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-06 11:52:04 +03:00
f386bffd37 logger: change logger interface
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-06 02:15:57 +03:00
772bde7938 network/tunnel/broker: fix metadata compile issue
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-06 02:14:56 +03:00
ea16f5f825 config/default: not implement watcher as it cant change
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-04 16:04:58 +03:00
c2f34df493 config: minor changes to split config and watcher files
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-04 13:51:43 +03:00
efe215cd60 config/default: watcher send changes only on non nil
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-04 12:25:29 +03:00
b4f332bf0d config/default: return error on Next() call
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-04 01:15:50 +03:00
f47fbb1030 config: add jitter interval for watcher to avoid dos
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-04 00:37:56 +03:00
1e8e57a708 config/default: minor changes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-03 00:49:21 +03:00
dependabot[bot]
5d0959b0a1 build(deps): bump github.com/golang-jwt/jwt (#54)
Bumps [github.com/golang-jwt/jwt](https://github.com/golang-jwt/jwt) from 3.2.1+incompatible to 3.2.2+incompatible.
- [Release notes](https://github.com/golang-jwt/jwt/releases)
- [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md)
- [Commits](https://github.com/golang-jwt/jwt/compare/v3.2.1...v3.2.2)

---
updated-dependencies:
- dependency-name: github.com/golang-jwt/jwt
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-03 00:27:35 +03:00
fa8fb3aed7 fixes and improvements (#55)
* util/router: sync from github
* config: add watcher interface

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-03 00:24:40 +03:00
cfd2d53a79 config: cleanup tests
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-27 23:58:45 +03:00
d306f77ffc util/token/jwt: change library
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-27 23:58:29 +03:00
e5b0a7e20d server: add BatchSubscriber
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-27 23:58:06 +03:00
9a5b158b4d change jwt lib
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-27 12:43:56 +03:00
af8d81f3c6 logger: add DefaultCallerSkipCount
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-26 09:48:15 +03:00
5c9b3dae33 broker: improve option naming, move BatchBroker to Broker interface
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-24 16:16:18 +03:00
9f3957d101 client: improve option naming, add BatchPublish to noop client
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-24 16:14:42 +03:00
8fd8bdcb39 logger: fix default logger funcs
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-24 15:22:01 +03:00
80e3d239ab broker/memory: optimize
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-23 15:12:20 +03:00
419cd486cf broker/memory: cleanup
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-23 15:06:10 +03:00
e64269b2a8 broker: add BatchBroker interface to avoid breaking older brokers
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-23 12:55:36 +03:00
d18429e024 metadata: add HeaderAuthorization
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-23 12:17:00 +03:00
675e121049 metadata: add default headers
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-23 12:03:18 +03:00
203 changed files with 3405 additions and 2725 deletions

View File

@@ -11,9 +11,16 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "daily" interval: "daily"
commit-message:
prefix: "chore"
include: "scope"
# Maintain dependencies for Golang # Maintain dependencies for Golang
- package-ecosystem: "gomod" - package-ecosystem: "gomod"
directory: "/" directory: "/"
schedule: schedule:
interval: "daily" interval: "daily"
commit-message:
prefix: "chore"
include: "scope"

View File

@@ -3,6 +3,7 @@ on:
push: push:
branches: branches:
- master - master
- v3
jobs: jobs:
test: test:
name: test name: test

78
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,78 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "codeql"
on:
workflow_run:
workflows: ["prbuild"]
types:
- completed
push:
branches: [ master, v3 ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, v3 ]
schedule:
- cron: '34 1 * * 0'
jobs:
analyze:
name: analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: checkout
uses: actions/checkout@v2
- name: setup
uses: actions/setup-go@v2
with:
go-version: 1.16
# Initializes the CodeQL tools for scanning.
- name: init
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: analyze
uses: github/codeql-action/analyze@v1

View File

@@ -0,0 +1,31 @@
name: "prautomerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- name: metadata
id: metadata
uses: dependabot/fetch-metadata@v1.1.1
with:
github-token: "${{ secrets.TOKEN }}"
- name: approve
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}
- name: merge
if: ${{contains(steps.metadata.outputs.dependency-names, 'go.unistack.org')}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

View File

@@ -3,6 +3,7 @@ on:
pull_request: pull_request:
branches: branches:
- master - master
- v3
jobs: jobs:
test: test:
name: test name: test

View File

@@ -30,7 +30,7 @@ linters:
- gofmt - gofmt
- gofumpt - gofumpt
- goimports - goimports
- golint - revive
- gosec - gosec
- makezero - makezero
- misspell - misspell

15
SECURITY.md Normal file
View File

@@ -0,0 +1,15 @@
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 3.7.x | :white_check_mark: |
| < 3.7.0 | :x: |
## Reporting a Vulnerability
If you find any issue, please create github issue in this repo

View File

@@ -1,15 +1,16 @@
package api package api // import "go.unistack.org/micro/v3/api"
import ( import (
"errors" "errors"
"regexp" "regexp"
"strings" "strings"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/register" "go.unistack.org/micro/v3/register"
"github.com/unistack-org/micro/v3/server" "go.unistack.org/micro/v3/server"
) )
// nolint: revive
// Api interface // Api interface
type Api interface { type Api interface {
// Initialise options // Initialise options
@@ -125,14 +126,14 @@ func Validate(e *Endpoint) error {
ps := p[0] ps := p[0]
pe := p[len(p)-1] pe := p[len(p)-1]
if ps == '^' && pe == '$' { switch {
_, err := regexp.CompilePOSIX(p) case ps == '^' && pe == '$':
if err != nil { if _, err := regexp.CompilePOSIX(p); err != nil {
return err return err
} }
} else if ps == '^' && pe != '$' { case ps == '^' && pe != '$':
return errors.New("invalid path") return errors.New("invalid path")
} else if ps != '^' && pe == '$' { case ps != '^' && pe == '$':
return errors.New("invalid path") return errors.New("invalid path")
} }
} }

View File

@@ -1,5 +1,5 @@
// Package handler provides http handlers // Package handler provides http handlers
package handler package handler // import "go.unistack.org/micro/v3/api/handler"
import ( import (
"net/http" "net/http"

View File

@@ -1,9 +1,9 @@
package handler package handler
import ( import (
"github.com/unistack-org/micro/v3/api/router" "go.unistack.org/micro/v3/api/router"
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
) )
// DefaultMaxRecvSize specifies max recv size for handler // DefaultMaxRecvSize specifies max recv size for handler

View File

@@ -1,12 +1,12 @@
// Package grpc resolves a grpc service like /greeter.Say/Hello to greeter service // Package grpc resolves a grpc service like /greeter.Say/Hello to greeter service
package grpc package grpc // import "go.unistack.org/micro/v3/api/resolver/grpc"
import ( import (
"errors" "errors"
"net/http" "net/http"
"strings" "strings"
"github.com/unistack-org/micro/v3/api/resolver" "go.unistack.org/micro/v3/api/resolver"
) )
// Resolver struct // Resolver struct

View File

@@ -1,10 +1,10 @@
// Package host resolves using http host // Package host resolves using http host
package host package host // import "go.unistack.org/micro/v3/api/resolver/host"
import ( import (
"net/http" "net/http"
"github.com/unistack-org/micro/v3/api/resolver" "go.unistack.org/micro/v3/api/resolver"
) )
type hostResolver struct { type hostResolver struct {

View File

@@ -3,7 +3,7 @@ package resolver
import ( import (
"context" "context"
"github.com/unistack-org/micro/v3/register" "go.unistack.org/micro/v3/register"
) )
// Options struct // Options struct

View File

@@ -1,11 +1,11 @@
// Package path resolves using http path // Package path resolves using http path
package path package path // import "go.unistack.org/micro/v3/api/resolver/path"
import ( import (
"net/http" "net/http"
"strings" "strings"
"github.com/unistack-org/micro/v3/api/resolver" "go.unistack.org/micro/v3/api/resolver"
) )
// Resolver the path resolver // Resolver the path resolver

View File

@@ -1,5 +1,5 @@
// Package resolver resolves a http request to an endpoint // Package resolver resolves a http request to an endpoint
package resolver package resolver // import "go.unistack.org/micro/v3/api/resolver"
import ( import (
"errors" "errors"

View File

@@ -1,14 +1,14 @@
// Package subdomain is a resolver which uses the subdomain to determine the domain to route to. It // Package subdomain is a resolver which uses the subdomain to determine the domain to route to. It
// offloads the endpoint resolution to a child resolver which is provided in New. // offloads the endpoint resolution to a child resolver which is provided in New.
package subdomain package subdomain // import "go.unistack.org/micro/v3/api/resolver/subdomain"
import ( import (
"net" "net"
"net/http" "net/http"
"strings" "strings"
"github.com/unistack-org/micro/v3/api/resolver" "go.unistack.org/micro/v3/api/resolver"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"golang.org/x/net/publicsuffix" "golang.org/x/net/publicsuffix"
) )

View File

@@ -5,7 +5,7 @@ import (
"net/url" "net/url"
"testing" "testing"
"github.com/unistack-org/micro/v3/api/resolver/vpath" "go.unistack.org/micro/v3/api/resolver/vpath"
) )
func TestResolve(t *testing.T) { func TestResolve(t *testing.T) {

View File

@@ -1,5 +1,5 @@
// Package vpath resolves using http path and recognised versioned urls // Package vpath resolves using http path and recognised versioned urls
package vpath package vpath // import "go.unistack.org/micro/v3/api/resolver/vpath"
import ( import (
"errors" "errors"
@@ -7,7 +7,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/unistack-org/micro/v3/api/resolver" "go.unistack.org/micro/v3/api/resolver"
) )
// NewResolver creates new vpath api resolver // NewResolver creates new vpath api resolver

View File

@@ -3,10 +3,10 @@ package router
import ( import (
"context" "context"
"github.com/unistack-org/micro/v3/api/resolver" "go.unistack.org/micro/v3/api/resolver"
"github.com/unistack-org/micro/v3/api/resolver/vpath" "go.unistack.org/micro/v3/api/resolver/vpath"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/register" "go.unistack.org/micro/v3/register"
) )
// Options holds the options for api router // Options holds the options for api router

View File

@@ -1,10 +1,10 @@
// Package router provides api service routing // Package router provides api service routing
package router package router // import "go.unistack.org/micro/v3/api/router"
import ( import (
"net/http" "net/http"
"github.com/unistack-org/micro/v3/api" "go.unistack.org/micro/v3/api"
) )
// DefaultRouter contains default router implementation // DefaultRouter contains default router implementation

View File

@@ -1,12 +1,12 @@
// Package auth provides authentication and authorization capability // Package auth provides authentication and authorization capability
package auth package auth // import "go.unistack.org/micro/v3/auth"
import ( import (
"context" "context"
"errors" "errors"
"time" "time"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
const ( const (
@@ -55,7 +55,7 @@ type Auth interface {
type Account struct { type Account struct {
// Metadata any other associated metadata // Metadata any other associated metadata
Metadata metadata.Metadata `json:"metadata"` Metadata metadata.Metadata `json:"metadata"`
// ID of the account e.g. email or uuid // ID of the account e.g. email or id
ID string `json:"id"` ID string `json:"id"`
// Type of the account, e.g. service // Type of the account, e.g. service
Type string `json:"type"` Type string `json:"type"`

View File

@@ -1,7 +1,7 @@
package auth package auth
import ( import (
"github.com/google/uuid" "go.unistack.org/micro/v3/util/id"
) )
type noopAuth struct { type noopAuth struct {
@@ -61,11 +61,11 @@ func (n *noopAuth) Verify(acc *Account, res *Resource, opts ...VerifyOption) err
// Inspect a token // Inspect a token
func (n *noopAuth) Inspect(token string) (*Account, error) { func (n *noopAuth) Inspect(token string) (*Account, error) {
uid, err := uuid.NewRandom() id, err := id.New()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Account{ID: uid.String(), Issuer: n.Options().Issuer}, nil return &Account{ID: id, Issuer: n.Options().Issuer}, nil
} }
// Token generation using an account id and secret // Token generation using an account id and secret

View File

@@ -4,11 +4,11 @@ import (
"context" "context"
"time" "time"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/store" "go.unistack.org/micro/v3/store"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// NewOptions creates Options struct from slice of options // NewOptions creates Options struct from slice of options

View File

@@ -1,11 +1,11 @@
// Package broker is an interface used for asynchronous messaging // Package broker is an interface used for asynchronous messaging
package broker package broker // import "go.unistack.org/micro/v3/broker"
import ( import (
"context" "context"
"errors" "errors"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
// DefaultBroker default memory broker // DefaultBroker default memory broker
@@ -34,10 +34,10 @@ type Broker interface {
Disconnect(ctx context.Context) error Disconnect(ctx context.Context) error
// Publish message to broker topic // Publish message to broker topic
Publish(ctx context.Context, topic string, msg *Message, opts ...PublishOption) error Publish(ctx context.Context, topic string, msg *Message, opts ...PublishOption) error
// BatchPublish messages to broker with multiple topics
BatchPublish(ctx context.Context, msgs []*Message, opts ...PublishOption) error
// Subscribe subscribes to topic message via handler // Subscribe subscribes to topic message via handler
Subscribe(ctx context.Context, topic string, h Handler, opts ...SubscribeOption) (Subscriber, error) Subscribe(ctx context.Context, topic string, h Handler, opts ...SubscribeOption) (Subscriber, error)
// BatchPublish messages to broker with multiple topics
BatchPublish(ctx context.Context, msgs []*Message, opts ...PublishOption) error
// BatchSubscribe subscribes to topic messages via handler // BatchSubscribe subscribes to topic messages via handler
BatchSubscribe(ctx context.Context, topic string, h BatchHandler, opts ...SubscribeOption) (Subscriber, error) BatchSubscribe(ctx context.Context, topic string, h BatchHandler, opts ...SubscribeOption) (Subscriber, error)
// String type of broker // String type of broker
@@ -112,6 +112,13 @@ type Message struct {
Body RawMessage Body RawMessage
} }
// NewMessage create broker message with topic filled
func NewMessage(topic string) *Message {
m := &Message{Header: metadata.New(2)}
m.Header.Set(metadata.HeaderTopic, topic)
return m
}
// Subscriber is a convenience return type for the Subscribe method // Subscriber is a convenience return type for the Subscribe method
type Subscriber interface { type Subscriber interface {
// Options returns subscriber options // Options returns subscriber options

View File

@@ -4,18 +4,18 @@ import (
"context" "context"
"sync" "sync"
"github.com/google/uuid" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/metadata"
maddr "github.com/unistack-org/micro/v3/util/addr" maddr "go.unistack.org/micro/v3/util/addr"
mnet "github.com/unistack-org/micro/v3/util/net" "go.unistack.org/micro/v3/util/id"
"github.com/unistack-org/micro/v3/util/rand" mnet "go.unistack.org/micro/v3/util/net"
"go.unistack.org/micro/v3/util/rand"
) )
type memoryBroker struct { type memoryBroker struct {
subscribers map[string][]*memorySubscriber subscribers map[string][]*memorySubscriber
batchsubscribers map[string][]*memoryBatchSubscriber addr string
addr string opts Options
opts Options
sync.RWMutex sync.RWMutex
connected bool connected bool
} }
@@ -28,21 +28,13 @@ type memoryEvent struct {
} }
type memorySubscriber struct { type memorySubscriber struct {
ctx context.Context ctx context.Context
exit chan bool exit chan bool
handler Handler handler Handler
id string batchhandler BatchHandler
topic string id string
opts SubscribeOptions topic string
} opts SubscribeOptions
type memoryBatchSubscriber struct {
ctx context.Context
exit chan bool
handler BatchHandler
id string
topic string
opts SubscribeOptions
} }
func (m *memoryBroker) Options() Options { func (m *memoryBroker) Options() Options {
@@ -96,7 +88,16 @@ func (m *memoryBroker) Init(opts ...Option) error {
return nil return nil
} }
func (m *memoryBroker) Publish(ctx context.Context, topic string, msg *Message, opts ...PublishOption) error {
msg.Header.Set(metadata.HeaderTopic, topic)
return m.publish(ctx, []*Message{msg}, opts...)
}
func (m *memoryBroker) BatchPublish(ctx context.Context, msgs []*Message, opts ...PublishOption) error { func (m *memoryBroker) BatchPublish(ctx context.Context, msgs []*Message, opts ...PublishOption) error {
return m.publish(ctx, msgs, opts...)
}
func (m *memoryBroker) publish(ctx context.Context, msgs []*Message, opts ...PublishOption) error {
m.RLock() m.RLock()
if !m.connected { if !m.connected {
m.RUnlock() m.RUnlock()
@@ -104,103 +105,81 @@ func (m *memoryBroker) BatchPublish(ctx context.Context, msgs []*Message, opts .
} }
m.RUnlock() m.RUnlock()
type msgWrapper struct { var err error
topic string
body interface{}
}
vs := make([]msgWrapper, 0, len(msgs)) select {
if m.opts.Codec == nil { case <-ctx.Done():
m.RLock() return ctx.Err()
for _, msg := range msgs { default:
topic, _ := msg.Header.Get("Micro-Topic") options := NewPublishOptions(opts...)
vs = append(vs, msgWrapper{topic: topic, body: m})
}
m.RUnlock()
} else {
m.RLock()
for _, msg := range msgs {
topic, _ := msg.Header.Get("Micro-Topic")
buf, err := m.opts.Codec.Marshal(msg)
if err != nil {
m.RUnlock()
return err
}
vs = append(vs, msgWrapper{topic: topic, body: buf})
}
m.RUnlock()
}
if len(m.batchsubscribers) > 0 {
eh := m.opts.BatchErrorHandler
msgTopicMap := make(map[string]Events) msgTopicMap := make(map[string]Events)
for _, v := range vs { for _, v := range msgs {
p := &memoryEvent{ p := &memoryEvent{opts: m.opts}
topic: v.topic,
message: v.body, if m.opts.Codec == nil || options.BodyOnly {
opts: m.opts, p.topic, _ = v.Header.Get(metadata.HeaderTopic)
p.message = v.Body
} else {
p.topic, _ = v.Header.Get(metadata.HeaderTopic)
p.message, err = m.opts.Codec.Marshal(v)
if err != nil {
return err
}
} }
msgTopicMap[p.topic] = append(msgTopicMap[p.topic], p) msgTopicMap[p.topic] = append(msgTopicMap[p.topic], p)
} }
beh := m.opts.BatchErrorHandler
eh := m.opts.ErrorHandler
for t, ms := range msgTopicMap { for t, ms := range msgTopicMap {
m.RLock() m.RLock()
subs, ok := m.batchsubscribers[t] subs, ok := m.subscribers[t]
m.RUnlock() m.RUnlock()
if !ok { if !ok {
continue continue
} }
for _, sub := range subs { for _, sub := range subs {
if err := sub.handler(ms); err != nil { if sub.opts.BatchErrorHandler != nil {
ms.SetError(err) beh = sub.opts.BatchErrorHandler
if sub.opts.BatchErrorHandler != nil {
eh = sub.opts.BatchErrorHandler
}
if eh != nil {
eh(ms)
} else if m.opts.Logger.V(logger.ErrorLevel) {
m.opts.Logger.Error(m.opts.Context, err.Error())
}
} else if sub.opts.AutoAck {
if err := ms.Ack(); err != nil {
m.opts.Logger.Errorf(m.opts.Context, "ack failed: %v", err)
}
} }
}
}
}
eh := m.opts.ErrorHandler
for _, v := range vs {
p := &memoryEvent{
topic: v.topic,
message: v.body,
opts: m.opts,
}
m.RLock()
subs, ok := m.subscribers[p.topic]
m.RUnlock()
if !ok {
continue
}
for _, sub := range subs {
if err := sub.handler(p); err != nil {
p.SetError(err)
if sub.opts.ErrorHandler != nil { if sub.opts.ErrorHandler != nil {
eh = sub.opts.ErrorHandler eh = sub.opts.ErrorHandler
} }
if eh != nil {
eh(p) switch {
} else if m.opts.Logger.V(logger.ErrorLevel) { // batch processing
m.opts.Logger.Error(m.opts.Context, err.Error()) case sub.batchhandler != nil:
} if err = sub.batchhandler(ms); err != nil {
} else if sub.opts.AutoAck { ms.SetError(err)
if err := p.Ack(); err != nil { if beh != nil {
m.opts.Logger.Errorf(m.opts.Context, "ack failed: %v", err) _ = beh(ms)
} else if m.opts.Logger.V(logger.ErrorLevel) {
m.opts.Logger.Error(m.opts.Context, err.Error())
}
} else if sub.opts.AutoAck {
if err = ms.Ack(); err != nil {
m.opts.Logger.Errorf(m.opts.Context, "ack failed: %v", err)
}
}
// single processing
case sub.handler != nil:
for _, p := range ms {
if err = sub.handler(p); err != nil {
p.SetError(err)
if eh != nil {
_ = eh(p)
} else if m.opts.Logger.V(logger.ErrorLevel) {
m.opts.Logger.Error(m.opts.Context, err.Error())
}
} else if sub.opts.AutoAck {
if err = p.Ack(); err != nil {
m.opts.Logger.Errorf(m.opts.Context, "ack failed: %v", err)
}
}
}
} }
} }
} }
@@ -209,56 +188,6 @@ func (m *memoryBroker) BatchPublish(ctx context.Context, msgs []*Message, opts .
return nil return nil
} }
func (m *memoryBroker) Publish(ctx context.Context, topic string, msg *Message, opts ...PublishOption) error {
m.RLock()
if !m.connected {
m.RUnlock()
return ErrNotConnected
}
subs, ok := m.subscribers[topic]
m.RUnlock()
if !ok {
return nil
}
var v interface{}
if m.opts.Codec != nil {
buf, err := m.opts.Codec.Marshal(msg)
if err != nil {
return err
}
v = buf
} else {
v = msg
}
p := &memoryEvent{
topic: topic,
message: v,
opts: m.opts,
}
eh := m.opts.ErrorHandler
for _, sub := range subs {
if err := sub.handler(p); err != nil {
p.err = err
if sub.opts.ErrorHandler != nil {
eh = sub.opts.ErrorHandler
}
if eh != nil {
eh(p)
} else if m.opts.Logger.V(logger.ErrorLevel) {
m.opts.Logger.Error(m.opts.Context, err.Error())
}
continue
}
}
return nil
}
func (m *memoryBroker) BatchSubscribe(ctx context.Context, topic string, handler BatchHandler, opts ...SubscribeOption) (Subscriber, error) { func (m *memoryBroker) BatchSubscribe(ctx context.Context, topic string, handler BatchHandler, opts ...SubscribeOption) (Subscriber, error) {
m.RLock() m.RLock()
if !m.connected { if !m.connected {
@@ -267,43 +196,41 @@ func (m *memoryBroker) BatchSubscribe(ctx context.Context, topic string, handler
} }
m.RUnlock() m.RUnlock()
options := NewSubscribeOptions(opts...) sid, err := id.New()
id, err := uuid.NewRandom()
if err != nil { if err != nil {
return nil, err return nil, err
} }
sub := &memoryBatchSubscriber{ options := NewSubscribeOptions(opts...)
exit: make(chan bool, 1),
id: id.String(), sub := &memorySubscriber{
topic: topic, exit: make(chan bool, 1),
handler: handler, id: sid,
opts: options, topic: topic,
ctx: ctx, batchhandler: handler,
opts: options,
ctx: ctx,
} }
m.Lock() m.Lock()
m.batchsubscribers[topic] = append(m.batchsubscribers[topic], sub) m.subscribers[topic] = append(m.subscribers[topic], sub)
m.Unlock() m.Unlock()
go func() { go func() {
<-sub.exit <-sub.exit
m.Lock() m.Lock()
var newSubscribers []*memoryBatchSubscriber newSubscribers := make([]*memorySubscriber, 0, len(m.subscribers)-1)
for _, sb := range m.batchsubscribers[topic] { for _, sb := range m.subscribers[topic] {
if sb.id == sub.id { if sb.id == sub.id {
continue continue
} }
newSubscribers = append(newSubscribers, sb) newSubscribers = append(newSubscribers, sb)
} }
m.batchsubscribers[topic] = newSubscribers m.subscribers[topic] = newSubscribers
m.Unlock() m.Unlock()
}() }()
return sub, nil return sub, nil
return nil, nil
} }
func (m *memoryBroker) Subscribe(ctx context.Context, topic string, handler Handler, opts ...SubscribeOption) (Subscriber, error) { func (m *memoryBroker) Subscribe(ctx context.Context, topic string, handler Handler, opts ...SubscribeOption) (Subscriber, error) {
@@ -314,16 +241,16 @@ func (m *memoryBroker) Subscribe(ctx context.Context, topic string, handler Hand
} }
m.RUnlock() m.RUnlock()
options := NewSubscribeOptions(opts...) sid, err := id.New()
id, err := uuid.NewRandom()
if err != nil { if err != nil {
return nil, err return nil, err
} }
options := NewSubscribeOptions(opts...)
sub := &memorySubscriber{ sub := &memorySubscriber{
exit: make(chan bool, 1), exit: make(chan bool, 1),
id: id.String(), id: sid,
topic: topic, topic: topic,
handler: handler, handler: handler,
opts: options, opts: options,
@@ -337,7 +264,7 @@ func (m *memoryBroker) Subscribe(ctx context.Context, topic string, handler Hand
go func() { go func() {
<-sub.exit <-sub.exit
m.Lock() m.Lock()
var newSubscribers []*memorySubscriber newSubscribers := make([]*memorySubscriber, 0, len(m.subscribers)-1)
for _, sb := range m.subscribers[topic] { for _, sb := range m.subscribers[topic] {
if sb.id == sub.id { if sb.id == sub.id {
continue continue
@@ -393,19 +320,6 @@ func (m *memoryEvent) SetError(err error) {
m.err = err m.err = err
} }
func (m *memoryBatchSubscriber) Options() SubscribeOptions {
return m.opts
}
func (m *memoryBatchSubscriber) Topic() string {
return m.topic
}
func (m *memoryBatchSubscriber) Unsubscribe(ctx context.Context) error {
m.exit <- true
return nil
}
func (m *memorySubscriber) Options() SubscribeOptions { func (m *memorySubscriber) Options() SubscribeOptions {
return m.opts return m.opts
} }
@@ -422,8 +336,7 @@ func (m *memorySubscriber) Unsubscribe(ctx context.Context) error {
// NewBroker return new memory broker // NewBroker return new memory broker
func NewBroker(opts ...Option) Broker { func NewBroker(opts ...Option) Broker {
return &memoryBroker{ return &memoryBroker{
opts: NewOptions(opts...), opts: NewOptions(opts...),
subscribers: make(map[string][]*memorySubscriber), subscribers: make(map[string][]*memorySubscriber),
batchsubscribers: make(map[string][]*memoryBatchSubscriber),
} }
} }

View File

@@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
"testing" "testing"
"go.unistack.org/micro/v3/metadata"
) )
func TestMemoryBatchBroker(t *testing.T) { func TestMemoryBatchBroker(t *testing.T) {
@@ -26,13 +28,13 @@ func TestMemoryBatchBroker(t *testing.T) {
t.Fatalf("Unexpected error subscribing %v", err) t.Fatalf("Unexpected error subscribing %v", err)
} }
msgs := make([]*Message, 0, 0) msgs := make([]*Message, 0, count)
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
message := &Message{ message := &Message{
Header: map[string]string{ Header: map[string]string{
"Micro-Topic": topic, metadata.HeaderTopic: topic,
"foo": "bar", "foo": "bar",
"id": fmt.Sprintf("%d", i), "id": fmt.Sprintf("%d", i),
}, },
Body: []byte(`"hello world"`), Body: []byte(`"hello world"`),
} }
@@ -51,6 +53,7 @@ func TestMemoryBatchBroker(t *testing.T) {
t.Fatalf("Unexpected connect error %v", err) t.Fatalf("Unexpected connect error %v", err)
} }
} }
func TestMemoryBroker(t *testing.T) { func TestMemoryBroker(t *testing.T) {
b := NewBroker() b := NewBroker()
ctx := context.Background() ctx := context.Background()
@@ -71,13 +74,13 @@ func TestMemoryBroker(t *testing.T) {
t.Fatalf("Unexpected error subscribing %v", err) t.Fatalf("Unexpected error subscribing %v", err)
} }
msgs := make([]*Message, 0, 0) msgs := make([]*Message, 0, count)
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
message := &Message{ message := &Message{
Header: map[string]string{ Header: map[string]string{
"Micro-Topic": topic, metadata.HeaderTopic: topic,
"foo": "bar", "foo": "bar",
"id": fmt.Sprintf("%d", i), "id": fmt.Sprintf("%d", i),
}, },
Body: []byte(`"hello world"`), Body: []byte(`"hello world"`),
} }

View File

@@ -3,12 +3,13 @@ package broker
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"time"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/register" "go.unistack.org/micro/v3/register"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Options struct // Options struct
@@ -73,11 +74,9 @@ func NewPublishOptions(opts ...PublishOption) PublishOptions {
options := PublishOptions{ options := PublishOptions{
Context: context.Background(), Context: context.Background(),
} }
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
} }
return options return options
} }
@@ -95,6 +94,10 @@ type SubscribeOptions struct {
AutoAck bool AutoAck bool
// BodyOnly flag specifies that message contains only body bytes without header // BodyOnly flag specifies that message contains only body bytes without header
BodyOnly bool BodyOnly bool
// BatchSize flag specifies max batch size
BatchSize int
// BatchWait flag specifies max wait time for batch filling
BatchWait time.Duration
} }
// Option func // Option func
@@ -117,23 +120,6 @@ func PublishContext(ctx context.Context) PublishOption {
} }
} }
// SubscribeOption func
type SubscribeOption func(*SubscribeOptions)
// NewSubscribeOptions creates new SubscribeOptions
func NewSubscribeOptions(opts ...SubscribeOption) SubscribeOptions {
options := SubscribeOptions{
AutoAck: true,
Context: context.Background(),
}
for _, o := range opts {
o(&options)
}
return options
}
// Addrs sets the host addresses to be used by the broker // Addrs sets the host addresses to be used by the broker
func Addrs(addrs ...string) Option { func Addrs(addrs ...string) Option {
return func(o *Options) { return func(o *Options) {
@@ -149,28 +135,6 @@ func Codec(c codec.Codec) Option {
} }
} }
// DisableAutoAck disables auto ack
func DisableAutoAck() SubscribeOption {
return func(o *SubscribeOptions) {
o.AutoAck = false
}
}
// SubscribeAutoAck will disable auto acking of messages
// after they have been handled.
func SubscribeAutoAck(b bool) SubscribeOption {
return func(o *SubscribeOptions) {
o.AutoAck = b
}
}
// SubscribeBodyOnly consumes only body of the message
func SubscribeBodyOnly(b bool) SubscribeOption {
return func(o *SubscribeOptions) {
o.BodyOnly = b
}
}
// ErrorHandler will catch all broker errors that cant be handled // ErrorHandler will catch all broker errors that cant be handled
// in normal way, for example Codec errors // in normal way, for example Codec errors
func ErrorHandler(h Handler) Option { func ErrorHandler(h Handler) Option {
@@ -266,3 +230,55 @@ func SubscribeContext(ctx context.Context) SubscribeOption {
o.Context = ctx o.Context = ctx
} }
} }
// DisableAutoAck disables auto ack
// Deprecated
func DisableAutoAck() SubscribeOption {
return func(o *SubscribeOptions) {
o.AutoAck = false
}
}
// SubscribeAutoAck contol auto acking of messages
// after they have been handled.
func SubscribeAutoAck(b bool) SubscribeOption {
return func(o *SubscribeOptions) {
o.AutoAck = b
}
}
// SubscribeBodyOnly consumes only body of the message
func SubscribeBodyOnly(b bool) SubscribeOption {
return func(o *SubscribeOptions) {
o.BodyOnly = b
}
}
// SubscribeBatchSize specifies max batch size
func SubscribeBatchSize(n int) SubscribeOption {
return func(o *SubscribeOptions) {
o.BatchSize = n
}
}
// SubscribeBatchWait specifies max batch wait time
func SubscribeBatchWait(td time.Duration) SubscribeOption {
return func(o *SubscribeOptions) {
o.BatchWait = td
}
}
// SubscribeOption func
type SubscribeOption func(*SubscribeOptions)
// NewSubscribeOptions creates new SubscribeOptions
func NewSubscribeOptions(opts ...SubscribeOption) SubscribeOptions {
options := SubscribeOptions{
AutoAck: true,
Context: context.Background(),
}
for _, o := range opts {
o(&options)
}
return options
}

View File

@@ -1,5 +1,5 @@
// Package build is for building source into a package // Package build is for building source into a package
package build package build // import "go.unistack.org/micro/v3/build"
// Build is an interface for building packages // Build is an interface for building packages
type Build interface { type Build interface {

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"time" "time"
"github.com/unistack-org/micro/v3/util/backoff" "go.unistack.org/micro/v3/util/backoff"
) )
// BackoffFunc is the backoff call func // BackoffFunc is the backoff call func

View File

@@ -1,12 +1,12 @@
// Package client is an interface for an RPC client // Package client is an interface for an RPC client
package client package client // import "go.unistack.org/micro/v3/client"
import ( import (
"context" "context"
"time" "time"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
var ( var (
@@ -40,6 +40,7 @@ type Client interface {
Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error
Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error)
Publish(ctx context.Context, msg Message, opts ...PublishOption) error Publish(ctx context.Context, msg Message, opts ...PublishOption) error
BatchPublish(ctx context.Context, msg []Message, opts ...PublishOption) error
String() string String() string
} }

View File

@@ -4,8 +4,8 @@ import (
"context" "context"
"sort" "sort"
"github.com/unistack-org/micro/v3/errors" "go.unistack.org/micro/v3/errors"
"github.com/unistack-org/micro/v3/router" "go.unistack.org/micro/v3/router"
) )
// LookupFunc is used to lookup routes for a service // LookupFunc is used to lookup routes for a service

View File

@@ -3,10 +3,10 @@ package client
import ( import (
"context" "context"
"github.com/unistack-org/micro/v3/broker" "go.unistack.org/micro/v3/broker"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/errors" "go.unistack.org/micro/v3/errors"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
// DefaultCodecs will be used to encode/decode data // DefaultCodecs will be used to encode/decode data
@@ -173,7 +173,7 @@ func (n *noopClient) NewRequest(service, endpoint string, req interface{}, opts
} }
func (n *noopClient) NewMessage(topic string, msg interface{}, opts ...MessageOption) Message { func (n *noopClient) NewMessage(topic string, msg interface{}, opts ...MessageOption) Message {
options := NewMessageOptions(opts...) options := NewMessageOptions(append([]MessageOption{MessageContentType(n.opts.ContentType)}, opts...)...)
return &noopMessage{topic: topic, payload: msg, opts: options} return &noopMessage{topic: topic, payload: msg, opts: options}
} }
@@ -181,47 +181,59 @@ func (n *noopClient) Stream(ctx context.Context, req Request, opts ...CallOption
return &noopStream{}, nil return &noopStream{}, nil
} }
func (n *noopClient) Publish(ctx context.Context, p Message, opts ...PublishOption) error { func (n *noopClient) BatchPublish(ctx context.Context, ps []Message, opts ...PublishOption) error {
var body []byte return n.publish(ctx, ps, opts...)
}
func (n *noopClient) Publish(ctx context.Context, p Message, opts ...PublishOption) error {
return n.publish(ctx, []Message{p}, opts...)
}
func (n *noopClient) publish(ctx context.Context, ps []Message, opts ...PublishOption) error {
options := NewPublishOptions(opts...) options := NewPublishOptions(opts...)
md, ok := metadata.FromOutgoingContext(ctx) msgs := make([]*broker.Message, 0, len(ps))
if !ok {
md = metadata.New(0)
}
md["Content-Type"] = p.ContentType()
md["Micro-Topic"] = p.Topic()
// passed in raw data for _, p := range ps {
if d, ok := p.Payload().(*codec.Frame); ok { md, ok := metadata.FromOutgoingContext(ctx)
body = d.Data if !ok {
} else { md = metadata.New(0)
// use codec for payload }
cf, err := n.newCodec(p.ContentType()) md[metadata.HeaderContentType] = p.ContentType()
if err != nil {
return errors.InternalServerError("go.micro.client", err.Error()) topic := p.Topic()
// get the exchange
if len(options.Exchange) > 0 {
topic = options.Exchange
} }
// set the body md[metadata.HeaderTopic] = topic
b, err := cf.Marshal(p.Payload())
if err != nil { var body []byte
return errors.InternalServerError("go.micro.client", err.Error())
// passed in raw data
if d, ok := p.Payload().(*codec.Frame); ok {
body = d.Data
} else {
// use codec for payload
cf, err := n.newCodec(p.ContentType())
if err != nil {
return errors.InternalServerError("go.micro.client", err.Error())
}
// set the body
b, err := cf.Marshal(p.Payload())
if err != nil {
return errors.InternalServerError("go.micro.client", err.Error())
}
body = b
} }
body = b
msgs = append(msgs, &broker.Message{Header: md, Body: body})
} }
topic := p.Topic() return n.opts.Broker.BatchPublish(ctx, msgs,
// get the exchange
if len(options.Exchange) > 0 {
topic = options.Exchange
}
return n.opts.Broker.Publish(ctx, topic, &broker.Message{
Header: md,
Body: body,
},
broker.PublishContext(options.Context), broker.PublishContext(options.Context),
broker.PublishBodyOnly(options.BodyOnly), broker.PublishBodyOnly(options.BodyOnly),
) )

View File

@@ -5,20 +5,22 @@ import (
"crypto/tls" "crypto/tls"
"time" "time"
"github.com/unistack-org/micro/v3/broker" "go.unistack.org/micro/v3/broker"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/network/transport" "go.unistack.org/micro/v3/network/transport"
"github.com/unistack-org/micro/v3/register" "go.unistack.org/micro/v3/register"
"github.com/unistack-org/micro/v3/router" "go.unistack.org/micro/v3/router"
"github.com/unistack-org/micro/v3/selector" "go.unistack.org/micro/v3/selector"
"github.com/unistack-org/micro/v3/selector/random" "go.unistack.org/micro/v3/selector/random"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Options holds client options // Options holds client options
type Options struct { type Options struct {
// Transport used for transfer messages
Transport transport.Transport
// Selector used to select needed address // Selector used to select needed address
Selector selector.Selector Selector selector.Selector
// Logger used to log messages // Logger used to log messages
@@ -29,18 +31,16 @@ type Options struct {
Broker broker.Broker Broker broker.Broker
// Meter used for metrics // Meter used for metrics
Meter meter.Meter Meter meter.Meter
// Router used to get route
Router router.Router
// Transport used for transfer messages
Transport transport.Transport
// Context is used for external options // Context is used for external options
Context context.Context Context context.Context
// Lookup func used to get destination addr // Router used to get route
Lookup LookupFunc Router router.Router
// Codecs map
Codecs map[string]codec.Codec
// TLSConfig specifies tls.Config for secure connection // TLSConfig specifies tls.Config for secure connection
TLSConfig *tls.Config TLSConfig *tls.Config
// Codecs map
Codecs map[string]codec.Codec
// Lookup func used to get destination addr
Lookup LookupFunc
// Proxy is used for proxy requests // Proxy is used for proxy requests
Proxy string Proxy string
// ContentType is used to select codec // ContentType is used to select codec
@@ -68,12 +68,12 @@ func NewCallOptions(opts ...CallOption) CallOptions {
// CallOptions holds client call options // CallOptions holds client call options
type CallOptions struct { type CallOptions struct {
// Router used for route
Router router.Router
// Selector selects addr // Selector selects addr
Selector selector.Selector Selector selector.Selector
// Context used for deadline // Context used for deadline
Context context.Context Context context.Context
// Router used for route
Router router.Router
// Retry func used for retries // Retry func used for retries
Retry RetryFunc Retry RetryFunc
// Backoff func used for backoff when retry // Backoff func used for backoff when retry
@@ -82,22 +82,22 @@ type CallOptions struct {
Network string Network string
// Content-Type // Content-Type
ContentType string ContentType string
// CallWrappers call wrappers // AuthToken string
CallWrappers []CallWrapper AuthToken string
// SelectOptions selector options
SelectOptions []selector.SelectOption
// Address specifies static addr list // Address specifies static addr list
Address []string Address []string
// Retries specifies retries num // SelectOptions selector options
Retries int SelectOptions []selector.SelectOption
// CallWrappers call wrappers
CallWrappers []CallWrapper
// StreamTimeout stream timeout // StreamTimeout stream timeout
StreamTimeout time.Duration StreamTimeout time.Duration
// RequestTimeout request timeout // RequestTimeout request timeout
RequestTimeout time.Duration RequestTimeout time.Duration
// DialTimeout dial timeout // DialTimeout dial timeout
DialTimeout time.Duration DialTimeout time.Duration
// AuthToken string // Retries specifies retries num
AuthToken string Retries int
} }
// Context pass context to client // Context pass context to client
@@ -118,12 +118,12 @@ func NewPublishOptions(opts ...PublishOption) PublishOptions {
// PublishOptions holds publish options // PublishOptions holds publish options
type PublishOptions struct { type PublishOptions struct {
// BodyOnly will publish only message body
BodyOnly bool
// Context used for external options // Context used for external options
Context context.Context Context context.Context
// Exchange topic exchange name // Exchange topic exchange name
Exchange string Exchange string
// BodyOnly will publish only message body
BodyOnly bool
} }
// NewMessageOptions creates message options struct // NewMessageOptions creates message options struct
@@ -267,7 +267,7 @@ func Transport(t transport.Transport) Option {
func Register(r register.Register) Option { func Register(r register.Register) Option {
return func(o *Options) { return func(o *Options) {
if o.Router != nil { if o.Router != nil {
o.Router.Init(router.Register(r)) _ = o.Router.Init(router.Register(r))
} }
} }
} }
@@ -331,7 +331,7 @@ func TLSConfig(t *tls.Config) Option {
// already set. Required for Init call below. // already set. Required for Init call below.
// set the transport tls // set the transport tls
o.Transport.Init( _ = o.Transport.Init(
transport.TLSConfig(t), transport.TLSConfig(t),
) )
} }
@@ -373,19 +373,35 @@ func DialTimeout(d time.Duration) Option {
} }
// WithExchange sets the exchange to route a message through // WithExchange sets the exchange to route a message through
// Deprecated
func WithExchange(e string) PublishOption { func WithExchange(e string) PublishOption {
return func(o *PublishOptions) { return func(o *PublishOptions) {
o.Exchange = e o.Exchange = e
} }
} }
// PublishExchange sets the exchange to route a message through
func PublishExchange(e string) PublishOption {
return func(o *PublishOptions) {
o.Exchange = e
}
}
// WithBodyOnly publish only message body // WithBodyOnly publish only message body
// DERECATED
func WithBodyOnly(b bool) PublishOption { func WithBodyOnly(b bool) PublishOption {
return func(o *PublishOptions) { return func(o *PublishOptions) {
o.BodyOnly = b o.BodyOnly = b
} }
} }
// PublishBodyOnly publish only message body
func PublishBodyOnly(b bool) PublishOption {
return func(o *PublishOptions) {
o.BodyOnly = b
}
}
// PublishContext sets the context in publish options // PublishContext sets the context in publish options
func PublishContext(ctx context.Context) PublishOption { func PublishContext(ctx context.Context) PublishOption {
return func(o *PublishOptions) { return func(o *PublishOptions) {
@@ -498,12 +514,20 @@ func WithSelectOptions(sops ...selector.SelectOption) CallOption {
} }
// WithMessageContentType sets the message content type // WithMessageContentType sets the message content type
// Deprecated
func WithMessageContentType(ct string) MessageOption { func WithMessageContentType(ct string) MessageOption {
return func(o *MessageOptions) { return func(o *MessageOptions) {
o.ContentType = ct o.ContentType = ct
} }
} }
// MessageContentType sets the message content type
func MessageContentType(ct string) MessageOption {
return func(o *MessageOptions) {
o.ContentType = ct
}
}
// StreamingRequest specifies that request is streaming // StreamingRequest specifies that request is streaming
func StreamingRequest(b bool) RequestOption { func StreamingRequest(b bool) RequestOption {
return func(o *RequestOptions) { return func(o *RequestOptions) {

View File

@@ -3,7 +3,7 @@ package client
import ( import (
"context" "context"
"github.com/unistack-org/micro/v3/errors" "go.unistack.org/micro/v3/errors"
) )
// RetryFunc that returning either false or a non-nil error will result in the call not being retried // RetryFunc that returning either false or a non-nil error will result in the call not being retried

View File

@@ -1,7 +1,7 @@
package client package client
import ( import (
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
) )
type testRequest struct { type testRequest struct {

View File

@@ -1,11 +1,11 @@
// Package codec is an interface for encoding messages // Package codec is an interface for encoding messages
package codec package codec // import "go.unistack.org/micro/v3/codec"
import ( import (
"errors" "errors"
"io" "io"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
// Message types // Message types
@@ -25,7 +25,7 @@ var (
var ( var (
// DefaultMaxMsgSize specifies how much data codec can handle // DefaultMaxMsgSize specifies how much data codec can handle
DefaultMaxMsgSize int = 1024 * 1024 * 4 // 4Mb DefaultMaxMsgSize = 1024 * 1024 * 4 // 4Mb
// DefaultCodec is the global default codec // DefaultCodec is the global default codec
DefaultCodec Codec = NewCodec() DefaultCodec Codec = NewCodec()
// DefaultTagName specifies struct tag name to control codec Marshal/Unmarshal // DefaultTagName specifies struct tag name to control codec Marshal/Unmarshal
@@ -41,11 +41,11 @@ type MessageType int
// connection. ReadBody may be called with a nil argument to force the // connection. ReadBody may be called with a nil argument to force the
// body to be read and discarded. // body to be read and discarded.
type Codec interface { type Codec interface {
ReadHeader(io.Reader, *Message, MessageType) error ReadHeader(r io.Reader, m *Message, mt MessageType) error
ReadBody(io.Reader, interface{}) error ReadBody(r io.Reader, v interface{}) error
Write(io.Writer, *Message, interface{}) error Write(w io.Writer, m *Message, v interface{}) error
Marshal(interface{}) ([]byte, error) Marshal(v interface{}, opts ...Option) ([]byte, error)
Unmarshal([]byte, interface{}) error Unmarshal(b []byte, v interface{}, opts ...Option) error
String() string String() string
} }
@@ -58,7 +58,7 @@ type Message struct {
Method string Method string
Endpoint string Endpoint string
Error string Error string
Id string ID string
Body []byte Body []byte
Type MessageType Type MessageType
} }
@@ -67,3 +67,20 @@ type Message struct {
func NewMessage(t MessageType) *Message { func NewMessage(t MessageType) *Message {
return &Message{Type: t, Header: metadata.New(0)} return &Message{Type: t, Header: metadata.New(0)}
} }
// MarshalAppend calls codec.Marshal(v) and returns the data appended to buf.
// If codec implements MarshalAppend, that is called instead.
func MarshalAppend(buf []byte, c Codec, v interface{}, opts ...Option) ([]byte, error) {
if nc, ok := c.(interface {
MarshalAppend([]byte, interface{}, ...Option) ([]byte, error)
}); ok {
return nc.MarshalAppend(buf, v, opts...)
}
mbuf, err := c.Marshal(v, opts...)
if err != nil {
return nil, err
}
return append(buf, mbuf...), nil
}

34
codec/context.go Normal file
View File

@@ -0,0 +1,34 @@
package codec
import (
"context"
)
type codecKey struct{}
// FromContext returns codec from context
func FromContext(ctx context.Context) (Codec, bool) {
if ctx == nil {
return nil, false
}
c, ok := ctx.Value(codecKey{}).(Codec)
return c, ok
}
// NewContext put codec in context
func NewContext(ctx context.Context, c Codec) context.Context {
if ctx == nil {
ctx = context.Background()
}
return context.WithValue(ctx, codecKey{}, c)
}
// SetOption returns a function to setup a context with given value
func SetOption(k, v interface{}) Option {
return func(o *Options) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, k, v)
}
}

View File

@@ -4,3 +4,42 @@ package codec
type Frame struct { type Frame struct {
Data []byte Data []byte
} }
// NewFrame returns new frame with data
func NewFrame(data []byte) *Frame {
return &Frame{Data: data}
}
// MarshalJSON returns frame data
func (m *Frame) MarshalJSON() ([]byte, error) {
return m.Marshal()
}
// UnmarshalJSON set frame data
func (m *Frame) UnmarshalJSON(data []byte) error {
return m.Unmarshal(data)
}
// ProtoMessage noop func
func (m *Frame) ProtoMessage() {}
// Reset resets frame
func (m *Frame) Reset() {
*m = Frame{}
}
// String returns frame as string
func (m *Frame) String() string {
return string(m.Data)
}
// Marshal returns frame data
func (m *Frame) Marshal() ([]byte, error) {
return m.Data, nil
}
// Unmarshal set frame data
func (m *Frame) Unmarshal(data []byte) error {
m.Data = data
return nil
}

View File

@@ -17,7 +17,7 @@ syntax = "proto3";
package micro.codec; package micro.codec;
option cc_enable_arenas = true; option cc_enable_arenas = true;
option go_package = "github.com/unistack-org/micro/v3/codec;codec"; option go_package = "go.unistack.org/micro/v3/codec;codec";
option java_multiple_files = true; option java_multiple_files = true;
option java_outer_classname = "MicroCodec"; option java_outer_classname = "MicroCodec";
option java_package = "micro.codec"; option java_package = "micro.codec";

View File

@@ -5,7 +5,9 @@ import (
"io" "io"
) )
type noopCodec struct{} type noopCodec struct {
opts Options
}
func (c *noopCodec) ReadHeader(conn io.Reader, m *Message, t MessageType) error { func (c *noopCodec) ReadHeader(conn io.Reader, m *Message, t MessageType) error {
return nil return nil
@@ -69,11 +71,11 @@ func (c *noopCodec) String() string {
} }
// NewCodec returns new noop codec // NewCodec returns new noop codec
func NewCodec() Codec { func NewCodec(opts ...Option) Codec {
return &noopCodec{} return &noopCodec{opts: NewOptions(opts...)}
} }
func (c *noopCodec) Marshal(v interface{}) ([]byte, error) { func (c *noopCodec) Marshal(v interface{}, opts ...Option) ([]byte, error) {
if v == nil { if v == nil {
return nil, nil return nil, nil
} }
@@ -96,7 +98,7 @@ func (c *noopCodec) Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v) return json.Marshal(v)
} }
func (c *noopCodec) Unmarshal(d []byte, v interface{}) error { func (c *noopCodec) Unmarshal(d []byte, v interface{}, opts ...Option) error {
if v == nil { if v == nil {
return nil return nil
} }

View File

@@ -1,9 +1,11 @@
package codec package codec
import ( import (
"github.com/unistack-org/micro/v3/logger" "context"
"github.com/unistack-org/micro/v3/meter"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/logger"
"go.unistack.org/micro/v3/meter"
"go.unistack.org/micro/v3/tracer"
) )
// Option func // Option func
@@ -17,6 +19,10 @@ type Options struct {
Logger logger.Logger Logger logger.Logger
// Tracer used for tracing // Tracer used for tracing
Tracer tracer.Tracer Tracer tracer.Tracer
// Context stores additional codec options
Context context.Context
// TagName specifies tag name in struct to control codec
TagName string
// MaxMsgSize specifies max messages size that reads by codec // MaxMsgSize specifies max messages size that reads by codec
MaxMsgSize int MaxMsgSize int
} }
@@ -28,6 +34,13 @@ func MaxMsgSize(n int) Option {
} }
} }
// TagName sets the codec tag name in struct
func TagName(n string) Option {
return func(o *Options) {
o.TagName = n
}
}
// Logger sets the logger // Logger sets the logger
func Logger(l logger.Logger) Option { func Logger(l logger.Logger) Option {
return func(o *Options) { return func(o *Options) {
@@ -52,10 +65,12 @@ func Meter(m meter.Meter) Option {
// NewOptions returns new options // NewOptions returns new options
func NewOptions(opts ...Option) Options { func NewOptions(opts ...Option) Options {
options := Options{ options := Options{
Context: context.Background(),
Logger: logger.DefaultLogger, Logger: logger.DefaultLogger,
Meter: meter.DefaultMeter, Meter: meter.DefaultMeter,
Tracer: tracer.DefaultTracer, Tracer: tracer.DefaultTracer,
MaxMsgSize: DefaultMaxMsgSize, MaxMsgSize: DefaultMaxMsgSize,
TagName: DefaultTagName,
} }
for _, o := range opts { for _, o := range opts {

View File

@@ -1,14 +1,21 @@
// Package config is an interface for dynamic configuration. // Package config is an interface for dynamic configuration.
package config package config // import "go.unistack.org/micro/v3/config"
import ( import (
"context" "context"
"errors" "errors"
"time"
) )
// DefaultConfig default config // DefaultConfig default config
var DefaultConfig Config = NewConfig() var DefaultConfig Config = NewConfig()
// DefaultWatcherMinInterval default min interval for poll changes
var DefaultWatcherMinInterval = 5 * time.Second
// DefaultWatcherMaxInterval default max interval for poll changes
var DefaultWatcherMaxInterval = 9 * time.Second
var ( var (
// ErrCodecMissing is returned when codec needed and not specified // ErrCodecMissing is returned when codec needed and not specified
ErrCodecMissing = errors.New("codec missing") ErrCodecMissing = errors.New("codec missing")
@@ -30,15 +37,17 @@ type Config interface {
Load(context.Context, ...LoadOption) error Load(context.Context, ...LoadOption) error
// Save config to sources // Save config to sources
Save(context.Context, ...SaveOption) error Save(context.Context, ...SaveOption) error
// Watch a value for changes // Watch a config for changes
//Watch(context.Context) (Watcher, error) Watch(context.Context, ...WatchOption) (Watcher, error)
// String returns config type name // String returns config type name
String() string String() string
} }
// Watcher is the config watcher // Watcher is the config watcher
type Watcher interface { type Watcher interface {
// Next() (, error) // Next blocks until update happens or error returned
Next() (map[string]interface{}, error)
// Stop stops watcher
Stop() error Stop() error
} }
@@ -55,3 +64,53 @@ func Load(ctx context.Context, cs []Config, opts ...LoadOption) error {
} }
return nil return nil
} }
var (
DefaultAfterLoad = func(ctx context.Context, c Config) error {
for _, fn := range c.Options().AfterLoad {
if err := fn(ctx, c); err != nil {
c.Options().Logger.Errorf(ctx, "%s AfterLoad err: %v", c.String(), err)
if !c.Options().AllowFail {
return err
}
}
}
return nil
}
DefaultAfterSave = func(ctx context.Context, c Config) error {
for _, fn := range c.Options().AfterSave {
if err := fn(ctx, c); err != nil {
c.Options().Logger.Errorf(ctx, "%s AfterSave err: %v", c.String(), err)
if !c.Options().AllowFail {
return err
}
}
}
return nil
}
DefaultBeforeLoad = func(ctx context.Context, c Config) error {
for _, fn := range c.Options().BeforeLoad {
if err := fn(ctx, c); err != nil {
c.Options().Logger.Errorf(ctx, "%s BeforeLoad err: %v", c.String(), err)
if !c.Options().AllowFail {
return err
}
}
}
return nil
}
DefaultBeforeSave = func(ctx context.Context, c Config) error {
for _, fn := range c.Options().BeforeSave {
if err := fn(ctx, c); err != nil {
c.Options().Logger.Errorf(ctx, "%s BeforeSavec err: %v", c.String(), err)
if !c.Options().AllowFail {
return err
}
}
}
return nil
}
)

View File

@@ -32,3 +32,33 @@ func SetOption(k, v interface{}) Option {
o.Context = context.WithValue(o.Context, k, v) o.Context = context.WithValue(o.Context, k, v)
} }
} }
// SetSaveOption returns a function to setup a context with given value
func SetSaveOption(k, v interface{}) SaveOption {
return func(o *SaveOptions) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, k, v)
}
}
// SetLoadOption returns a function to setup a context with given value
func SetLoadOption(k, v interface{}) LoadOption {
return func(o *LoadOptions) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, k, v)
}
}
// SetWatchOption returns a function to setup a context with given value
func SetWatchOption(k, v interface{}) WatchOption {
return func(o *WatchOptions) {
if o.Context == nil {
o.Context = context.Background()
}
o.Context = context.WithValue(o.Context, k, v)
}
}

View File

@@ -2,12 +2,13 @@ package config
import ( import (
"context" "context"
"fmt"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"github.com/imdario/mergo" "github.com/imdario/mergo"
rutil "github.com/unistack-org/micro/v3/util/reflect" rutil "go.unistack.org/micro/v3/util/reflect"
) )
type defaultConfig struct { type defaultConfig struct {
@@ -26,10 +27,8 @@ func (c *defaultConfig) Init(opts ...Option) error {
} }
func (c *defaultConfig) Load(ctx context.Context, opts ...LoadOption) error { func (c *defaultConfig) Load(ctx context.Context, opts ...LoadOption) error {
for _, fn := range c.opts.BeforeLoad { if err := DefaultBeforeLoad(ctx, c); err != nil {
if err := fn(ctx, c); err != nil && !c.opts.AllowFail { return err
return err
}
} }
options := NewLoadOptions(opts...) options := NewLoadOptions(opts...)
@@ -41,29 +40,39 @@ func (c *defaultConfig) Load(ctx context.Context, opts ...LoadOption) error {
mopts = append(mopts, mergo.WithAppendSlice) mopts = append(mopts, mergo.WithAppendSlice)
} }
src, err := rutil.Zero(c.opts.Struct) dst := c.opts.Struct
if err == nil { if options.Struct != nil {
valueOf := reflect.ValueOf(src) dst = options.Struct
if err = c.fillValues(valueOf); err == nil {
err = mergo.Merge(c.opts.Struct, src, mopts...)
}
} }
if err != nil && !c.opts.AllowFail { src, err := rutil.Zero(dst)
return err if err != nil {
} if !c.opts.AllowFail {
for _, fn := range c.opts.AfterLoad {
if err := fn(ctx, c); err != nil && !c.opts.AllowFail {
return err return err
} }
return DefaultAfterLoad(ctx, c)
}
if err = fillValues(reflect.ValueOf(src), c.opts.StructTag); err == nil {
err = mergo.Merge(dst, src, mopts...)
}
if err != nil {
c.opts.Logger.Errorf(ctx, "default load error: %v", err)
if !c.opts.AllowFail {
return err
}
}
if err := DefaultAfterLoad(ctx, c); err != nil {
return err
} }
return nil return nil
} }
//nolint:gocyclo //nolint:gocyclo
func (c *defaultConfig) fillValue(value reflect.Value, val string) error { func fillValue(value reflect.Value, val string) error {
if !rutil.IsEmpty(value) { if !rutil.IsEmpty(value) {
return nil return nil
} }
@@ -80,10 +89,10 @@ func (c *defaultConfig) fillValue(value reflect.Value, val string) error {
kv := strings.FieldsFunc(nval, func(c rune) bool { return c == '=' }) kv := strings.FieldsFunc(nval, func(c rune) bool { return c == '=' })
mkey := reflect.Indirect(reflect.New(kt)) mkey := reflect.Indirect(reflect.New(kt))
mval := reflect.Indirect(reflect.New(et)) mval := reflect.Indirect(reflect.New(et))
if err := c.fillValue(mkey, kv[0]); err != nil { if err := fillValue(mkey, kv[0]); err != nil {
return err return err
} }
if err := c.fillValue(mval, kv[1]); err != nil { if err := fillValue(mval, kv[1]); err != nil {
return err return err
} }
value.SetMapIndex(mkey, mval) value.SetMapIndex(mkey, mval)
@@ -93,7 +102,7 @@ func (c *defaultConfig) fillValue(value reflect.Value, val string) error {
value.Set(reflect.MakeSlice(reflect.SliceOf(value.Type().Elem()), len(nvals), len(nvals))) value.Set(reflect.MakeSlice(reflect.SliceOf(value.Type().Elem()), len(nvals), len(nvals)))
for idx, nval := range nvals { for idx, nval := range nvals {
nvalue := reflect.Indirect(reflect.New(value.Type().Elem())) nvalue := reflect.Indirect(reflect.New(value.Type().Elem()))
if err := c.fillValue(nvalue, nval); err != nil { if err := fillValue(nvalue, nval); err != nil {
return err return err
} }
value.Index(idx).Set(nvalue) value.Index(idx).Set(nvalue)
@@ -182,7 +191,7 @@ func (c *defaultConfig) fillValue(value reflect.Value, val string) error {
return nil return nil
} }
func (c *defaultConfig) fillValues(valueOf reflect.Value) error { func fillValues(valueOf reflect.Value, tname string) error {
var values reflect.Value var values reflect.Value
if valueOf.Kind() == reflect.Ptr { if valueOf.Kind() == reflect.Ptr {
@@ -209,7 +218,7 @@ func (c *defaultConfig) fillValues(valueOf reflect.Value) error {
switch value.Kind() { switch value.Kind() {
case reflect.Struct: case reflect.Struct:
value.Set(reflect.Indirect(reflect.New(value.Type()))) value.Set(reflect.Indirect(reflect.New(value.Type())))
if err := c.fillValues(value); err != nil { if err := fillValues(value, tname); err != nil {
return err return err
} }
continue continue
@@ -223,17 +232,17 @@ func (c *defaultConfig) fillValues(valueOf reflect.Value) error {
value.Set(reflect.New(value.Type().Elem())) value.Set(reflect.New(value.Type().Elem()))
} }
value = value.Elem() value = value.Elem()
if err := c.fillValues(value); err != nil { if err := fillValues(value, tname); err != nil {
return err return err
} }
continue continue
} }
tag, ok := field.Tag.Lookup(c.opts.StructTag) tag, ok := field.Tag.Lookup(tname)
if !ok { if !ok {
continue continue
} }
if err := c.fillValue(value, tag); err != nil { if err := fillValue(value, tag); err != nil {
return err return err
} }
} }
@@ -242,16 +251,12 @@ func (c *defaultConfig) fillValues(valueOf reflect.Value) error {
} }
func (c *defaultConfig) Save(ctx context.Context, opts ...SaveOption) error { func (c *defaultConfig) Save(ctx context.Context, opts ...SaveOption) error {
for _, fn := range c.opts.BeforeSave { if err := DefaultBeforeSave(ctx, c); err != nil {
if err := fn(ctx, c); err != nil && !c.opts.AllowFail { return err
return err
}
} }
for _, fn := range c.opts.AfterSave { if err := DefaultAfterSave(ctx, c); err != nil {
if err := fn(ctx, c); err != nil && !c.opts.AllowFail { return err
return err
}
} }
return nil return nil
@@ -265,6 +270,10 @@ func (c *defaultConfig) Name() string {
return c.opts.Name return c.opts.Name
} }
func (c *defaultConfig) Watch(ctx context.Context, opts ...WatchOption) (Watcher, error) {
return nil, fmt.Errorf("not implemented")
}
// NewConfig returns new default config source // NewConfig returns new default config source
func NewConfig(opts ...Option) Config { func NewConfig(opts ...Option) Config {
options := NewOptions(opts...) options := NewOptions(opts...)

View File

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/unistack-org/micro/v3/config" "go.unistack.org/micro/v3/config"
) )
type Cfg struct { type Cfg struct {
@@ -47,6 +47,6 @@ func TestDefault(t *testing.T) {
if conf.StringValue != "after_load" { if conf.StringValue != "after_load" {
t.Fatal("AfterLoad option not working") t.Fatal("AfterLoad option not working")
} }
_ = conf
t.Logf("%#+v\n", conf) // t.Logf("%#+v\n", conf)
} }

View File

@@ -2,11 +2,12 @@ package config
import ( import (
"context" "context"
"time"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Options hold the config options // Options hold the config options
@@ -62,8 +63,10 @@ type LoadOption func(o *LoadOptions)
// LoadOptions struct // LoadOptions struct
type LoadOptions struct { type LoadOptions struct {
Struct interface{}
Override bool Override bool
Append bool Append bool
Context context.Context
} }
func NewLoadOptions(opts ...LoadOption) LoadOptions { func NewLoadOptions(opts ...LoadOption) LoadOptions {
@@ -88,13 +91,30 @@ func LoadAppend(b bool) LoadOption {
} }
} }
// LoadStruct override struct for loading
func LoadStruct(src interface{}) LoadOption {
return func(o *LoadOptions) {
o.Struct = src
}
}
// SaveOption function signature // SaveOption function signature
type SaveOption func(o *SaveOptions) type SaveOption func(o *SaveOptions)
// SaveOptions struct // SaveOptions struct
type SaveOptions struct { type SaveOptions struct {
Struct interface{}
Context context.Context
} }
// SaveStruct override struct for save to config
func SaveStruct(src interface{}) SaveOption {
return func(o *SaveOptions) {
o.Struct = src
}
}
// NewSaveOptions fill SaveOptions struct
func NewSaveOptions(opts ...SaveOption) SaveOptions { func NewSaveOptions(opts ...SaveOption) SaveOptions {
options := SaveOptions{} options := SaveOptions{}
for _, o := range opts { for _, o := range opts {
@@ -186,3 +206,60 @@ func Name(n string) Option {
o.Name = n o.Name = n
} }
} }
// WatchOptions struuct
type WatchOptions struct {
// Context used by non default options
Context context.Context
// Struct for filling
Struct interface{}
// MinInterval specifies the min time.Duration interval for poll changes
MinInterval time.Duration
// MaxInterval specifies the max time.Duration interval for poll changes
MaxInterval time.Duration
// Coalesce multiple events to one
Coalesce bool
}
type WatchOption func(*WatchOptions)
func NewWatchOptions(opts ...WatchOption) WatchOptions {
options := WatchOptions{
Context: context.Background(),
MinInterval: DefaultWatcherMinInterval,
MaxInterval: DefaultWatcherMaxInterval,
}
for _, o := range opts {
o(&options)
}
return options
}
// WatchContext pass context
func WatchContext(ctx context.Context) WatchOption {
return func(o *WatchOptions) {
o.Context = ctx
}
}
// WatchCoalesce controls watch event combining
func WatchCoalesce(b bool) WatchOption {
return func(o *WatchOptions) {
o.Coalesce = b
}
}
// WatchInterval specifies min and max time.Duration for pulling changes
func WatchInterval(min, max time.Duration) WatchOption {
return func(o *WatchOptions) {
o.MinInterval = min
o.MaxInterval = max
}
}
// WatchStruct overrides struct for fill
func WatchStruct(src interface{}) WatchOption {
return func(o *WatchOptions) {
o.Struct = src
}
}

View File

@@ -1,26 +0,0 @@
package config_test
import (
"testing"
rutil "github.com/unistack-org/micro/v3/util/reflect"
)
type Config struct {
SubConfig *SubConfig
Config *Config
Value string
}
type SubConfig struct {
Value string
}
func TestReflect(t *testing.T) {
cfg1 := &Config{Value: "cfg1", Config: &Config{Value: "cfg1_1"}, SubConfig: &SubConfig{Value: "cfg1"}}
cfg2, err := rutil.Zero(cfg1)
if err != nil {
t.Fatal(err)
}
t.Logf("dst: %#+v\n", cfg2)
}

View File

@@ -1,6 +1,6 @@
// Package errors provides a way to return detailed information // Package errors provides a way to return detailed information
// for an RPC request error. The error is normally JSON encoded. // for an RPC request error. The error is normally JSON encoded.
package errors package errors // import "go.unistack.org/micro/v3/errors"
import ( import (
"encoding/json" "encoding/json"
@@ -37,8 +37,8 @@ var (
// Error type // Error type
type Error struct { type Error struct {
// Id holds error id or service, usually someting like my_service or uuid // ID holds error id or service, usually someting like my_service or id
Id string ID string
// Detail holds some useful details about error // Detail holds some useful details about error
Detail string Detail string
// Status usually holds text of http status // Status usually holds text of http status
@@ -56,7 +56,7 @@ func (e *Error) Error() string {
// New generates a custom error // New generates a custom error
func New(id, detail string, code int32) error { func New(id, detail string, code int32) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: code, Code: code,
Detail: detail, Detail: detail,
Status: http.StatusText(int(code)), Status: http.StatusText(int(code)),
@@ -77,7 +77,7 @@ func Parse(err string) *Error {
// BadRequest generates a 400 error. // BadRequest generates a 400 error.
func BadRequest(id, format string, a ...interface{}) error { func BadRequest(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 400, Code: 400,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(400), Status: http.StatusText(400),
@@ -87,7 +87,7 @@ func BadRequest(id, format string, a ...interface{}) error {
// Unauthorized generates a 401 error. // Unauthorized generates a 401 error.
func Unauthorized(id, format string, a ...interface{}) error { func Unauthorized(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 401, Code: 401,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(401), Status: http.StatusText(401),
@@ -97,7 +97,7 @@ func Unauthorized(id, format string, a ...interface{}) error {
// Forbidden generates a 403 error. // Forbidden generates a 403 error.
func Forbidden(id, format string, a ...interface{}) error { func Forbidden(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 403, Code: 403,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(403), Status: http.StatusText(403),
@@ -107,7 +107,7 @@ func Forbidden(id, format string, a ...interface{}) error {
// NotFound generates a 404 error. // NotFound generates a 404 error.
func NotFound(id, format string, a ...interface{}) error { func NotFound(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 404, Code: 404,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(404), Status: http.StatusText(404),
@@ -117,7 +117,7 @@ func NotFound(id, format string, a ...interface{}) error {
// MethodNotAllowed generates a 405 error. // MethodNotAllowed generates a 405 error.
func MethodNotAllowed(id, format string, a ...interface{}) error { func MethodNotAllowed(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 405, Code: 405,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(405), Status: http.StatusText(405),
@@ -127,7 +127,7 @@ func MethodNotAllowed(id, format string, a ...interface{}) error {
// Timeout generates a 408 error. // Timeout generates a 408 error.
func Timeout(id, format string, a ...interface{}) error { func Timeout(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 408, Code: 408,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(408), Status: http.StatusText(408),
@@ -137,7 +137,7 @@ func Timeout(id, format string, a ...interface{}) error {
// Conflict generates a 409 error. // Conflict generates a 409 error.
func Conflict(id, format string, a ...interface{}) error { func Conflict(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 409, Code: 409,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(409), Status: http.StatusText(409),
@@ -147,7 +147,7 @@ func Conflict(id, format string, a ...interface{}) error {
// InternalServerError generates a 500 error. // InternalServerError generates a 500 error.
func InternalServerError(id, format string, a ...interface{}) error { func InternalServerError(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 500, Code: 500,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(500), Status: http.StatusText(500),
@@ -157,7 +157,7 @@ func InternalServerError(id, format string, a ...interface{}) error {
// NotImplemented generates a 501 error // NotImplemented generates a 501 error
func NotImplemented(id, format string, a ...interface{}) error { func NotImplemented(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 501, Code: 501,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(501), Status: http.StatusText(501),
@@ -167,7 +167,7 @@ func NotImplemented(id, format string, a ...interface{}) error {
// BadGateway generates a 502 error // BadGateway generates a 502 error
func BadGateway(id, format string, a ...interface{}) error { func BadGateway(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 502, Code: 502,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(502), Status: http.StatusText(502),
@@ -177,7 +177,7 @@ func BadGateway(id, format string, a ...interface{}) error {
// ServiceUnavailable generates a 503 error // ServiceUnavailable generates a 503 error
func ServiceUnavailable(id, format string, a ...interface{}) error { func ServiceUnavailable(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 503, Code: 503,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(503), Status: http.StatusText(503),
@@ -187,7 +187,7 @@ func ServiceUnavailable(id, format string, a ...interface{}) error {
// GatewayTimeout generates a 504 error // GatewayTimeout generates a 504 error
func GatewayTimeout(id, format string, a ...interface{}) error { func GatewayTimeout(id, format string, a ...interface{}) error {
return &Error{ return &Error{
Id: id, ID: id,
Code: 504, Code: 504,
Detail: fmt.Sprintf(format, a...), Detail: fmt.Sprintf(format, a...),
Status: http.StatusText(504), Status: http.StatusText(504),

View File

@@ -9,12 +9,12 @@ import (
func TestFromError(t *testing.T) { func TestFromError(t *testing.T) {
err := NotFound("go.micro.test", "%s", "example") err := NotFound("go.micro.test", "%s", "example")
merr := FromError(err) merr := FromError(err)
if merr.Id != "go.micro.test" || merr.Code != 404 { if merr.ID != "go.micro.test" || merr.Code != 404 {
t.Fatalf("invalid conversation %v != %v", err, merr) t.Fatalf("invalid conversation %v != %v", err, merr)
} }
err = er.New(err.Error()) err = er.New(err.Error())
merr = FromError(err) merr = FromError(err)
if merr.Id != "go.micro.test" || merr.Code != 404 { if merr.ID != "go.micro.test" || merr.Code != 404 {
t.Fatalf("invalid conversation %v != %v", err, merr) t.Fatalf("invalid conversation %v != %v", err, merr)
} }
} }
@@ -36,7 +36,7 @@ func TestEqual(t *testing.T) {
func TestErrors(t *testing.T) { func TestErrors(t *testing.T) {
testData := []*Error{ testData := []*Error{
{ {
Id: "test", ID: "test",
Code: 500, Code: 500,
Detail: "Internal server error", Detail: "Internal server error",
Status: http.StatusText(500), Status: http.StatusText(500),
@@ -44,7 +44,7 @@ func TestErrors(t *testing.T) {
} }
for _, e := range testData { for _, e := range testData {
ne := New(e.Id, e.Detail, e.Code) ne := New(e.ID, e.Detail, e.Code)
if e.Error() != ne.Error() { if e.Error() != ne.Error() {
t.Fatalf("Expected %s got %s", e.Error(), ne.Error()) t.Fatalf("Expected %s got %s", e.Error(), ne.Error())
@@ -56,8 +56,8 @@ func TestErrors(t *testing.T) {
t.Fatalf("Expected error got nil %v", pe) t.Fatalf("Expected error got nil %v", pe)
} }
if pe.Id != e.Id { if pe.ID != e.ID {
t.Fatalf("Expected %s got %s", e.Id, pe.Id) t.Fatalf("Expected %s got %s", e.ID, pe.ID)
} }
if pe.Detail != e.Detail { if pe.Detail != e.Detail {

View File

@@ -3,7 +3,7 @@ package micro
import ( import (
"context" "context"
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
) )
// Event is used to publish messages to a topic // Event is used to publish messages to a topic

View File

@@ -6,13 +6,13 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/google/uuid"
"github.com/silas/dag" "github.com/silas/dag"
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/store" "go.unistack.org/micro/v3/store"
"go.unistack.org/micro/v3/util/id"
) )
type microFlow struct { type microFlow struct {
@@ -20,13 +20,13 @@ type microFlow struct {
} }
type microWorkflow struct { type microWorkflow struct {
id string
g *dag.AcyclicGraph
init bool
sync.RWMutex
opts Options opts Options
g *dag.AcyclicGraph
steps map[string]Step steps map[string]Step
id string
status Status status Status
sync.RWMutex
init bool
} }
func (w *microWorkflow) ID() string { func (w *microWorkflow) ID() string {
@@ -149,18 +149,18 @@ func (w *microWorkflow) getSteps(start string, reverse bool) ([][]Step, error) {
return steps, nil return steps, nil
} }
func (w *microWorkflow) Abort(ctx context.Context, eid string) error { func (w *microWorkflow) Abort(ctx context.Context, id string) error {
workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", eid)) workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", id))
return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusAborted.String())}) return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusAborted.String())})
} }
func (w *microWorkflow) Suspend(ctx context.Context, eid string) error { func (w *microWorkflow) Suspend(ctx context.Context, id string) error {
workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", eid)) workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", id))
return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusSuspend.String())}) return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusSuspend.String())})
} }
func (w *microWorkflow) Resume(ctx context.Context, eid string) error { func (w *microWorkflow) Resume(ctx context.Context, id string) error {
workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", eid)) workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", id))
return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusRunning.String())}) return workflowStore.Write(ctx, "status", &codec.Frame{Data: []byte(StatusRunning.String())})
} }
@@ -176,11 +176,10 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
} }
w.Unlock() w.Unlock()
uid, err := uuid.NewRandom() eid, err := id.New()
if err != nil { if err != nil {
return "", err return "", err
} }
eid := uid.String()
stepStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("steps", eid)) stepStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("steps", eid))
workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", eid)) workflowStore := store.NewNamespaceStore(w.opts.Store, filepath.Join("workflows", eid))
@@ -242,6 +241,7 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
w.opts.Logger.Tracef(nctx, "will be executed %v", steps[idx][nidx]) w.opts.Logger.Tracef(nctx, "will be executed %v", steps[idx][nidx])
} }
cstep := steps[idx][nidx] cstep := steps[idx][nidx]
// nolint: nestif
if len(cstep.Requires()) == 0 { if len(cstep.Requires()) == 0 {
wg.Add(1) wg.Add(1)
go func(step Step) { go func(step Step) {
@@ -265,17 +265,16 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
} }
cherr <- serr cherr <- serr
return return
} else { }
if werr := stepStore.Write(ctx, filepath.Join(step.ID(), "rsp"), rsp); werr != nil { if werr := stepStore.Write(ctx, filepath.Join(step.ID(), "rsp"), rsp); werr != nil {
w.opts.Logger.Errorf(ctx, "store write error: %v", werr) w.opts.Logger.Errorf(ctx, "store write error: %v", werr)
cherr <- werr cherr <- werr
return return
} }
if werr := stepStore.Write(ctx, filepath.Join(step.ID(), "status"), &codec.Frame{Data: []byte(StatusSuccess.String())}); werr != nil { if werr := stepStore.Write(ctx, filepath.Join(step.ID(), "status"), &codec.Frame{Data: []byte(StatusSuccess.String())}); werr != nil {
w.opts.Logger.Errorf(ctx, "store write error: %v", werr) w.opts.Logger.Errorf(ctx, "store write error: %v", werr)
cherr <- werr cherr <- werr
return return
}
} }
}(cstep) }(cstep)
wg.Wait() wg.Wait()
@@ -299,16 +298,15 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
} }
cherr <- serr cherr <- serr
return return
} else { }
if werr := stepStore.Write(ctx, filepath.Join(cstep.ID(), "rsp"), rsp); werr != nil { if werr := stepStore.Write(ctx, filepath.Join(cstep.ID(), "rsp"), rsp); werr != nil {
w.opts.Logger.Errorf(ctx, "store write error: %v", werr) w.opts.Logger.Errorf(ctx, "store write error: %v", werr)
cherr <- werr cherr <- werr
return return
} }
if werr := stepStore.Write(ctx, filepath.Join(cstep.ID(), "status"), &codec.Frame{Data: []byte(StatusSuccess.String())}); werr != nil { if werr := stepStore.Write(ctx, filepath.Join(cstep.ID(), "status"), &codec.Frame{Data: []byte(StatusSuccess.String())}); werr != nil {
cherr <- werr cherr <- werr
return return
}
} }
} }
} }
@@ -330,7 +328,7 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
close(cherr) close(cherr)
case <-chstatus: case <-chstatus:
close(chstatus) close(chstatus)
return uid.String(), nil return eid, nil
} }
switch { switch {
@@ -338,20 +336,17 @@ func (w *microWorkflow) Execute(ctx context.Context, req *Message, opts ...Execu
if werr := workflowStore.Write(w.opts.Context, "status", &codec.Frame{Data: []byte(StatusAborted.String())}); werr != nil { if werr := workflowStore.Write(w.opts.Context, "status", &codec.Frame{Data: []byte(StatusAborted.String())}); werr != nil {
w.opts.Logger.Errorf(w.opts.Context, "store error: %v", werr) w.opts.Logger.Errorf(w.opts.Context, "store error: %v", werr)
} }
break
case err == nil: case err == nil:
if werr := workflowStore.Write(w.opts.Context, "status", &codec.Frame{Data: []byte(StatusSuccess.String())}); werr != nil { if werr := workflowStore.Write(w.opts.Context, "status", &codec.Frame{Data: []byte(StatusSuccess.String())}); werr != nil {
w.opts.Logger.Errorf(w.opts.Context, "store error: %v", werr) w.opts.Logger.Errorf(w.opts.Context, "store error: %v", werr)
} }
break
case err != nil: case err != nil:
if werr := workflowStore.Write(w.opts.Context, "status", &codec.Frame{Data: []byte(StatusFailure.String())}); werr != nil { if werr := workflowStore.Write(w.opts.Context, "status", &codec.Frame{Data: []byte(StatusFailure.String())}); werr != nil {
w.opts.Logger.Errorf(w.opts.Context, "store error: %v", werr) w.opts.Logger.Errorf(w.opts.Context, "store error: %v", werr)
} }
break
} }
return uid.String(), err return eid, err
} }
func NewFlow(opts ...Option) Flow { func NewFlow(opts ...Option) Flow {
@@ -430,11 +425,11 @@ func (f *microFlow) WorkflowLoad(ctx context.Context, id string) (Workflow, erro
} }
type microCallStep struct { type microCallStep struct {
opts StepOptions
service string
method string
rsp *Message rsp *Message
req *Message req *Message
service string
method string
opts StepOptions
status Status status Status
} }
@@ -500,10 +495,12 @@ func (s *microCallStep) Execute(ctx context.Context, req *Message, opts ...Execu
rsp := &codec.Frame{} rsp := &codec.Frame{}
copts := []client.CallOption{client.WithRetries(0)} copts := []client.CallOption{client.WithRetries(0)}
if options.Timeout > 0 { if options.Timeout > 0 {
copts = append(copts, client.WithRequestTimeout(options.Timeout), client.WithDialTimeout(options.Timeout)) copts = append(copts,
client.WithRequestTimeout(options.Timeout),
client.WithDialTimeout(options.Timeout))
} }
nctx := metadata.NewOutgoingContext(ctx, req.Header) nctx := metadata.NewOutgoingContext(ctx, req.Header)
err := options.Client.Call(nctx, options.Client.NewRequest(s.service, s.method, &codec.Frame{Data: req.Body}), rsp) err := options.Client.Call(nctx, options.Client.NewRequest(s.service, s.method, &codec.Frame{Data: req.Body}), rsp, copts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -512,10 +509,10 @@ func (s *microCallStep) Execute(ctx context.Context, req *Message, opts ...Execu
} }
type microPublishStep struct { type microPublishStep struct {
opts StepOptions
topic string
req *Message req *Message
rsp *Message rsp *Message
topic string
opts StepOptions
status Status status Status
} }
@@ -554,7 +551,7 @@ func (s *microPublishStep) String() string {
if s.opts.ID != "" { if s.opts.ID != "" {
return s.opts.ID return s.opts.ID
} }
return fmt.Sprintf("%s", s.topic) return s.topic
} }
func (s *microPublishStep) Name() string { func (s *microPublishStep) Name() string {

View File

@@ -1,5 +1,5 @@
// Package flow is an interface used for saga pattern microservice workflow // Package flow is an interface used for saga pattern microservice workflow
package flow package flow // import "go.unistack.org/micro/v3/flow"
import ( import (
"context" "context"
@@ -7,7 +7,7 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
var ( var (
@@ -116,11 +116,11 @@ type Workflow interface {
// Steps returns steps slice where parallel steps returned on the same level // Steps returns steps slice where parallel steps returned on the same level
Steps() ([][]Step, error) Steps() ([][]Step, error)
// Suspend suspends execution // Suspend suspends execution
Suspend(ctx context.Context, eid string) error Suspend(ctx context.Context, id string) error
// Resume resumes execution // Resume resumes execution
Resume(ctx context.Context, eid string) error Resume(ctx context.Context, id string) error
// Abort abort execution // Abort abort execution
Abort(ctx context.Context, eid string) error Abort(ctx context.Context, id string) error
} }
// Flow the base interface to interact with workflows // Flow the base interface to interact with workflows

View File

@@ -4,11 +4,11 @@ import (
"context" "context"
"time" "time"
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/store" "go.unistack.org/micro/v3/store"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Option func // Option func
@@ -96,8 +96,8 @@ type WorkflowOption func(*WorkflowOptions)
// WorkflowOptions holds workflow options // WorkflowOptions holds workflow options
type WorkflowOptions struct { type WorkflowOptions struct {
ID string
Context context.Context Context context.Context
ID string
} }
// WorkflowID set workflow id // WorkflowID set workflow id
@@ -120,10 +120,10 @@ type ExecuteOptions struct {
Context context.Context Context context.Context
// Start step // Start step
Start string Start string
// Reverse execution
Reverse bool
// Timeout for execution // Timeout for execution
Timeout time.Duration Timeout time.Duration
// Reverse execution
Reverse bool
// Async enables async execution // Async enables async execution
Async bool Async bool
} }
@@ -193,10 +193,10 @@ func NewExecuteOptions(opts ...ExecuteOption) ExecuteOptions {
} }
type StepOptions struct { type StepOptions struct {
ID string
Context context.Context Context context.Context
Requires []string
Fallback string Fallback string
ID string
Requires []string
} }
type StepOption func(*StepOptions) type StepOption func(*StepOptions)

View File

@@ -6,7 +6,7 @@ import (
"context" "context"
"time" "time"
"github.com/unistack-org/micro/v3/server" "go.unistack.org/micro/v3/server"
) )
// Function is a one time executing Service // Function is a one time executing Service

View File

@@ -8,7 +8,7 @@ import (
"sync" "sync"
"testing" "testing"
"github.com/unistack-org/micro/v3/register" "go.unistack.org/micro/v3/register"
) )
func TestFunction(t *testing.T) { func TestFunction(t *testing.T) {

11
go.mod
View File

@@ -1,13 +1,14 @@
module github.com/unistack-org/micro/v3 module go.unistack.org/micro/v3
go 1.16 go 1.16
require ( require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/ef-ds/deque v1.0.4 github.com/ef-ds/deque v1.0.4
github.com/google/uuid v1.3.0 github.com/golang-jwt/jwt/v4 v4.1.0
github.com/imdario/mergo v0.3.12 github.com/imdario/mergo v0.3.12
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34 github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4
golang.org/x/net v0.0.0-20210510120150-4163338589ed go.unistack.org/micro-proto/v3 v3.1.0
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
) )

25
go.sum
View File

@@ -1,22 +1,31 @@
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/ef-ds/deque v1.0.4 h1:iFAZNmveMT9WERAkqLJ+oaABF9AcVQ5AjXem/hroniI= github.com/ef-ds/deque v1.0.4 h1:iFAZNmveMT9WERAkqLJ+oaABF9AcVQ5AjXem/hroniI=
github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg= github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34 h1:vBfVmA5mZhsQa2jr1FOL9nfA37N/jnbBmi5XUfviVTI= github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4 h1:fOH64AB0C3ixGf9emky61STvPJL3smxJg+1Zwx1oCdg=
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I= github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= go.unistack.org/micro-proto/v3 v3.1.0 h1:q39FwjFiRZn+Ux/tt+d3bJTmDtsQQWa+3SLYVo1vLfA=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= go.unistack.org/micro-proto/v3 v3.1.0/go.mod h1:DpRhYCBXlmSJ/AAXTmntvlh7kQkYU6eFvlmYAx4BQS8=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -11,21 +11,12 @@ import (
"time" "time"
) )
func init() {
lvl, err := GetLevel(os.Getenv("MICRO_LOG_LEVEL"))
if err != nil {
lvl = InfoLevel
}
DefaultLogger = NewLogger(WithLevel(lvl))
}
type defaultLogger struct { type defaultLogger struct {
enc *json.Encoder enc *json.Encoder
opts Options
sync.RWMutex
logFunc LogFunc logFunc LogFunc
logfFunc LogfFunc logfFunc LogfFunc
opts Options
sync.RWMutex
} }
// Init(opts...) should only overwrite provided options // Init(opts...) should only overwrite provided options
@@ -35,15 +26,11 @@ func (l *defaultLogger) Init(opts ...Option) error {
o(&l.opts) o(&l.opts)
} }
l.enc = json.NewEncoder(l.opts.Out) l.enc = json.NewEncoder(l.opts.Out)
l.logFunc = l.Log
l.logfFunc = l.Logf
// wrap the Log func // wrap the Log func
for i := len(l.opts.Wrappers); i > 0; i-- { for i := len(l.opts.Wrappers); i > 0; i-- {
l.logFunc = l.opts.Wrappers[i-1].Log(l.logFunc) l.logFunc = l.opts.Wrappers[i-1].Log(l.logFunc)
l.logfFunc = l.opts.Wrappers[i-1].Logf(l.logfFunc) l.logfFunc = l.opts.Wrappers[i-1].Logf(l.logfFunc)
} }
l.Unlock() l.Unlock()
return nil return nil
} }
@@ -52,6 +39,28 @@ func (l *defaultLogger) String() string {
return "micro" return "micro"
} }
func (l *defaultLogger) Clone(opts ...Option) Logger {
newopts := NewOptions(opts...)
oldopts := l.opts
for _, o := range opts {
o(&newopts)
o(&oldopts)
}
oldopts.Wrappers = newopts.Wrappers
l.Lock()
cl := &defaultLogger{opts: oldopts, logFunc: l.logFunc, logfFunc: l.logfFunc}
l.Unlock()
// wrap the Log func
for i := len(newopts.Wrappers); i > 0; i-- {
cl.logFunc = newopts.Wrappers[i-1].Log(cl.logFunc)
cl.logfFunc = newopts.Wrappers[i-1].Logf(cl.logfFunc)
}
return cl
}
func (l *defaultLogger) V(level Level) bool { func (l *defaultLogger) V(level Level) bool {
l.RLock() l.RLock()
ok := l.opts.Level.Enabled(level) ok := l.opts.Level.Enabled(level)
@@ -59,26 +68,26 @@ func (l *defaultLogger) V(level Level) bool {
return ok return ok
} }
func (l *defaultLogger) Fields(fields map[string]interface{}) Logger { func (l *defaultLogger) Level(level Level) {
nl := &defaultLogger{opts: l.opts, enc: l.enc} l.Lock()
nl.opts.Fields = make(map[string]interface{}, len(l.opts.Fields)+len(fields)) l.opts.Level = level
l.RLock() l.Unlock()
for k, v := range l.opts.Fields { }
nl.opts.Fields[k] = v
}
l.RUnlock()
for k, v := range fields { func (l *defaultLogger) Fields(fields ...interface{}) Logger {
nl.opts.Fields[k] = v nl := &defaultLogger{opts: l.opts, enc: l.enc}
if len(fields) == 0 {
return nl
} else if len(fields)%2 != 0 {
fields = fields[:len(fields)-1]
} }
nl.opts.Fields = append(nl.opts.Fields, fields...)
return nl return nl
} }
func copyFields(src map[string]interface{}) map[string]interface{} { func copyFields(src []interface{}) []interface{} {
dst := make(map[string]interface{}, len(src)) dst := make([]interface{}, len(src))
for k, v := range src { copy(dst, src)
dst[k] = v
}
return dst return dst
} }
@@ -165,19 +174,23 @@ func (l *defaultLogger) Log(ctx context.Context, level Level, args ...interface{
fields := copyFields(l.opts.Fields) fields := copyFields(l.opts.Fields)
l.RUnlock() l.RUnlock()
fields["level"] = level.String() fields = append(fields, "level", level.String())
if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok { if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
fields["caller"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line) fields = append(fields, "caller", fmt.Sprintf("%s:%d", logCallerfilePath(file), line))
} }
fields = append(fields, "timestamp", time.Now().Format("2006-01-02 15:04:05"))
fields["timestamp"] = time.Now().Format("2006-01-02 15:04:05")
if len(args) > 0 { if len(args) > 0 {
fields["msg"] = fmt.Sprint(args...) fields = append(fields, "msg", fmt.Sprint(args...))
} }
out := make(map[string]interface{}, len(fields)/2)
for i := 0; i < len(fields); i += 2 {
out[fields[i].(string)] = fields[i+1]
}
l.RLock() l.RLock()
_ = l.enc.Encode(fields) _ = l.enc.Encode(out)
l.RUnlock() l.RUnlock()
} }
@@ -190,35 +203,39 @@ func (l *defaultLogger) Logf(ctx context.Context, level Level, msg string, args
fields := copyFields(l.opts.Fields) fields := copyFields(l.opts.Fields)
l.RUnlock() l.RUnlock()
fields["level"] = level.String() fields = append(fields, "level", level.String())
if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok { if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
fields["caller"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line) fields = append(fields, "caller", fmt.Sprintf("%s:%d", logCallerfilePath(file), line))
} }
fields["timestamp"] = time.Now().Format("2006-01-02 15:04:05") fields = append(fields, "timestamp", time.Now().Format("2006-01-02 15:04:05"))
if len(args) > 0 { if len(args) > 0 {
fields["msg"] = fmt.Sprintf(msg, args...) fields = append(fields, "msg", fmt.Sprintf(msg, args...))
} else if msg != "" { } else if msg != "" {
fields["msg"] = msg fields = append(fields, "msg", msg)
}
out := make(map[string]interface{}, len(fields)/2)
for i := 0; i < len(fields); i += 2 {
out[fields[i].(string)] = fields[i+1]
} }
l.RLock() l.RLock()
_ = l.enc.Encode(fields) _ = l.enc.Encode(out)
l.RUnlock() l.RUnlock()
} }
func (l *defaultLogger) Options() Options { func (l *defaultLogger) Options() Options {
// not guard against options Context values return l.opts
l.RLock()
opts := l.opts
opts.Fields = copyFields(l.opts.Fields)
l.RUnlock()
return opts
} }
// NewLogger builds a new logger based on options // NewLogger builds a new logger based on options
func NewLogger(opts ...Option) Logger { func NewLogger(opts ...Option) Logger {
l := &defaultLogger{opts: NewOptions(opts...)} l := &defaultLogger{
opts: NewOptions(opts...),
}
l.logFunc = l.Log
l.logfFunc = l.Logf
l.enc = json.NewEncoder(l.opts.Out) l.enc = json.NewEncoder(l.opts.Out)
return l return l
} }

View File

@@ -1,24 +1,20 @@
package logger package logger
import (
"fmt"
)
// Level means logger level // Level means logger level
type Level int8 type Level int8
const ( const (
// TraceLevel level. Designates finer-grained informational events than the Debug. // TraceLevel level usually used to find bugs, very verbose
TraceLevel Level = iota - 2 TraceLevel Level = iota - 2
// DebugLevel level. Usually only enabled when debugging. Very verbose logging. // DebugLevel level used only when enabled debugging
DebugLevel DebugLevel
// InfoLevel level. General operational entries about what's going on inside the application. // InfoLevel level used for general info about what's going on inside the application
InfoLevel InfoLevel
// WarnLevel level. Non-critical entries that deserve eyes. // WarnLevel level used for non-critical entries
WarnLevel WarnLevel
// ErrorLevel level. Used for errors that should definitely be noted. // ErrorLevel level used for errors that should definitely be noted
ErrorLevel ErrorLevel
// FatalLevel level. Logs and then calls `os.Exit(1)`. highest level of severity. // FatalLevel level used for critical errors and then calls `os.Exit(1)`
FatalLevel FatalLevel
) )
@@ -38,7 +34,7 @@ func (l Level) String() string {
case FatalLevel: case FatalLevel:
return "fatal" return "fatal"
} }
return "" return "info"
} }
// Enabled returns true if the given level is at or above this level. // Enabled returns true if the given level is at or above this level.
@@ -46,22 +42,22 @@ func (l Level) Enabled(lvl Level) bool {
return lvl >= l return lvl >= l
} }
// GetLevel converts a level string into a logger Level value. // ParseLevel converts a level string into a logger Level value.
// returns an error if the input string does not match known values. // returns an InfoLevel if the input string does not match known values.
func GetLevel(levelStr string) (Level, error) { func ParseLevel(lvl string) Level {
switch levelStr { switch lvl {
case TraceLevel.String(): case TraceLevel.String():
return TraceLevel, nil return TraceLevel
case DebugLevel.String(): case DebugLevel.String():
return DebugLevel, nil return DebugLevel
case InfoLevel.String(): case InfoLevel.String():
return InfoLevel, nil return InfoLevel
case WarnLevel.String(): case WarnLevel.String():
return WarnLevel, nil return WarnLevel
case ErrorLevel.String(): case ErrorLevel.String():
return ErrorLevel, nil return ErrorLevel
case FatalLevel.String(): case FatalLevel.String():
return FatalLevel, nil return FatalLevel
} }
return InfoLevel, fmt.Errorf("unknown Level String: '%s', use InfoLevel", levelStr) return InfoLevel
} }

View File

@@ -1,25 +1,34 @@
// Package logger provides a log interface // Package logger provides a log interface
package logger package logger // import "go.unistack.org/micro/v3/logger"
import "context" import (
"context"
"os"
)
var ( var (
// DefaultLogger variable // DefaultLogger variable
DefaultLogger Logger = NewLogger() DefaultLogger Logger = NewLogger(WithLevel(ParseLevel(os.Getenv("MICRO_LOG_LEVEL"))))
// DefaultLevel used by logger // DefaultLevel used by logger
DefaultLevel Level = InfoLevel DefaultLevel Level = InfoLevel
// DefaultCallerSkipCount used by logger
DefaultCallerSkipCount = 2
) )
// Logger is a generic logging interface // Logger is a generic logging interface
type Logger interface { type Logger interface {
// Init initialises options // Init initialises options
Init(opts ...Option) error Init(opts ...Option) error
// Clone create logger copy with new options
Clone(opts ...Option) Logger
// V compare provided verbosity level with current log level // V compare provided verbosity level with current log level
V(level Level) bool V(level Level) bool
// Level sets the log level for logger
Level(level Level)
// The Logger options // The Logger options
Options() Options Options() Options
// Fields set fields to always be logged // Fields set fields to always be logged with keyval pairs
Fields(fields map[string]interface{}) Logger Fields(fields ...interface{}) Logger
// Info level message // Info level message
Info(ctx context.Context, args ...interface{}) Info(ctx context.Context, args ...interface{})
// Trace level message // Trace level message
@@ -52,6 +61,9 @@ type Logger interface {
String() string String() string
} }
// Field contains keyval pair
type Field interface{}
// Info writes msg to default logger on info level // Info writes msg to default logger on info level
func Info(ctx context.Context, args ...interface{}) { func Info(ctx context.Context, args ...interface{}) {
DefaultLogger.Info(ctx, args...) DefaultLogger.Info(ctx, args...)
@@ -123,6 +135,6 @@ func Init(opts ...Option) error {
} }
// Fields create logger with specific fields // Fields create logger with specific fields
func Fields(fields map[string]interface{}) Logger { func Fields(fields ...interface{}) Logger {
return DefaultLogger.Fields(fields) return DefaultLogger.Fields(fields...)
} }

View File

@@ -3,9 +3,58 @@ package logger
import ( import (
"bytes" "bytes"
"context" "context"
"log"
"testing" "testing"
) )
func TestClone(t *testing.T) {
ctx := context.TODO()
buf := bytes.NewBuffer(nil)
l := NewLogger(WithLevel(TraceLevel), WithOutput(buf))
if err := l.Init(); err != nil {
t.Fatal(err)
}
nl := l.Clone(WithLevel(ErrorLevel))
if err := nl.Init(); err != nil {
t.Fatal(err)
}
nl.Info(ctx, "info message")
if len(buf.Bytes()) != 0 {
t.Fatal("message must not be logged")
}
l.Info(ctx, "info message")
if len(buf.Bytes()) == 0 {
t.Fatal("message must be logged")
}
}
func TestRedirectStdLogger(t *testing.T) {
buf := bytes.NewBuffer(nil)
l := NewLogger(WithLevel(TraceLevel), WithOutput(buf))
if err := l.Init(); err != nil {
t.Fatal(err)
}
fn := RedirectStdLogger(l, ErrorLevel)
defer fn()
log.Print("test")
if !bytes.Contains(buf.Bytes(), []byte(`"level":"error","msg":"test","timestamp"`)) {
t.Fatalf("logger error, buf %s", buf.Bytes())
}
}
func TestStdLogger(t *testing.T) {
buf := bytes.NewBuffer(nil)
l := NewLogger(WithLevel(TraceLevel), WithOutput(buf))
if err := l.Init(); err != nil {
t.Fatal(err)
}
lg := NewStdLogger(l, ErrorLevel)
lg.Print("test")
if !bytes.Contains(buf.Bytes(), []byte(`"level":"error","msg":"test","timestamp"`)) {
t.Fatalf("logger error, buf %s", buf.Bytes())
}
}
func TestLogger(t *testing.T) { func TestLogger(t *testing.T) {
ctx := context.TODO() ctx := context.TODO()
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
@@ -15,7 +64,7 @@ func TestLogger(t *testing.T) {
} }
l.Trace(ctx, "trace_msg1") l.Trace(ctx, "trace_msg1")
l.Warn(ctx, "warn_msg1") l.Warn(ctx, "warn_msg1")
l.Fields(map[string]interface{}{"error": "test"}).Info(ctx, "error message") l.Fields("error", "test").Info(ctx, "error message")
l.Warn(ctx, "first", " ", "second") l.Warn(ctx, "first", " ", "second")
if !bytes.Contains(buf.Bytes(), []byte(`"level":"trace","msg":"trace_msg1"`)) { if !bytes.Contains(buf.Bytes(), []byte(`"level":"trace","msg":"trace_msg1"`)) {
t.Fatalf("logger error, buf %s", buf.Bytes()) t.Fatalf("logger error, buf %s", buf.Bytes())

View File

@@ -16,24 +16,24 @@ type Options struct {
// Context holds exernal options // Context holds exernal options
Context context.Context Context context.Context
// Fields holds additional metadata // Fields holds additional metadata
Fields map[string]interface{} Fields []interface{}
// Name holds the logger name // Name holds the logger name
Name string Name string
// CallerSkipCount number of frmaes to skip
CallerSkipCount int
// The logging level the logger should log
Level Level
// Wrappers logger wrapper that called before actual Log/Logf function // Wrappers logger wrapper that called before actual Log/Logf function
Wrappers []Wrapper Wrappers []Wrapper
// The logging level the logger should log
Level Level
// CallerSkipCount number of frmaes to skip
CallerSkipCount int
} }
// NewOptions creates new options struct // NewOptions creates new options struct
func NewOptions(opts ...Option) Options { func NewOptions(opts ...Option) Options {
options := Options{ options := Options{
Level: DefaultLevel, Level: DefaultLevel,
Fields: make(map[string]interface{}), Fields: make([]interface{}, 0, 6),
Out: os.Stderr, Out: os.Stderr,
CallerSkipCount: 0, CallerSkipCount: DefaultCallerSkipCount,
Context: context.Background(), Context: context.Background(),
} }
for _, o := range opts { for _, o := range opts {
@@ -43,7 +43,7 @@ func NewOptions(opts ...Option) Options {
} }
// WithFields set default fields for the logger // WithFields set default fields for the logger
func WithFields(fields map[string]interface{}) Option { func WithFields(fields ...interface{}) Option {
return func(o *Options) { return func(o *Options) {
o.Fields = fields o.Fields = fields
} }

35
logger/stdlogger.go Normal file
View File

@@ -0,0 +1,35 @@
package logger
import (
"bytes"
"log"
)
type stdLogger struct {
l Logger
level Level
}
func NewStdLogger(l Logger, level Level) *log.Logger {
return log.New(&stdLogger{l: l, level: level}, "" /* prefix */, 0 /* flags */)
}
func (sl *stdLogger) Write(p []byte) (int, error) {
p = bytes.TrimSpace(p)
sl.l.Log(sl.l.Options().Context, sl.level, string(p))
return len(p), nil
}
func RedirectStdLogger(l Logger, level Level) func() {
flags := log.Flags()
prefix := log.Prefix()
writer := log.Writer()
log.SetFlags(0)
log.SetPrefix("")
log.SetOutput(&stdLogger{l: l, level: level})
return func() {
log.SetFlags(flags)
log.SetPrefix(prefix)
log.SetOutput(writer)
}
}

View File

@@ -1,10 +1,10 @@
package logger package logger // import "go.unistack.org/micro/v3/logger/wrapper"
import ( import (
"context" "context"
"reflect" "reflect"
rutil "github.com/unistack-org/micro/v3/util/reflect" rutil "go.unistack.org/micro/v3/util/reflect"
) )
// LogFunc function used for Log method // LogFunc function used for Log method
@@ -20,9 +20,7 @@ type Wrapper interface {
Logf(LogfFunc) LogfFunc Logf(LogfFunc) LogfFunc
} }
var ( var _ Logger = &OmitLogger{}
_ Logger = &OmitLogger{}
)
type OmitLogger struct { type OmitLogger struct {
l Logger l Logger
@@ -40,12 +38,20 @@ func (w *OmitLogger) V(level Level) bool {
return w.l.V(level) return w.l.V(level)
} }
func (w *OmitLogger) Level(level Level) {
w.l.Level(level)
}
func (w *OmitLogger) Clone(opts ...Option) Logger {
return w.l.Clone(opts...)
}
func (w *OmitLogger) Options() Options { func (w *OmitLogger) Options() Options {
return w.l.Options() return w.l.Options()
} }
func (w *OmitLogger) Fields(fields map[string]interface{}) Logger { func (w *OmitLogger) Fields(fields ...interface{}) Logger {
return w.l.Fields(fields) return w.l.Fields(fields...)
} }
func (w *OmitLogger) Info(ctx context.Context, args ...interface{}) { func (w *OmitLogger) Info(ctx context.Context, args ...interface{}) {
@@ -119,23 +125,29 @@ func getArgs(args []interface{}) []interface{} {
var err error var err error
for _, arg := range args { for _, arg := range args {
val := reflect.ValueOf(arg) val := reflect.ValueOf(arg)
switch val.Kind() { if val.Kind() == reflect.Ptr {
case reflect.Ptr:
val = val.Elem() val = val.Elem()
} }
narg := arg narg := arg
if val.Kind() == reflect.Struct { if val.Kind() != reflect.Struct {
if narg, err = rutil.Zero(arg); err == nil { nargs = append(nargs, narg)
rutil.CopyDefaults(narg, arg) continue
if flds, ferr := rutil.StructFields(narg); ferr == nil { }
for _, fld := range flds {
if tv, ok := fld.Field.Tag.Lookup("logger"); ok && tv == "omit" { if narg, err = rutil.Zero(arg); err != nil {
fld.Value.Set(reflect.Zero(fld.Value.Type())) nargs = append(nargs, narg)
} continue
} }
rutil.CopyDefaults(narg, arg)
if flds, ferr := rutil.StructFields(narg); ferr == nil {
for _, fld := range flds {
if tv, ok := fld.Field.Tag.Lookup("logger"); ok && tv == "omit" {
fld.Value.Set(reflect.Zero(fld.Value.Type()))
} }
} }
} }
nargs = append(nargs, narg) nargs = append(nargs, narg)
} }
return nargs return nargs

View File

@@ -5,9 +5,9 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/server" "go.unistack.org/micro/v3/server"
) )
var ( var (

View File

@@ -1,13 +1,25 @@
// Package metadata is a way of defining message headers // Package metadata is a way of defining message headers
package metadata package metadata // import "go.unistack.org/micro/v3/metadata"
import ( import (
"net/textproto" "net/textproto"
"sort" "sort"
) )
// HeaderPrefix for all headers passed var (
var HeaderPrefix = "Micro-" // HeaderTopic is the header name that contains topic name
HeaderTopic = "Micro-Topic"
// HeaderContentType specifies content type of message
HeaderContentType = "Content-Type"
// HeaderEndpoint specifies endpoint in service
HeaderEndpoint = "Micro-Endpoint"
// HeaderService specifies service
HeaderService = "Micro-Service"
// HeaderTimeout specifies timeout of operation
HeaderTimeout = "Micro-Timeout"
// HeaderAuthorization specifies Authorization header
HeaderAuthorization = "Authorization"
)
// Metadata is our way of representing request headers internally. // Metadata is our way of representing request headers internally.
// They're used at the RPC level and translate back and forth // They're used at the RPC level and translate back and forth
@@ -95,13 +107,16 @@ func New(size int) Metadata {
// Merge merges metadata to existing metadata, overwriting if specified // Merge merges metadata to existing metadata, overwriting if specified
func Merge(omd Metadata, mmd Metadata, overwrite bool) Metadata { func Merge(omd Metadata, mmd Metadata, overwrite bool) Metadata {
var ok bool
nmd := Copy(omd) nmd := Copy(omd)
for key, val := range mmd { for key, val := range mmd {
if _, ok := nmd[key]; ok && !overwrite { _, ok = nmd[key]
// skip switch {
} else if val != "" { case ok && !overwrite:
continue
case val != "":
nmd.Set(key, val) nmd.Set(key, val)
} else { case ok && val == "":
nmd.Del(key) nmd.Del(key)
} }
} }

View File

@@ -1,3 +1,12 @@
package meter package meter
//go:generate protoc -I./handler -I../ -I/home/vtolstov/.cache/go-path/pkg/mod/github.com/unistack-org/micro-proto@v0.0.1 --micro_out=components=micro|http|server,standalone=false,debug=true,paths=source_relative:./handler handler/handler.proto //go:generate sh -c "protoc -I./handler -I../ -I$(go list -f '{{ .Dir }}' -m go.unistack.org/micro-proto/v3) --go-micro_out='components=micro|http|server',standalone=false,debug=true,paths=source_relative:./handler handler/handler.proto"
import (
// import required packages
_ "go.unistack.org/micro-proto/v3/api"
// import required packages
_ "go.unistack.org/micro-proto/v3/openapiv3"
)

View File

@@ -1,12 +1,12 @@
package handler package handler // import "go.unistack.org/micro/v3/meter/handler"
import ( import (
"bytes" "bytes"
"context" "context"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/errors" "go.unistack.org/micro/v3/errors"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
) )
// guard to fail early // guard to fail early

View File

@@ -1,27 +1,23 @@
syntax = "proto3"; syntax = "proto3";
package micro.meter.handler; package micro.meter.handler;
option go_package = "github.com/unistack-org/micro/v3/meter/handler;handler"; option go_package = "go.unistack.org/micro/v3/meter/handler;handler";
import "api/annotations.proto"; import "api/annotations.proto";
import "openapiv2/annotations.proto"; import "openapiv3/annotations.proto";
import "codec/frame.proto"; import "codec/frame.proto";
service Meter { service Meter {
rpc Metrics(micro.codec.Frame) returns (micro.codec.Frame) { rpc Metrics(micro.codec.Frame) returns (micro.codec.Frame) {
option (micro.openapiv2.openapiv2_operation) = { option (micro.openapiv3.openapiv3_operation) = {
operation_id: "Metrics"; operation_id: "Metrics";
responses: { responses: {
key: "default"; default: {
value: { reference: {
description: "Error response"; _ref: "micro.codec.Frame";
schema: { };
json_schema: { };
ref: "micro.codec.Frame"; };
}
}
}
}
}; };
option (micro.api.http) = { get: "/metrics"; }; option (micro.api.http) = { get: "/metrics"; };
}; };

View File

@@ -1,22 +1,30 @@
// Code generated by protoc-gen-micro // Code generated by protoc-gen-go-micro. DO NOT EDIT.
// protoc-gen-go-micro version: v3.5.2
// source: handler.proto // source: handler.proto
package handler package handler
import ( import (
context "context" context "context"
api "github.com/unistack-org/micro/v3/api" api "go.unistack.org/micro/v3/api"
codec "github.com/unistack-org/micro/v3/codec" codec "go.unistack.org/micro/v3/codec"
) )
func NewMeterEndpoints() []*api.Endpoint { var (
return []*api.Endpoint{ MeterName = "Meter"
&api.Endpoint{
MeterEndpoints = []api.Endpoint{
{
Name: "Meter.Metrics", Name: "Meter.Metrics",
Path: []string{"/metrics"}, Path: []string{"/metrics"},
Method: []string{"GET"}, Method: []string{"GET"},
Handler: "rpc", Handler: "rpc",
}, },
} }
)
func NewMeterEndpoints() []api.Endpoint {
return MeterEndpoints
} }
type MeterServer interface { type MeterServer interface {

View File

@@ -1,12 +1,14 @@
// Code generated by protoc-gen-micro // Code generated by protoc-gen-go-micro. DO NOT EDIT.
// protoc-gen-go-micro version: v3.5.2
// source: handler.proto // source: handler.proto
package handler package handler
import ( import (
context "context" context "context"
api "github.com/unistack-org/micro/v3/api" api "go.unistack.org/micro/v3/api"
codec "github.com/unistack-org/micro/v3/codec" codec "go.unistack.org/micro/v3/codec"
server "github.com/unistack-org/micro/v3/server" server "go.unistack.org/micro/v3/server"
) )
type meterServer struct { type meterServer struct {
@@ -26,8 +28,8 @@ func RegisterMeterServer(s server.Server, sh MeterServer, opts ...server.Handler
} }
h := &meterServer{sh} h := &meterServer{sh}
var nopts []server.HandlerOption var nopts []server.HandlerOption
for _, endpoint := range NewMeterEndpoints() { for _, endpoint := range MeterEndpoints {
nopts = append(nopts, api.WithEndpoint(endpoint)) nopts = append(nopts, api.WithEndpoint(&endpoint))
} }
return s.Handle(s.NewHandler(&Meter{h}, append(nopts, opts...)...)) return s.Handle(s.NewHandler(&Meter{h}, append(nopts, opts...)...))
} }

View File

@@ -1,5 +1,5 @@
// Package meter is for instrumentation // Package meter is for instrumentation
package meter package meter // import "go.unistack.org/micro/v3/meter"
import ( import (
"io" "io"
@@ -28,17 +28,31 @@ var (
// Meter is an interface for collecting and instrumenting metrics // Meter is an interface for collecting and instrumenting metrics
type Meter interface { type Meter interface {
// Name returns meter name
Name() string Name() string
// Init initialize meter
Init(opts ...Option) error Init(opts ...Option) error
// Clone create meter copy with new options
Clone(opts ...Option) Meter
// Counter get or create counter
Counter(name string, labels ...string) Counter Counter(name string, labels ...string) Counter
// FloatCounter get or create float counter
FloatCounter(name string, labels ...string) FloatCounter FloatCounter(name string, labels ...string) FloatCounter
// Gauge get or create gauge
Gauge(name string, fn func() float64, labels ...string) Gauge Gauge(name string, fn func() float64, labels ...string) Gauge
// Set create new meter metrics set
Set(opts ...Option) Meter Set(opts ...Option) Meter
// Histogram get or create histogram
Histogram(name string, labels ...string) Histogram Histogram(name string, labels ...string) Histogram
// Summary get or create summary
Summary(name string, labels ...string) Summary Summary(name string, labels ...string) Summary
// SummaryExt get or create summary with spcified quantiles and window time
SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) Summary SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) Summary
// Write writes metrics to io.Writer
Write(w io.Writer, opts ...Option) error Write(w io.Writer, opts ...Option) error
// Options returns meter options
Options() Options Options() Options
// String return meter type
String() string String() string
} }

View File

@@ -33,7 +33,7 @@ func TestBuildLabels(t *testing.T) {
} }
data := []testData{ data := []testData{
testData{ {
src: []string{"zerolabel", "value3", "firstlabel", "value2"}, src: []string{"zerolabel", "value3", "firstlabel", "value2"},
dst: []string{"firstlabel", "value2", "zerolabel", "value3"}, dst: []string{"firstlabel", "value2", "zerolabel", "value3"},
}, },
@@ -48,15 +48,15 @@ func TestBuildLabels(t *testing.T) {
func TestBuildName(t *testing.T) { func TestBuildName(t *testing.T) {
data := map[string][]string{ data := map[string][]string{
`my_metric{firstlabel="value2",zerolabel="value3"}`: []string{ `my_metric{firstlabel="value2",zerolabel="value3"}`: {
"my_metric", "my_metric",
"zerolabel", "value3", "firstlabel", "value2", "zerolabel", "value3", "firstlabel", "value2",
}, },
`my_metric{broker="broker2",register="mdns",server="tcp"}`: []string{ `my_metric{broker="broker2",register="mdns",server="tcp"}`: {
"my_metric", "my_metric",
"broker", "broker1", "broker", "broker2", "server", "http", "server", "tcp", "register", "mdns", "broker", "broker1", "broker", "broker2", "server", "http", "server", "tcp", "register", "mdns",
}, },
`my_metric{aaa="aaa"}`: []string{ `my_metric{aaa="aaa"}`: {
"my_metric", "my_metric",
"aaa", "aaa", "aaa", "aaa",
}, },

View File

@@ -15,6 +15,15 @@ func NewMeter(opts ...Option) Meter {
return &noopMeter{opts: NewOptions(opts...)} return &noopMeter{opts: NewOptions(opts...)}
} }
// Clone return old meter with new options
func (r *noopMeter) Clone(opts ...Option) Meter {
options := r.opts
for _, o := range opts {
o(&options)
}
return &noopMeter{opts: options}
}
func (r *noopMeter) Name() string { func (r *noopMeter) Name() string {
return r.opts.Name return r.opts.Name
} }

View File

@@ -3,7 +3,7 @@ package meter
import ( import (
"context" "context"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
) )
// Option powers the configuration for metrics implementations: // Option powers the configuration for metrics implementations:
@@ -51,6 +51,20 @@ func NewOptions(opt ...Option) Options {
return opts return opts
} }
// LabelPrefix sets the labels prefix
func LabelPrefix(pref string) Option {
return func(o *Options) {
o.LabelPrefix = pref
}
}
// MetricPrefix sets the metric prefix
func MetricPrefix(pref string) Option {
return func(o *Options) {
o.MetricPrefix = pref
}
}
// Context sets the metrics context // Context sets the metrics context
func Context(ctx context.Context) Option { func Context(ctx context.Context) Option {
return func(o *Options) { return func(o *Options) {

View File

@@ -1,13 +1,13 @@
package wrapper package wrapper // import "go.unistack.org/micro/v3/meter/wrapper"
import ( import (
"context" "context"
"fmt" "fmt"
"time" "time"
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/server" "go.unistack.org/micro/v3/server"
) )
var ( var (

1
micro.go Normal file
View File

@@ -0,0 +1 @@
package micro // import "go.unistack.org/micro/v3"

View File

@@ -1,35 +0,0 @@
// +build ignore
// Package model is an interface for data modelling
package model
// Model provides an interface for data modelling
type Model interface {
// Initialise options
Init(...Option) error
// NewEntity creates a new entity to store or access
NewEntity(name string, value interface{}) Entity
// Create a value
Create(Entity) error
// Read values
Read(...ReadOption) ([]Entity, error)
// Update the value
Update(Entity) error
// Delete an entity
Delete(...DeleteOption) error
// Implementation of the model
String() string
}
type Entity interface {
// Unique id of the entity
Id() string
// Name of the entity
Name() string
// The value associated with the entity
Value() interface{}
// Attributes of the entity
Attributes() map[string]interface{}
// Read a value as a concrete type
Read(v interface{}) error
}

View File

@@ -1,41 +0,0 @@
// +build ignore
// Package model is an interface for data modelling
package model
import (
"github.com/unistack-org/micro/v3/codec"
"github.com/unistack-org/micro/v3/logger"
"github.com/unistack-org/micro/v3/store"
"github.com/unistack-org/micro/v3/sync"
)
type Options struct {
// Database to write to
Database string
// for serialising
Codec codec.Codec
// for locking
Sync sync.Sync
// for storage
Store store.Store
// for logger
Logger logger.Logger
}
type Option func(o *Options)
// Logger sets the logger
func Logger(l logger.Logger) Option {
return func(o *Options) {
o.Logger = l
}
}
type ReadOptions struct{}
type ReadOption func(o *ReadOptions)
type DeleteOptions struct{}
type DeleteOption func(o *DeleteOptions)

View File

@@ -1,9 +1,9 @@
// Package network is for creating internetworks // Package network is for creating internetworks
package network package network // import "go.unistack.org/micro/v3/network"
import ( import (
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/server" "go.unistack.org/micro/v3/server"
) )
// Error is network node errors // Error is network node errors

View File

@@ -1,13 +1,13 @@
package network package network
import ( import (
"github.com/google/uuid" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/network/tunnel"
"github.com/unistack-org/micro/v3/network/tunnel" "go.unistack.org/micro/v3/proxy"
"github.com/unistack-org/micro/v3/proxy" "go.unistack.org/micro/v3/router"
"github.com/unistack-org/micro/v3/router" "go.unistack.org/micro/v3/tracer"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/util/id"
) )
// Option func // Option func
@@ -27,8 +27,8 @@ type Options struct {
Tracer tracer.Tracer Tracer tracer.Tracer
// Tunnel used for transfer data // Tunnel used for transfer data
Tunnel tunnel.Tunnel Tunnel tunnel.Tunnel
// Id of the node // ID of the node
Id string ID string
// Name of the network // Name of the network
Name string Name string
// Address to bind to // Address to bind to
@@ -39,10 +39,10 @@ type Options struct {
Nodes []string Nodes []string
} }
// Id sets the id of the network node // ID sets the id of the network node
func Id(id string) Option { func ID(id string) Option {
return func(o *Options) { return func(o *Options) {
o.Id = id o.ID = id
} }
} }
@@ -119,7 +119,7 @@ func Tracer(t tracer.Tracer) Option {
// NewOptions returns network default options // NewOptions returns network default options
func NewOptions(opts ...Option) Options { func NewOptions(opts ...Option) Options {
options := Options{ options := Options{
Id: uuid.New().String(), ID: id.Must(),
Name: "go.micro", Name: "go.micro",
Address: ":0", Address: ":0",
Logger: logger.DefaultLogger, Logger: logger.DefaultLogger,

View File

@@ -8,9 +8,9 @@ import (
"sync" "sync"
"time" "time"
maddr "github.com/unistack-org/micro/v3/util/addr" maddr "go.unistack.org/micro/v3/util/addr"
mnet "github.com/unistack-org/micro/v3/util/net" mnet "go.unistack.org/micro/v3/util/net"
"github.com/unistack-org/micro/v3/util/rand" "go.unistack.org/micro/v3/util/rand"
) )
type memorySocket struct { type memorySocket struct {

View File

@@ -16,12 +16,14 @@ func TestMemoryTransport(t *testing.T) {
} }
defer l.Close() defer l.Close()
cherr := make(chan error, 1)
// accept // accept
go func() { go func() {
if err := l.Accept(func(sock Socket) { if nerr := l.Accept(func(sock Socket) {
for { for {
var m Message var m Message
if err := sock.Recv(&m); err != nil { if rerr := sock.Recv(&m); rerr != nil {
cherr <- rerr
return return
} }
if len(os.Getenv("INTEGRATION_TESTS")) == 0 { if len(os.Getenv("INTEGRATION_TESTS")) == 0 {
@@ -30,11 +32,12 @@ func TestMemoryTransport(t *testing.T) {
if cerr := sock.Send(&Message{ if cerr := sock.Send(&Message{
Body: []byte(`pong`), Body: []byte(`pong`),
}); cerr != nil { }); cerr != nil {
cherr <- cerr
return return
} }
} }
}); err != nil { }); nerr != nil {
t.Fatalf("Unexpected error accepting %v", err) cherr <- err
} }
}() }()
@@ -45,19 +48,24 @@ func TestMemoryTransport(t *testing.T) {
} }
defer c.Close() defer c.Close()
// send <=> receive select {
for i := 0; i < 3; i++ { case err := <-cherr:
if err := c.Send(&Message{ t.Fatal(err)
Body: []byte(`ping`), default:
}); err != nil { // send <=> receive
return for i := 0; i < 3; i++ {
} if err := c.Send(&Message{
var m Message Body: []byte(`ping`),
if err := c.Recv(&m); err != nil { }); err != nil {
return return
} }
if len(os.Getenv("INTEGRATION_TESTS")) == 0 { var m Message
t.Logf("Client Received %s", string(m.Body)) if err := c.Recv(&m); err != nil {
return
}
if len(os.Getenv("INTEGRATION_TESTS")) == 0 {
t.Logf("Client Received %s", string(m.Body))
}
} }
} }
} }

View File

@@ -5,10 +5,10 @@ import (
"crypto/tls" "crypto/tls"
"time" "time"
"github.com/unistack-org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Options struct holds the transport options // Options struct holds the transport options

View File

@@ -1,11 +1,11 @@
// Package transport is an interface for synchronous connection based communication // Package transport is an interface for synchronous connection based communication
package transport package transport // import "go.unistack.org/micro/v3/network/transport"
import ( import (
"context" "context"
"time" "time"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
var ( var (

View File

@@ -1,14 +1,15 @@
// Package broker is a tunnel broker // Package broker is a tunnel broker
package broker package broker // import "go.unistack.org/micro/v3/network/tunnel/broker"
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/unistack-org/micro/v3/broker" "go.unistack.org/micro/v3/broker"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/network/transport" "go.unistack.org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/network/tunnel" "go.unistack.org/micro/v3/network/transport"
"go.unistack.org/micro/v3/network/tunnel"
) )
type tunBroker struct { type tunBroker struct {
@@ -33,9 +34,9 @@ type tunBatchSubscriber struct {
} }
type tunEvent struct { type tunEvent struct {
err error
message *broker.Message message *broker.Message
topic string topic string
err error
} }
// used to access tunnel from options context // used to access tunnel from options context
@@ -78,10 +79,10 @@ func (t *tunBroker) BatchPublish(ctx context.Context, msgs []*broker.Message, op
var err error var err error
for _, msg := range msgs { for _, msg := range msgs {
topic, _ := msg.Header.Get("Micro-Topic") topic, _ := msg.Header.Get(metadata.HeaderTopic)
c, ok := topicMap[topic] c, ok := topicMap[topic]
if !ok { if !ok {
c, err := t.tunnel.Dial(ctx, topic, tunnel.DialMode(tunnel.Multicast)) c, err = t.tunnel.Dial(ctx, topic, tunnel.DialMode(tunnel.Multicast))
if err != nil { if err != nil {
return err return err
} }
@@ -198,7 +199,9 @@ func (t *tunBatchSubscriber) run() {
}, },
}} }}
// handle the message // handle the message
go t.handler(evts) go func() {
_ = t.handler(evts)
}()
} }
} }
@@ -234,13 +237,15 @@ func (t *tunSubscriber) run() {
c.Close() c.Close()
// handle the message // handle the message
go t.handler(&tunEvent{ go func() {
topic: t.topic, _ = t.handler(&tunEvent{
message: &broker.Message{ topic: t.topic,
Header: m.Header, message: &broker.Message{
Body: m.Body, Header: m.Header,
}, Body: m.Body,
}) },
})
}()
} }
} }

View File

@@ -3,11 +3,11 @@ package tunnel
import ( import (
"time" "time"
"github.com/google/uuid" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/network/transport"
"github.com/unistack-org/micro/v3/network/transport" "go.unistack.org/micro/v3/tracer"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/util/id"
) )
var ( var (
@@ -164,7 +164,7 @@ func DialWait(b bool) DialOption {
// NewOptions returns router default options with filled values // NewOptions returns router default options with filled values
func NewOptions(opts ...Option) Options { func NewOptions(opts ...Option) Options {
options := Options{ options := Options{
ID: uuid.New().String(), ID: id.Must(),
Address: DefaultAddress, Address: DefaultAddress,
Token: DefaultToken, Token: DefaultToken,
Logger: logger.DefaultLogger, Logger: logger.DefaultLogger,

View File

@@ -1,8 +1,8 @@
package transport package transport
import ( import (
"github.com/unistack-org/micro/v3/network/transport" "go.unistack.org/micro/v3/network/transport"
"github.com/unistack-org/micro/v3/network/tunnel" "go.unistack.org/micro/v3/network/tunnel"
) )
type tunListener struct { type tunListener struct {

View File

@@ -1,12 +1,12 @@
// Package transport provides a tunnel transport // Package transport provides a tunnel transport
package transport package transport // import "go.unistack.org/micro/v3/network/tunnel/transport"
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/unistack-org/micro/v3/network/transport" "go.unistack.org/micro/v3/network/transport"
"github.com/unistack-org/micro/v3/network/tunnel" "go.unistack.org/micro/v3/network/tunnel"
) )
type tunTransport struct { type tunTransport struct {
@@ -37,7 +37,7 @@ func (t *tunTransport) Init(opts ...transport.Option) error {
// get the transport // get the transport
tr, ok := t.options.Context.Value(transportKey{}).(transport.Transport) tr, ok := t.options.Context.Value(transportKey{}).(transport.Transport)
if ok { if ok {
tun.Init(tunnel.Transport(tr)) _ = tun.Init(tunnel.Transport(tr))
} }
// set the tunnel // set the tunnel

View File

@@ -1,12 +1,12 @@
// Package tunnel provides gre network tunnelling // Package tunnel provides gre network tunnelling
package tunnel package tunnel // import "go.unistack.org/micro/v3/network/transport/tunnel"
import ( import (
"context" "context"
"errors" "errors"
"time" "time"
"github.com/unistack-org/micro/v3/network/transport" "go.unistack.org/micro/v3/network/transport"
) )
// DefaultTunnel contains default tunnel implementation // DefaultTunnel contains default tunnel implementation

View File

@@ -5,18 +5,18 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/unistack-org/micro/v3/auth" "go.unistack.org/micro/v3/auth"
"github.com/unistack-org/micro/v3/broker" "go.unistack.org/micro/v3/broker"
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/config" "go.unistack.org/micro/v3/config"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/register" "go.unistack.org/micro/v3/register"
"github.com/unistack-org/micro/v3/router" "go.unistack.org/micro/v3/router"
"github.com/unistack-org/micro/v3/server" "go.unistack.org/micro/v3/server"
"github.com/unistack-org/micro/v3/store" "go.unistack.org/micro/v3/store"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Options for micro service // Options for micro service

View File

@@ -1,5 +1,5 @@
// Package http enables the http profiler // Package http enables the http profiler
package http package http // import "go.unistack.org/micro/v3/profiler/http"
import ( import (
"context" "context"
@@ -7,7 +7,7 @@ import (
"net/http/pprof" "net/http/pprof"
"sync" "sync"
profile "github.com/unistack-org/micro/v3/profiler" profile "go.unistack.org/micro/v3/profiler"
) )
type httpProfile struct { type httpProfile struct {

View File

@@ -1,5 +1,5 @@
// Package pprof provides a pprof profiler which writes output to /tmp/[name].{cpu,mem}.pprof // Package pprof provides a pprof profiler which writes output to /tmp/[name].{cpu,mem}.pprof
package pprof package pprof // import "go.unistack.org/micro/v3/profiler/pprof"
import ( import (
"os" "os"
@@ -9,7 +9,7 @@ import (
"sync" "sync"
"time" "time"
profile "github.com/unistack-org/micro/v3/profiler" profile "go.unistack.org/micro/v3/profiler"
) )
type profiler struct { type profiler struct {
@@ -31,7 +31,7 @@ func (p *profiler) writeHeap(f *os.File) {
select { select {
case <-t.C: case <-t.C:
runtime.GC() runtime.GC()
pprof.WriteHeapProfile(f) _ = pprof.WriteHeapProfile(f)
case <-p.exit: case <-p.exit:
return return
} }

View File

@@ -1,5 +1,5 @@
// Package profiler is for profilers // Package profiler is for profilers
package profiler package profiler // import "go.unistack.org/micro/v3/profiler"
// Profiler interface // Profiler interface
type Profiler interface { type Profiler interface {

View File

@@ -2,11 +2,11 @@
package proxy package proxy
import ( import (
"github.com/unistack-org/micro/v3/client" "go.unistack.org/micro/v3/client"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/router" "go.unistack.org/micro/v3/router"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Options for proxy // Options for proxy

View File

@@ -1,10 +1,10 @@
// Package proxy is a transparent proxy built on the micro/server // Package proxy is a transparent proxy built on the micro/server
package proxy package proxy // import "go.unistack.org/micro/v3/proxy"
import ( import (
"context" "context"
"github.com/unistack-org/micro/v3/server" "go.unistack.org/micro/v3/server"
) )
// DefaultEndpoint holds default proxy address // DefaultEndpoint holds default proxy address

View File

@@ -6,7 +6,7 @@ import (
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
// ExtractValue from reflect.Type from specified depth // ExtractValue from reflect.Type from specified depth

View File

@@ -6,8 +6,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/google/uuid" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/util/id"
) )
var ( var (
@@ -378,13 +378,16 @@ func (m *memory) ListServices(ctx context.Context, opts ...ListOption) ([]*Servi
} }
func (m *memory) Watch(ctx context.Context, opts ...WatchOption) (Watcher, error) { func (m *memory) Watch(ctx context.Context, opts ...WatchOption) (Watcher, error) {
id, err := id.New()
if err != nil {
return nil, err
}
wo := NewWatchOptions(opts...) wo := NewWatchOptions(opts...)
// construct the watcher // construct the watcher
w := &watcher{ w := &watcher{
exit: make(chan bool), exit: make(chan bool),
res: make(chan *Result), res: make(chan *Result),
id: uuid.New().String(), id: id,
wo: wo, wo: wo,
} }

View File

@@ -5,9 +5,9 @@ import (
"crypto/tls" "crypto/tls"
"time" "time"
"github.com/unistack-org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"github.com/unistack-org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
"github.com/unistack-org/micro/v3/tracer" "go.unistack.org/micro/v3/tracer"
) )
// Options holds options for register // Options holds options for register
@@ -44,7 +44,7 @@ func NewOptions(opts ...Option) Options {
return options return options
} }
// nolint: golint // nolint: golint,revive
// RegisterOptions holds options for register method // RegisterOptions holds options for register method
type RegisterOptions struct { type RegisterOptions struct {
Context context.Context Context context.Context
@@ -197,7 +197,7 @@ func TLSConfig(t *tls.Config) Option {
} }
} }
// nolint: golint // nolint: golint,revive
// RegisterAttempts specifies register atempts count // RegisterAttempts specifies register atempts count
func RegisterAttempts(t int) RegisterOption { func RegisterAttempts(t int) RegisterOption {
return func(o *RegisterOptions) { return func(o *RegisterOptions) {
@@ -205,7 +205,7 @@ func RegisterAttempts(t int) RegisterOption {
} }
} }
// nolint: golint // nolint: golint,revive
// RegisterTTL specifies register ttl // RegisterTTL specifies register ttl
func RegisterTTL(t time.Duration) RegisterOption { func RegisterTTL(t time.Duration) RegisterOption {
return func(o *RegisterOptions) { return func(o *RegisterOptions) {
@@ -213,7 +213,7 @@ func RegisterTTL(t time.Duration) RegisterOption {
} }
} }
// nolint: golint // nolint: golint,revive
// RegisterContext sets the register context // RegisterContext sets the register context
func RegisterContext(ctx context.Context) RegisterOption { func RegisterContext(ctx context.Context) RegisterOption {
return func(o *RegisterOptions) { return func(o *RegisterOptions) {
@@ -221,7 +221,7 @@ func RegisterContext(ctx context.Context) RegisterOption {
} }
} }
// nolint: golint // nolint: golint,revive
// RegisterDomain secifies register domain // RegisterDomain secifies register domain
func RegisterDomain(d string) RegisterOption { func RegisterDomain(d string) RegisterOption {
return func(o *RegisterOptions) { return func(o *RegisterOptions) {

View File

@@ -1,11 +1,11 @@
// Package register is an interface for service discovery // Package register is an interface for service discovery
package register package register // import "go.unistack.org/micro/v3/register"
import ( import (
"context" "context"
"errors" "errors"
"github.com/unistack-org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
) )
const ( const (
@@ -68,8 +68,8 @@ type Endpoint struct {
// Option func signature // Option func signature
type Option func(*Options) type Option func(*Options)
// nolint: golint,revive
// RegisterOption option is used to register service // RegisterOption option is used to register service
// nolint: golint
type RegisterOption func(*RegisterOptions) type RegisterOption func(*RegisterOptions)
// WatchOption option is used to watch service changes // WatchOption option is used to watch service changes

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