Compare commits

...

22 Commits

Author SHA1 Message Date
816abc2bbc add copy metadata from grpc-go (#386)
Some checks failed
coverage / build (push) Failing after 1m5s
test / test (push) Successful in 2m10s
Co-authored-by: Василий Толстов <v.tolstov@unistack.org>
Co-authored-by: Vasiliy Tolstov <v.tolstov@unistack.org>
Co-authored-by: vtolstov <vtolstov@users.noreply.github.com>
Reviewed-on: #386
Co-authored-by: Evstigneev Denis <danteevstigneev@yandex.ru>
Co-committed-by: Evstigneev Denis <danteevstigneev@yandex.ru>
2025-01-25 15:57:55 +03:00
f3f2a9b737 move to v4
Some checks failed
coverage / build (push) Failing after 56s
test / test (push) Successful in 2m30s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-01-25 15:48:10 +03:00
3f82cb3ba4 Обновить README.md
All checks were successful
coverage / build (push) Successful in 1m31s
test / test (push) Successful in 2m34s
2025-01-18 15:35:52 +03:00
vtolstov
306b7a3962 Apply Code Coverage Badge 2025-01-17 12:58:03 +00:00
a8eda9d58d Merge pull request 'move set content-type in client publish' (#394) from devstigneev/micro:v3_publish_bug into v3
All checks were successful
coverage / build (push) Successful in 1m19s
test / test (push) Successful in 2m13s
Reviewed-on: #394
2025-01-17 15:57:30 +03:00
7e4477dcb4 move set content-type in client publish
Some checks failed
test / test (pull_request) Successful in 3m40s
lint / lint (pull_request) Successful in 45s
coverage / build (pull_request) Failing after 26s
2025-01-17 15:38:53 +03:00
vtolstov
d846044fc6 Apply Code Coverage Badge 2025-01-04 16:10:26 +00:00
29d956e74e fix readme
All checks were successful
coverage / build (push) Successful in 59s
test / test (push) Successful in 3m27s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-01-04 19:09:50 +03:00
fcc4faff8a fix godoc link
All checks were successful
coverage / build (push) Successful in 56s
test / test (push) Successful in 3m25s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-01-04 18:57:02 +03:00
5df8f83f45 badges (#392)
Some checks failed
coverage / build (push) Successful in 57s
test / test (push) Has been cancelled
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
Co-authored-by: vtolstov <vtolstov@users.noreply.github.com>
Reviewed-on: #392
Co-authored-by: Vasiliy Tolstov <v.tolstov@unistack.org>
Co-committed-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-01-04 18:53:57 +03:00
vtolstov
27fa6e9173 Apply Code Coverage Badge 2024-12-28 22:58:19 +00:00
bd55a35dc3 logger/slog: add delayed buffer test
All checks were successful
test / test (push) Successful in 3m33s
coverage / build (push) Successful in 8m22s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-29 01:57:41 +03:00
653bd386cc util/buffer: add DelayedBuffer
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-29 01:57:41 +03:00
vtolstov
558c6f4d7c Apply Code Coverage Badge 2024-12-28 11:56:07 +00:00
d7dd6fbeb2 register/memory: fix build
All checks were successful
test / test (push) Successful in 3m35s
coverage / build (push) Successful in 8m22s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-28 14:55:20 +03:00
a00cf2c8d9 register: watcher fixes
Some checks failed
coverage / build (push) Failing after 55s
test / test (push) Successful in 3m39s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-28 14:51:10 +03:00
vtolstov
a3e8ab2492 Apply Code Coverage Badge 2024-12-27 20:57:08 +00:00
06da500ef4 register: cleanup
All checks were successful
test / test (push) Successful in 3m33s
coverage / build (push) Successful in 9m11s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-27 23:56:27 +03:00
277f04ba19 register: add Codec option
All checks were successful
coverage / build (push) Successful in 1m3s
test / test (push) Successful in 3m31s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-27 19:33:50 +03:00
vtolstov
470263ff5f Apply Code Coverage Badge 2024-12-27 16:14:00 +00:00
b8232e02be register: add ListName option
All checks were successful
test / test (push) Successful in 3m50s
coverage / build (push) Successful in 8m15s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-27 19:12:57 +03:00
vtolstov
f8c5e10c1d Apply Code Coverage Badge 2024-12-26 22:21:35 +00:00
108 changed files with 761 additions and 373 deletions

View File

@@ -26,24 +26,24 @@ jobs:
- name: test coverage - name: test coverage
run: | run: |
go test -v -cover ./... -coverprofile coverage.out -coverpkg ./... go test -v -cover ./... -covermode=count -coverprofile coverage.out -coverpkg ./...
go tool cover -func coverage.out -o coverage.out go tool cover -func coverage.out -o coverage.out
- name: coverage badge - name: coverage badge
uses: tj-actions/coverage-badge-go@v1 uses: tj-actions/coverage-badge-go@v2
with: with:
green: 80 green: 80
filename: coverage.out filename: coverage.out
- uses: stefanzweifel/git-auto-commit-action@v4 - uses: stefanzweifel/git-auto-commit-action@v4
id: auto-commit-action name: autocommit
with: with:
commit_message: Apply Code Coverage Badge commit_message: Apply Code Coverage Badge
skip_fetch: true skip_fetch: true
skip_checkout: true skip_checkout: true
file_pattern: ./README.md file_pattern: ./README.md
- name: Push Changes - name: push
if: steps.auto-commit-action.outputs.changes_detected == 'true' if: steps.auto-commit-action.outputs.changes_detected == 'true'
uses: ad-m/github-push-action@master uses: ad-m/github-push-action@master
with: with:

View File

@@ -1,5 +1,9 @@
# Micro # Micro
![Coverage](https://img.shields.io/badge/Coverage-45.1%25-yellow) ![Coverage](https://img.shields.io/badge/Coverage-44.6%25-yellow)
[![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Doc](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/go.unistack.org/micro/v3?tab=overview)
[![Status](https://git.unistack.org/unistack-org/micro/actions/workflows/job_tests.yml/badge.svg?branch=v3)](https://git.unistack.org/unistack-org/micro/actions?query=workflow%3Abuild+branch%3Av3+event%3Apush)
[![Lint](https://goreportcard.com/badge/go.unistack.org/micro/v3)](https://goreportcard.com/report/go.unistack.org/micro/v3)
Micro is a standard library for microservices. Micro is a standard library for microservices.
@@ -11,30 +15,20 @@ Micro provides the core requirements for distributed systems development includi
Micro abstracts away the details of distributed systems. Here are the main features. Micro abstracts away the details of distributed systems. Here are the main features.
- **Authentication** - Auth is built in as a first class citizen. Authentication and authorization enable secure
zero trust networking by providing every service an identity and certificates. This additionally includes rule
based access control.
- **Dynamic Config** - Load and hot reload dynamic config from anywhere. The config interface provides a way to load application - **Dynamic Config** - Load and hot reload dynamic config from anywhere. The config interface provides a way to load application
level config from any source such as env vars, file, etcd. You can merge the sources and even define fallbacks. level config from any source such as env vars, cmdline, file, consul, vault... You can merge the sources and even define fallbacks.
- **Data Storage** - A simple data store interface to read, write and delete records. It includes support for memory, file and - **Data Storage** - A simple data store interface to read, write and delete records. It includes support for memory, file and
CockroachDB by default. State and persistence becomes a core requirement beyond prototyping and Micro looks to build that into the framework. s3. State and persistence becomes a core requirement beyond prototyping and Micro looks to build that into the framework.
- **Service Discovery** - Automatic service registration and name resolution. Service discovery is at the core of micro service - **Service Discovery** - Automatic service registration and name resolution. Service discovery is at the core of micro service
development. When service A needs to speak to service B it needs the location of that service. development. When service A needs to speak to service B it needs the location of that service.
- **Load Balancing** - Client side load balancing built on service discovery. Once we have the addresses of any number of instances
of a service we now need a way to decide which node to route to. We use random hashed load balancing to provide even distribution
across the services and retry a different node if there's a problem.
- **Message Encoding** - Dynamic message encoding based on content-type. The client and server will use codecs along with content-type - **Message Encoding** - Dynamic message encoding based on content-type. The client and server will use codecs along with content-type
to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client
and server handle this by default. and server handle this by default.
- **Transport** - gRPC or http based request/response with support for bidirectional streaming. We provide an abstraction for synchronous communication. A request made to a service will be automatically resolved, load balanced, dialled and streamed. - **Async Messaging** - Pub/Sub is built in as a first class citizen for asynchronous communication and event driven architectures.
- **Async Messaging** - PubSub is built in as a first class citizen for asynchronous communication and event driven architectures.
Event notifications are a core pattern in micro service development. Event notifications are a core pattern in micro service development.
- **Synchronization** - Distributed systems are often built in an eventually consistent manner. Support for distributed locking and - **Synchronization** - Distributed systems are often built in an eventually consistent manner. Support for distributed locking and
@@ -43,10 +37,6 @@ leadership are built in as a Sync interface. When using an eventually consistent
- **Pluggable Interfaces** - Micro makes use of Go interfaces for each system abstraction. Because of this these interfaces - **Pluggable Interfaces** - Micro makes use of Go interfaces for each system abstraction. Because of this these interfaces
are pluggable and allows Micro to be runtime agnostic. are pluggable and allows Micro to be runtime agnostic.
## Getting Started
To be created.
## License ## License
Micro is Apache 2.0 licensed. Micro is Apache 2.0 licensed.

View File

@@ -6,8 +6,8 @@ import (
"errors" "errors"
"time" "time"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
// DefaultBroker default memory broker // DefaultBroker default memory broker

View File

@@ -4,14 +4,14 @@ import (
"context" "context"
"sync" "sync"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
maddr "go.unistack.org/micro/v3/util/addr" maddr "go.unistack.org/micro/v4/util/addr"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
mnet "go.unistack.org/micro/v3/util/net" mnet "go.unistack.org/micro/v4/util/net"
"go.unistack.org/micro/v3/util/rand" "go.unistack.org/micro/v4/util/rand"
) )
type memoryBroker struct { type memoryBroker struct {

View File

@@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"testing" "testing"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
func TestMemoryBatchBroker(t *testing.T) { func TestMemoryBatchBroker(t *testing.T) {

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"strings" "strings"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
) )
type NoopBroker struct { type NoopBroker struct {

View File

@@ -5,13 +5,13 @@ import (
"crypto/tls" "crypto/tls"
"time" "time"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/sync" "go.unistack.org/micro/v4/sync"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// Options struct // Options struct

View File

@@ -5,7 +5,7 @@ import (
"math" "math"
"time" "time"
"go.unistack.org/micro/v3/util/backoff" "go.unistack.org/micro/v4/util/backoff"
) )
// BackoffFunc is the backoff call func // BackoffFunc is the backoff call func

View File

@@ -5,8 +5,8 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
var ( var (

View File

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

View File

@@ -7,14 +7,14 @@ import (
"strconv" "strconv"
"time" "time"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/errors" "go.unistack.org/micro/v4/errors"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
"go.unistack.org/micro/v3/semconv" "go.unistack.org/micro/v4/semconv"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// DefaultCodecs will be used to encode/decode data // DefaultCodecs will be used to encode/decode data
@@ -588,7 +588,6 @@ func (n *noopClient) publish(ctx context.Context, ps []Message, opts ...PublishO
for _, p := range ps { for _, p := range ps {
md := metadata.Copy(omd) md := metadata.Copy(omd)
md[metadata.HeaderContentType] = p.ContentType()
topic := p.Topic() topic := p.Topic()
if len(exchange) > 0 { if len(exchange) > 0 {
topic = exchange topic = exchange
@@ -600,6 +599,8 @@ func (n *noopClient) publish(ctx context.Context, ps []Message, opts ...PublishO
md.Set(k, v) md.Set(k, v)
} }
md[metadata.HeaderContentType] = p.ContentType()
var body []byte var body []byte
// passed in raw data // passed in raw data

View File

@@ -6,17 +6,17 @@ import (
"net" "net"
"time" "time"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/router" "go.unistack.org/micro/v4/router"
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
"go.unistack.org/micro/v3/selector/random" "go.unistack.org/micro/v4/selector/random"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// Options holds client options // Options holds client options

View File

@@ -3,7 +3,7 @@ package client
import ( import (
"context" "context"
"go.unistack.org/micro/v3/errors" "go.unistack.org/micro/v4/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

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"go.unistack.org/micro/v3/errors" "go.unistack.org/micro/v4/errors"
) )
func TestRetryAlways(t *testing.T) { func TestRetryAlways(t *testing.T) {

View File

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

View File

@@ -3,7 +3,7 @@ package cluster
import ( import (
"context" "context"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
// Message sent to member in cluster // Message sent to member in cluster

View File

@@ -3,9 +3,9 @@ package codec
import ( import (
"context" "context"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// Option func // Option func

View File

@@ -9,10 +9,10 @@ import (
"dario.cat/mergo" "dario.cat/mergo"
"github.com/google/uuid" "github.com/google/uuid"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
mid "go.unistack.org/micro/v3/util/id" mid "go.unistack.org/micro/v4/util/id"
rutil "go.unistack.org/micro/v3/util/reflect" rutil "go.unistack.org/micro/v4/util/reflect"
mtime "go.unistack.org/micro/v3/util/time" mtime "go.unistack.org/micro/v4/util/time"
) )
type defaultConfig struct { type defaultConfig struct {
@@ -210,7 +210,7 @@ func fillValue(value reflect.Value, val string) error {
return err return err
} }
value.Set(reflect.ValueOf(v)) value.Set(reflect.ValueOf(v))
case value.Type().String() == "time.Duration" && value.Type().PkgPath() == "go.unistack.org/micro/v3/util/time": case value.Type().String() == "time.Duration" && value.Type().PkgPath() == "go.unistack.org/micro/v4/util/time":
v, err := mtime.ParseDuration(val) v, err := mtime.ParseDuration(val)
if err != nil { if err != nil {
return err return err

View File

@@ -7,8 +7,8 @@ import (
"testing" "testing"
"time" "time"
"go.unistack.org/micro/v3/config" "go.unistack.org/micro/v4/config"
mtime "go.unistack.org/micro/v3/util/time" mtime "go.unistack.org/micro/v4/util/time"
) )
type cfg struct { type cfg struct {

View File

@@ -4,11 +4,11 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// Options hold the config options // Options hold the config options

View File

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

View File

@@ -6,12 +6,12 @@ import (
"sync" "sync"
"github.com/silas/dag" "github.com/silas/dag"
"go.unistack.org/micro/v3/client" "go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/store" "go.unistack.org/micro/v4/store"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
type microFlow struct { type microFlow struct {

View File

@@ -7,7 +7,7 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
var ( var (

View File

@@ -4,11 +4,11 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/client" "go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/store" "go.unistack.org/micro/v4/store"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// Option func // Option func

View File

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
) )
func TestFSMStart(t *testing.T) { func TestFSMStart(t *testing.T) {

12
go.mod
View File

@@ -1,11 +1,11 @@
module go.unistack.org/micro/v3 module go.unistack.org/micro/v4
go 1.22.0 go 1.22.0
require ( require (
dario.cat/mergo v1.0.1 dario.cat/mergo v1.0.1
github.com/DATA-DOG/go-sqlmock v1.5.2 github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/KimMachineGun/automemlimit v0.6.1 github.com/KimMachineGun/automemlimit v0.7.0
github.com/ash3in/uuidv8 v1.2.0 github.com/ash3in/uuidv8 v1.2.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/matoous/go-nanoid v1.5.1 github.com/matoous/go-nanoid v1.5.1
@@ -14,8 +14,8 @@ require (
go.uber.org/automaxprocs v1.6.0 go.uber.org/automaxprocs v1.6.0
go.unistack.org/micro-proto/v3 v3.4.1 go.unistack.org/micro-proto/v3 v3.4.1
golang.org/x/sync v0.10.0 golang.org/x/sync v0.10.0
google.golang.org/grpc v1.69.2 google.golang.org/grpc v1.69.4
google.golang.org/protobuf v1.36.1 google.golang.org/protobuf v1.36.3
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
@@ -36,8 +36,8 @@ require (
github.com/stretchr/testify v1.10.0 // indirect github.com/stretchr/testify v1.10.0 // indirect
go.uber.org/goleak v1.3.0 // indirect go.uber.org/goleak v1.3.0 // indirect
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
golang.org/x/net v0.33.0 // indirect golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/sys v0.29.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
) )

View File

@@ -8,7 +8,7 @@ import (
"slices" "slices"
"time" "time"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
) )
// Option func signature // Option func signature

View File

@@ -13,9 +13,9 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/semconv" "go.unistack.org/micro/v4/semconv"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
const ( const (

View File

@@ -12,8 +12,9 @@ import (
"time" "time"
"github.com/google/uuid" "github.com/google/uuid"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v4/util/buffer"
) )
// always first to have proper check // always first to have proper check
@@ -30,11 +31,30 @@ func TestStacktrace(t *testing.T) {
l.Error(ctx, "msg1", errors.New("err")) l.Error(ctx, "msg1", errors.New("err"))
if !bytes.Contains(buf.Bytes(), []byte(`slog_test.go:31`)) { if !bytes.Contains(buf.Bytes(), []byte(`slog_test.go:32`)) {
t.Fatalf("logger error not works, buf contains: %s", buf.Bytes()) t.Fatalf("logger error not works, buf contains: %s", buf.Bytes())
} }
} }
func TestDelayedBuffer(t *testing.T) {
ctx := context.TODO()
buf := bytes.NewBuffer(nil)
dbuf := buffer.NewDelayedBuffer(100, 100*time.Millisecond, buf)
l := NewLogger(logger.WithLevel(logger.ErrorLevel), logger.WithOutput(dbuf),
WithHandlerFunc(slog.NewTextHandler),
logger.WithAddStacktrace(true),
)
if err := l.Init(logger.WithFields("key1", "val1")); err != nil {
t.Fatal(err)
}
l.Error(ctx, "msg1", errors.New("err"))
time.Sleep(120 * time.Millisecond)
if !bytes.Contains(buf.Bytes(), []byte(`key1=val1`)) {
t.Fatalf("logger delayed buffer not works, buf contains: %s", buf.Bytes())
}
}
func TestTime(t *testing.T) { func TestTime(t *testing.T) {
ctx := context.TODO() ctx := context.TODO()
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)

View File

@@ -8,7 +8,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
) )
const sf = "0-+# " const sf = "0-+# "

View File

@@ -5,7 +5,7 @@ import (
"strings" "strings"
"testing" "testing"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
) )
func TestUnwrap(t *testing.T) { func TestUnwrap(t *testing.T) {

View File

@@ -1,3 +1,5 @@
//go:build !exclude
// Package metadata is a way of defining message headers // Package metadata is a way of defining message headers
package metadata package metadata

View File

@@ -1,3 +1,5 @@
//go:build !exclude
// Package metadata is a way of defining message headers // Package metadata is a way of defining message headers
package metadata package metadata

282
metadata/metadata_grpc.go Normal file
View File

@@ -0,0 +1,282 @@
//go:build exclude
// Package metadata TODO need compare with micro metadata
package metadata // import "google.golang.org/grpc/metadata"
import (
"context"
"fmt"
"strings"
)
// MD is a mapping from metadata keys to values. Users should use the following
// two convenience functions New and Pairs to generate MD.
type MD map[string][]string
type Metadata map[string]string
// New creates an MD from a given key-value map.
//
// Only the following ASCII characters are allowed in keys:
// - digits: 0-9
// - uppercase letters: A-Z (normalized to lower)
// - lowercase letters: a-z
// - special characters: -_.
//
// Uppercase letters are automatically converted to lowercase.
//
// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
// result in errors if set in metadata.
func New(m map[string]string) MD {
md := make(MD, len(m))
for k, val := range m {
key := strings.ToLower(k)
md[key] = append(md[key], val)
}
return md
}
// Pairs returns an MD formed by the mapping of key, value ...
// Pairs panics if len(kv) is odd.
//
// Only the following ASCII characters are allowed in keys:
// - digits: 0-9
// - uppercase letters: A-Z (normalized to lower)
// - lowercase letters: a-z
// - special characters: -_.
//
// Uppercase letters are automatically converted to lowercase.
//
// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
// result in errors if set in metadata.
func Pairs(kv ...string) MD {
if len(kv)%2 == 1 {
panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
}
md := make(MD, len(kv)/2)
for i := 0; i < len(kv); i += 2 {
key := strings.ToLower(kv[i])
md[key] = append(md[key], kv[i+1])
}
return md
}
// Len returns the number of items in md.
func (md MD) Len() int {
return len(md)
}
// Copy returns a copy of md.
func (md MD) Copy() MD {
out := make(MD, len(md))
for k, v := range md {
out[k] = copyOf(v)
}
return out
}
// Get obtains the values for a given key.
//
// k is converted to lowercase before searching in md.
func (md MD) Get(k string) []string {
k = strings.ToLower(k)
return md[k]
}
// Set sets the value of a given key with a slice of values.
//
// k is converted to lowercase before storing in md.
func (md MD) Set(k string, vals ...string) {
if len(vals) == 0 {
return
}
k = strings.ToLower(k)
md[k] = vals
}
// Append adds the values to key k, not overwriting what was already stored at
// that key.
//
// k is converted to lowercase before storing in md.
func (md MD) Append(k string, vals ...string) {
if len(vals) == 0 {
return
}
k = strings.ToLower(k)
md[k] = append(md[k], vals...)
}
// Delete removes the values for a given key k which is converted to lowercase
// before removing it from md.
func (md MD) Delete(k string) {
k = strings.ToLower(k)
delete(md, k)
}
// Join joins any number of mds into a single MD.
//
// The order of values for each key is determined by the order in which the mds
// containing those values are presented to Join.
func Join(mds ...MD) MD {
out := MD{}
for _, md := range mds {
for k, v := range md {
out[k] = append(out[k], v...)
}
}
return out
}
type mdIncomingKey struct{}
type mdOutgoingKey struct{}
// NewIncomingContext creates a new context with incoming md attached. md must
// not be modified after calling this function.
func NewIncomingContext(ctx context.Context, md Metadata) context.Context {
in := make(MD, len(md))
for k, v := range md {
in[k] = []string{v}
}
return context.WithValue(ctx, mdIncomingKey{}, in)
}
// NewOutgoingContext creates a new context with outgoing md attached. If used
// in conjunction with AppendToOutgoingContext, NewOutgoingContext will
// overwrite any previously-appended metadata. md must not be modified after
// calling this function.
func NewOutgoingContext(ctx context.Context, md Metadata) context.Context {
out := make(MD, len(md))
for k, v := range md {
out[k] = []string{v}
}
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: out})
}
// AppendToOutgoingContext returns a new context with the provided kv merged
// with any existing metadata in the context. Please refer to the documentation
// of Pairs for a description of kv.
func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
if len(kv)%2 == 1 {
panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv)))
}
md, _ := ctx.Value(mdOutgoingKey{}).(rawMD)
added := make([][]string, len(md.added)+1)
copy(added, md.added)
kvCopy := make([]string, 0, len(kv))
for i := 0; i < len(kv); i += 2 {
kvCopy = append(kvCopy, strings.ToLower(kv[i]), kv[i+1])
}
added[len(added)-1] = kvCopy
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added})
}
// FromIncomingContext returns the incoming metadata in ctx if it exists.
//
// All keys in the returned MD are lowercase.
func FromIncomingContext(ctx context.Context) (Metadata, bool) {
md, ok := ctx.Value(mdIncomingKey{}).(MD)
if !ok {
return nil, false
}
out := make(Metadata, len(md))
for k, v := range md {
// We need to manually convert all keys to lower case, because MD is a
// map, and there's no guarantee that the MD attached to the context is
// created using our helper functions.
if len(v) > 0 {
key := strings.ToLower(k)
out[key] = v[0]
}
}
return out, true
}
// ValueFromIncomingContext returns the metadata value corresponding to the metadata
// key from the incoming metadata if it exists. Keys are matched in a case insensitive
// manner.
func ValueFromIncomingContext(ctx context.Context, key string) []string {
md, ok := ctx.Value(mdIncomingKey{}).(MD)
if !ok {
return nil
}
if v, ok := md[key]; ok {
return copyOf(v)
}
for k, v := range md {
// Case insensitive comparison: MD is a map, and there's no guarantee
// that the MD attached to the context is created using our helper
// functions.
if strings.EqualFold(k, key) {
return copyOf(v)
}
}
return nil
}
func copyOf(v []string) []string {
vals := make([]string, len(v))
copy(vals, v)
return vals
}
// fromOutgoingContextRaw returns the un-merged, intermediary contents of rawMD.
//
// Remember to perform strings.ToLower on the keys, for both the returned MD (MD
// is a map, there's no guarantee it's created using our helper functions) and
// the extra kv pairs (AppendToOutgoingContext doesn't turn them into
// lowercase).
func fromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) {
raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
if !ok {
return nil, nil, false
}
return raw.md, raw.added, true
}
// FromOutgoingContext returns the outgoing metadata in ctx if it exists.
//
// All keys in the returned MD are lowercase.
func FromOutgoingContext(ctx context.Context) (Metadata, bool) {
raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
if !ok {
return nil, false
}
mdSize := len(raw.md)
for i := range raw.added {
mdSize += len(raw.added[i]) / 2
}
out := make(Metadata, mdSize)
for k, v := range raw.md {
// We need to manually convert all keys to lower case, because MD is a
// map, and there's no guarantee that the MD attached to the context is
// created using our helper functions.
if len(v) > 0 {
key := strings.ToLower(k)
out[key] = v[0]
}
}
for _, added := range raw.added {
if len(added)%2 == 1 {
panic(fmt.Sprintf("metadata: FromOutgoingContext got an odd number of input pairs for metadata: %d", len(added)))
}
for i := 0; i < len(added); i += 2 {
key := strings.ToLower(added[i])
out[key] = added[i+1]
}
}
return out, ok
}
type rawMD struct {
md MD
added [][]string
}

View File

@@ -3,21 +3,21 @@ package micro
import ( import (
"reflect" "reflect"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/client" "go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/flow" "go.unistack.org/micro/v4/flow"
"go.unistack.org/micro/v3/fsm" "go.unistack.org/micro/v4/fsm"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/resolver" "go.unistack.org/micro/v4/resolver"
"go.unistack.org/micro/v3/router" "go.unistack.org/micro/v4/router"
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
"go.unistack.org/micro/v3/server" "go.unistack.org/micro/v4/server"
"go.unistack.org/micro/v3/store" "go.unistack.org/micro/v4/store"
"go.unistack.org/micro/v3/sync" "go.unistack.org/micro/v4/sync"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
func As(b any, target any) bool { func As(b any, target any) bool {

View File

@@ -6,8 +6,8 @@ import (
"reflect" "reflect"
"testing" "testing"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/fsm" "go.unistack.org/micro/v4/fsm"
) )
func TestAs(t *testing.T) { func TestAs(t *testing.T) {

View File

@@ -2,8 +2,8 @@
package network package network
import ( import (
"go.unistack.org/micro/v3/client" "go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v3/server" "go.unistack.org/micro/v4/server"
) )
// Error is network node errors // Error is network node errors

View File

@@ -1,13 +1,13 @@
package network package network
import ( import (
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/network/tunnel" "go.unistack.org/micro/v4/network/tunnel"
"go.unistack.org/micro/v3/proxy" "go.unistack.org/micro/v4/proxy"
"go.unistack.org/micro/v3/router" "go.unistack.org/micro/v4/router"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
// Option func // Option func

View File

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

View File

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

View File

@@ -5,7 +5,7 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
var ( var (

View File

@@ -5,11 +5,11 @@ import (
"context" "context"
"fmt" "fmt"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/network/transport" "go.unistack.org/micro/v4/network/transport"
"go.unistack.org/micro/v3/network/tunnel" "go.unistack.org/micro/v4/network/tunnel"
) )
type tunBroker struct { type tunBroker struct {

View File

@@ -3,11 +3,11 @@ package tunnel
import ( import (
"time" "time"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/network/transport" "go.unistack.org/micro/v4/network/transport"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
var ( var (

View File

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

View File

@@ -5,8 +5,8 @@ import (
"context" "context"
"fmt" "fmt"
"go.unistack.org/micro/v3/network/transport" "go.unistack.org/micro/v4/network/transport"
"go.unistack.org/micro/v3/network/tunnel" "go.unistack.org/micro/v4/network/tunnel"
) )
type tunTransport struct { type tunTransport struct {

View File

@@ -6,7 +6,7 @@ import (
"errors" "errors"
"time" "time"
"go.unistack.org/micro/v3/network/transport" "go.unistack.org/micro/v4/network/transport"
) )
// DefaultTunnel contains default tunnel implementation // DefaultTunnel contains default tunnel implementation

View File

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

View File

@@ -7,7 +7,7 @@ import (
"net/http/pprof" "net/http/pprof"
"sync" "sync"
profile "go.unistack.org/micro/v3/profiler" profile "go.unistack.org/micro/v4/profiler"
) )
type httpProfile struct { type httpProfile struct {

View File

@@ -9,7 +9,7 @@ import (
"sync" "sync"
"time" "time"
profile "go.unistack.org/micro/v3/profiler" profile "go.unistack.org/micro/v4/profiler"
) )
type profiler struct { type profiler struct {

View File

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

View File

@@ -4,7 +4,7 @@ package proxy
import ( import (
"context" "context"
"go.unistack.org/micro/v3/server" "go.unistack.org/micro/v4/server"
) )
// DefaultEndpoint holds default proxy address // DefaultEndpoint holds default proxy address

View File

@@ -6,9 +6,9 @@ import (
"sync" "sync"
"time" "time"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
var ( var (
@@ -149,7 +149,7 @@ func (m *memory) Register(_ context.Context, s *register.Service, opts ...regist
m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register added new service: %s, version: %s", s.Name, s.Version)) m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register added new service: %s, version: %s", s.Name, s.Version))
} }
m.records[options.Namespace] = srvs m.records[options.Namespace] = srvs
go m.sendEvent(&register.Result{Action: "create", Service: s}) go m.sendEvent(&register.Result{Action: register.EventCreate, Service: s})
} }
var addedNodes bool var addedNodes bool
@@ -185,7 +185,7 @@ func (m *memory) Register(_ context.Context, s *register.Service, opts ...regist
if m.opts.Logger.V(logger.DebugLevel) { if m.opts.Logger.V(logger.DebugLevel) {
m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register added new node to service: %s, version: %s", s.Name, s.Version)) m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register added new node to service: %s, version: %s", s.Name, s.Version))
} }
go m.sendEvent(&register.Result{Action: "update", Service: s}) go m.sendEvent(&register.Result{Action: register.EventUpdate, Service: s})
} else { } else {
// refresh TTL and timestamp // refresh TTL and timestamp
for _, n := range s.Nodes { for _, n := range s.Nodes {
@@ -238,7 +238,7 @@ func (m *memory) Deregister(ctx context.Context, s *register.Service, opts ...re
// is cleanup // is cleanup
if len(version.Nodes) > 0 { if len(version.Nodes) > 0 {
m.records[options.Namespace][s.Name][s.Version] = version m.records[options.Namespace][s.Name][s.Version] = version
go m.sendEvent(&register.Result{Action: "update", Service: s}) go m.sendEvent(&register.Result{Action: register.EventUpdate, Service: s})
return nil return nil
} }
@@ -246,7 +246,7 @@ func (m *memory) Deregister(ctx context.Context, s *register.Service, opts ...re
// register and exit // register and exit
if len(versions) == 1 { if len(versions) == 1 {
delete(m.records[options.Namespace], s.Name) delete(m.records[options.Namespace], s.Name)
go m.sendEvent(&register.Result{Action: "delete", Service: s}) go m.sendEvent(&register.Result{Action: register.EventDelete, Service: s})
if m.opts.Logger.V(logger.DebugLevel) { if m.opts.Logger.V(logger.DebugLevel) {
m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register removed service: %s", s.Name)) m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register removed service: %s", s.Name))
@@ -256,7 +256,7 @@ func (m *memory) Deregister(ctx context.Context, s *register.Service, opts ...re
// there are other versions of the service running, so only remove this version of it // there are other versions of the service running, so only remove this version of it
delete(m.records[options.Namespace][s.Name], s.Version) delete(m.records[options.Namespace][s.Name], s.Version)
go m.sendEvent(&register.Result{Action: "delete", Service: s}) go m.sendEvent(&register.Result{Action: register.EventDelete, Service: s})
if m.opts.Logger.V(logger.DebugLevel) { if m.opts.Logger.V(logger.DebugLevel) {
m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register removed service: %s, version: %s", s.Name, s.Version)) m.opts.Logger.Debug(m.opts.Context, fmt.Sprintf("Register removed service: %s, version: %s", s.Name, s.Version))
} }

View File

@@ -7,7 +7,7 @@ import (
"testing" "testing"
"time" "time"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
) )
var testData = map[string][]*register.Service{ var testData = map[string][]*register.Service{

View File

@@ -5,9 +5,10 @@ import (
"crypto/tls" "crypto/tls"
"time" "time"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v4/tracer"
) )
// Options holds options for register // Options holds options for register
@@ -26,6 +27,8 @@ type Options struct {
Name string Name string
// Addrs specifies register addrs // Addrs specifies register addrs
Addrs []string Addrs []string
// Codec used to marshal/unmarshal data in register
Codec codec.Codec
// Timeout specifies timeout // Timeout specifies timeout
Timeout time.Duration Timeout time.Duration
} }
@@ -37,6 +40,7 @@ func NewOptions(opts ...Option) Options {
Meter: meter.DefaultMeter, Meter: meter.DefaultMeter,
Tracer: tracer.DefaultTracer, Tracer: tracer.DefaultTracer,
Context: context.Background(), Context: context.Background(),
Codec: codec.NewCodec(),
} }
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
@@ -130,6 +134,7 @@ func NewLookupOptions(opts ...LookupOption) LookupOptions {
// ListOptions holds the list options for list method // ListOptions holds the list options for list method
type ListOptions struct { type ListOptions struct {
// Context used to store additional options
Context context.Context Context context.Context
// Namespace to scope the request to // Namespace to scope the request to
Namespace string Namespace string
@@ -300,3 +305,9 @@ func Name(n string) Option {
o.Name = n o.Name = n
} }
} }
func Codec(c codec.Codec) Option {
return func(o *Options) {
o.Codec = c
}
}

View File

@@ -5,7 +5,7 @@ import (
"context" "context"
"errors" "errors"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
const ( const (

View File

@@ -15,31 +15,31 @@ type Watcher interface {
// the watcher. Actions can be create, update, delete // the watcher. Actions can be create, update, delete
type Result struct { type Result struct {
// Service holds register service // Service holds register service
Service *Service Service *Service `json:"service,omitempty"`
// Action holds the action // Action holds the action
Action string Action EventType `json:"action,omitempty"`
} }
// EventType defines register event type // EventType defines register event type
type EventType int type EventType int
const ( const (
// Create is emitted when a new service is registered // EventCreate is emitted when a new service is registered
Create EventType = iota EventCreate EventType = iota
// Delete is emitted when an existing service is deregistered // EventDelete is emitted when an existing service is deregistered
Delete EventDelete
// Update is emitted when an existing service is updated // EventUpdate is emitted when an existing service is updated
Update EventUpdate
) )
// String returns human readable event type // String returns human readable event type
func (t EventType) String() string { func (t EventType) String() string {
switch t { switch t {
case Create: case EventCreate:
return "create" return "create"
case Delete: case EventDelete:
return "delete" return "delete"
case Update: case EventUpdate:
return "update" return "update"
default: default:
return "unknown" return "unknown"
@@ -49,11 +49,11 @@ func (t EventType) String() string {
// Event is register event // Event is register event
type Event struct { type Event struct {
// Timestamp is event timestamp // Timestamp is event timestamp
Timestamp time.Time Timestamp time.Time `json:"timestamp,omitempty"`
// Service is register service // Service is register service
Service *Service Service *Service `json:"service,omitempty"`
// ID is register id // ID is register id
ID string ID string `json:"id,omitempty"`
// Type defines type of event // Type defines type of event
Type EventType Type EventType `json:"type,omitempty"`
} }

View File

@@ -7,7 +7,7 @@ import (
"sync" "sync"
"time" "time"
"go.unistack.org/micro/v3/resolver" "go.unistack.org/micro/v4/resolver"
) )
// Resolver is a DNS network resolve // Resolver is a DNS network resolve

View File

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"net" "net"
"go.unistack.org/micro/v3/resolver" "go.unistack.org/micro/v4/resolver"
) )
// Resolver is a DNS network resolve // Resolver is a DNS network resolve

View File

@@ -8,7 +8,7 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"go.unistack.org/micro/v3/resolver" "go.unistack.org/micro/v4/resolver"
) )
// nolint: golint,revive // nolint: golint,revive

View File

@@ -2,7 +2,7 @@
package noop package noop
import ( import (
"go.unistack.org/micro/v3/resolver" "go.unistack.org/micro/v4/resolver"
) )
// Resolver contains noop resolver // Resolver contains noop resolver

View File

@@ -4,8 +4,8 @@ package register
import ( import (
"context" "context"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/resolver" "go.unistack.org/micro/v4/resolver"
) )
// Resolver is a register network resolver // Resolver is a register network resolver

View File

@@ -2,7 +2,7 @@
package static package static
import ( import (
"go.unistack.org/micro/v3/resolver" "go.unistack.org/micro/v4/resolver"
) )
// Resolver returns a static list of nodes. In the event the node list // Resolver returns a static list of nodes. In the event the node list

View File

@@ -3,9 +3,9 @@ package router
import ( import (
"context" "context"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
// Options are router options // Options are router options

View File

@@ -3,7 +3,7 @@ package router
import ( import (
"hash/fnv" "hash/fnv"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
var ( var (

View File

@@ -1,8 +1,8 @@
package random package random
import ( import (
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
"go.unistack.org/micro/v3/util/rand" "go.unistack.org/micro/v4/util/rand"
) )
type random struct{} type random struct{}

View File

@@ -3,7 +3,7 @@ package random
import ( import (
"testing" "testing"
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
) )
func TestRandom(t *testing.T) { func TestRandom(t *testing.T) {

View File

@@ -1,8 +1,8 @@
package roundrobin package roundrobin
import ( import (
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
"go.unistack.org/micro/v3/util/rand" "go.unistack.org/micro/v4/util/rand"
) )
// NewSelector returns an initialised round robin selector // NewSelector returns an initialised round robin selector

View File

@@ -3,7 +3,7 @@ package roundrobin
import ( import (
"testing" "testing"
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
) )
func TestRoundRobin(t *testing.T) { func TestRoundRobin(t *testing.T) {

View File

@@ -1,6 +1,6 @@
package server package server
import "go.unistack.org/micro/v3/errors" import "go.unistack.org/micro/v4/errors"
type Error struct { type Error struct {
id string id string

View File

@@ -3,7 +3,7 @@ package server
import ( import (
"testing" "testing"
"go.unistack.org/micro/v3/errors" "go.unistack.org/micro/v4/errors"
) )
func TestError(t *testing.T) { func TestError(t *testing.T) {

View File

@@ -9,16 +9,16 @@ import (
"sync" "sync"
"time" "time"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/errors" "go.unistack.org/micro/v4/errors"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
maddr "go.unistack.org/micro/v3/util/addr" maddr "go.unistack.org/micro/v4/util/addr"
mnet "go.unistack.org/micro/v3/util/net" mnet "go.unistack.org/micro/v4/util/net"
"go.unistack.org/micro/v3/util/rand" "go.unistack.org/micro/v4/util/rand"
) )
// DefaultCodecs will be used to encode/decode // DefaultCodecs will be used to encode/decode

View File

@@ -5,12 +5,12 @@ import (
"fmt" "fmt"
"testing" "testing"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/client" "go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/server" "go.unistack.org/micro/v4/server"
) )
type TestHandler struct { type TestHandler struct {

View File

@@ -7,16 +7,16 @@ import (
"sync" "sync"
"time" "time"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
msync "go.unistack.org/micro/v3/sync" msync "go.unistack.org/micro/v4/sync"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
// Option func // Option func

View File

@@ -4,10 +4,10 @@ import (
"net" "net"
"time" "time"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/util/addr" "go.unistack.org/micro/v4/util/addr"
"go.unistack.org/micro/v3/util/backoff" "go.unistack.org/micro/v4/util/backoff"
) )
var ( var (

View File

@@ -5,8 +5,8 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
) )
// DefaultServer default server // DefaultServer default server

View File

@@ -9,17 +9,17 @@ import (
"github.com/KimMachineGun/automemlimit/memlimit" "github.com/KimMachineGun/automemlimit/memlimit"
"go.uber.org/automaxprocs/maxprocs" "go.uber.org/automaxprocs/maxprocs"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/client" "go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v3/config" "go.unistack.org/micro/v4/config"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/router" "go.unistack.org/micro/v4/router"
"go.unistack.org/micro/v3/server" "go.unistack.org/micro/v4/server"
"go.unistack.org/micro/v3/store" "go.unistack.org/micro/v4/store"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
utildns "go.unistack.org/micro/v3/util/dns" utildns "go.unistack.org/micro/v4/util/dns"
) )
func init() { func init() {

View File

@@ -5,16 +5,16 @@ import (
"reflect" "reflect"
"testing" "testing"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v4/broker"
"go.unistack.org/micro/v3/client" "go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v3/config" "go.unistack.org/micro/v4/config"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/router" "go.unistack.org/micro/v4/router"
"go.unistack.org/micro/v3/server" "go.unistack.org/micro/v4/server"
"go.unistack.org/micro/v3/store" "go.unistack.org/micro/v4/store"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
func TestClient(t *testing.T) { func TestClient(t *testing.T) {

View File

@@ -8,8 +8,8 @@ import (
"time" "time"
cache "github.com/patrickmn/go-cache" cache "github.com/patrickmn/go-cache"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/store" "go.unistack.org/micro/v4/store"
) )
// NewStore returns a memory store // NewStore returns a memory store

View File

@@ -5,7 +5,7 @@ import (
"testing" "testing"
"time" "time"
"go.unistack.org/micro/v3/store" "go.unistack.org/micro/v4/store"
) )
type testHook struct { type testHook struct {

View File

@@ -5,8 +5,8 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
var _ Store = (*noopStore)(nil) var _ Store = (*noopStore)(nil)

View File

@@ -5,12 +5,12 @@ import (
"crypto/tls" "crypto/tls"
"time" "time"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v4/codec"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/options" "go.unistack.org/micro/v4/options"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// Options contains configuration for the Store // Options contains configuration for the Store

View File

@@ -3,9 +3,9 @@ package sync
import ( import (
"time" "time"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
// Options holds the sync options // Options holds the sync options

View File

@@ -4,8 +4,8 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
var _ tracer.Tracer = (*Tracer)(nil) var _ tracer.Tracer = (*Tracer)(nil)

View File

@@ -7,9 +7,9 @@ import (
"strings" "strings"
"testing" "testing"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
"go.unistack.org/micro/v3/logger/slog" "go.unistack.org/micro/v4/logger/slog"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
func TestLoggerWithTracer(t *testing.T) { func TestLoggerWithTracer(t *testing.T) {

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/util/id" "go.unistack.org/micro/v4/util/id"
) )
var _ Tracer = (*noopTracer)(nil) var _ Tracer = (*noopTracer)(nil)

View File

@@ -3,7 +3,7 @@ package tracer
import ( import (
"context" "context"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
) )
type SpanStatus int type SpanStatus int

View File

@@ -4,7 +4,7 @@ package tracer
import ( import (
"context" "context"
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v4/logger"
) )
var ( var (

View File

@@ -1,27 +0,0 @@
package buf
import (
"bytes"
"io"
)
var _ io.Closer = &Buffer{}
// Buffer bytes.Buffer wrapper to satisfie io.Closer interface
type Buffer struct {
*bytes.Buffer
}
// Close reset buffer contents
func (b *Buffer) Close() error {
b.Buffer.Reset()
return nil
}
// New creates new buffer that satisfies Closer interface
func New(b *bytes.Buffer) *Buffer {
if b == nil {
b = bytes.NewBuffer(nil)
}
return &Buffer{b}
}

85
util/buffer/buffer.go Normal file
View File

@@ -0,0 +1,85 @@
package buffer
import (
"io"
"sync"
"time"
)
var _ io.WriteCloser = (*DelayedBuffer)(nil)
// DelayedBuffer is the buffer that holds items until either the buffer filled or a specified time limit is reached
type DelayedBuffer struct {
mu sync.Mutex
maxWait time.Duration
flushTime time.Time
buffer chan []byte
ticker *time.Ticker
w io.Writer
err error
}
func NewDelayedBuffer(size int, maxWait time.Duration, w io.Writer) *DelayedBuffer {
b := &DelayedBuffer{
buffer: make(chan []byte, size),
ticker: time.NewTicker(maxWait),
w: w,
flushTime: time.Now(),
maxWait: maxWait,
}
b.loop()
return b
}
func (b *DelayedBuffer) loop() {
go func() {
for range b.ticker.C {
b.mu.Lock()
if time.Since(b.flushTime) > b.maxWait {
b.flush()
}
b.mu.Unlock()
}
}()
}
func (b *DelayedBuffer) flush() {
bufLen := len(b.buffer)
if bufLen > 0 {
tmp := make([][]byte, bufLen)
for i := 0; i < bufLen; i++ {
tmp[i] = <-b.buffer
}
for _, t := range tmp {
_, b.err = b.w.Write(t)
}
b.flushTime = time.Now()
}
}
func (b *DelayedBuffer) Put(items ...[]byte) {
b.mu.Lock()
for _, item := range items {
select {
case b.buffer <- item:
default:
b.flush()
b.buffer <- item
}
}
b.mu.Unlock()
}
func (b *DelayedBuffer) Close() error {
b.mu.Lock()
b.flush()
close(b.buffer)
b.ticker.Stop()
b.mu.Unlock()
return b.err
}
func (b *DelayedBuffer) Write(data []byte) (int, error) {
b.Put(data)
return len(data), b.err
}

View File

@@ -0,0 +1,22 @@
package buffer
import (
"bytes"
"testing"
"time"
)
func TestTimedBuffer(t *testing.T) {
buf := bytes.NewBuffer(nil)
b := NewDelayedBuffer(100, 300*time.Millisecond, buf)
for i := 0; i < 100; i++ {
_, _ = b.Write([]byte(`test`))
}
if buf.Len() != 0 {
t.Fatal("delayed write not worked")
}
time.Sleep(400 * time.Millisecond)
if buf.Len() == 0 {
t.Fatal("delayed write not worked")
}
}

View File

@@ -7,8 +7,8 @@ import (
"sync" "sync"
"time" "time"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v4/meter"
"go.unistack.org/micro/v3/semconv" "go.unistack.org/micro/v4/semconv"
) )
// DialFunc is a [net.Resolver.Dial] function. // DialFunc is a [net.Resolver.Dial] function.

View File

@@ -8,7 +8,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
grpc_codes "google.golang.org/grpc/codes" grpc_codes "google.golang.org/grpc/codes"
"google.golang.org/grpc/peer" "google.golang.org/grpc/peer"
"google.golang.org/grpc/stats" "google.golang.org/grpc/stats"

View File

@@ -23,7 +23,7 @@ import (
"strings" "strings"
"sync" "sync"
"go.unistack.org/micro/v3/tracer" "go.unistack.org/micro/v4/tracer"
) )
const ( const (

View File

@@ -8,8 +8,8 @@ import (
"net/http" "net/http"
"strings" "strings"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v4/metadata"
"go.unistack.org/micro/v3/selector/random" "go.unistack.org/micro/v4/selector/random"
) )
// Write sets the status and body on a http ResponseWriter // Write sets the status and body on a http ResponseWriter

View File

@@ -9,10 +9,10 @@ import (
"net/http" "net/http"
"testing" "testing"
"go.unistack.org/micro/v3/register" "go.unistack.org/micro/v4/register"
"go.unistack.org/micro/v3/register/memory" "go.unistack.org/micro/v4/register/memory"
"go.unistack.org/micro/v3/router" "go.unistack.org/micro/v4/router"
regRouter "go.unistack.org/micro/v3/router/register" regRouter "go.unistack.org/micro/v4/router/register"
) )
func TestRoundTripper(t *testing.T) { func TestRoundTripper(t *testing.T) {

View File

@@ -1,6 +1,6 @@
package http package http
import "go.unistack.org/micro/v3/router" import "go.unistack.org/micro/v4/router"
// Options struct // Options struct
type Options struct { type Options struct {

View File

@@ -4,8 +4,8 @@ import (
"errors" "errors"
"net/http" "net/http"
"go.unistack.org/micro/v3/router" "go.unistack.org/micro/v4/router"
"go.unistack.org/micro/v3/selector" "go.unistack.org/micro/v4/selector"
) )
type roundTripper struct { type roundTripper struct {

View File

@@ -4,7 +4,7 @@ package jitter
import ( import (
"time" "time"
"go.unistack.org/micro/v3/util/rand" "go.unistack.org/micro/v4/util/rand"
) )
// Random returns a random time to jitter with max cap specified // Random returns a random time to jitter with max cap specified

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"time" "time"
"go.unistack.org/micro/v3/util/rand" "go.unistack.org/micro/v4/util/rand"
) )
// Ticker is similar to time.Ticker but ticks at random intervals between // Ticker is similar to time.Ticker but ticks at random intervals between

View File

@@ -6,7 +6,7 @@ import (
"testing" "testing"
"time" "time"
rutil "go.unistack.org/micro/v3/util/reflect" rutil "go.unistack.org/micro/v4/util/reflect"
) )
func TestStructFields(t *testing.T) { func TestStructFields(t *testing.T) {

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