From fb61066889a681d80645eeab2ff90c746df66d7e Mon Sep 17 00:00:00 2001 From: "dino.ma" Date: Mon, 28 Jun 2021 11:37:52 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9context=E7=9A=84?= =?UTF-8?q?=E8=B6=85=E6=97=B6=E3=80=81=E5=8F=96=E6=B6=88=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/hcontext/README.md | 15 ++++ util/hcontext/hcontext.go | 30 +++++++ util/hcontext/hcontext_test.go | 152 +++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 util/hcontext/README.md create mode 100644 util/hcontext/hcontext.go create mode 100644 util/hcontext/hcontext_test.go diff --git a/util/hcontext/README.md b/util/hcontext/README.md new file mode 100644 index 00000000..203733cf --- /dev/null +++ b/util/hcontext/README.md @@ -0,0 +1,15 @@ +# hcontext + +## 功能 + +对 context.Context 的包装函数 + +## usage + +```golang +//移除超时信息,保留value信息 +ctx = hcontext.WithNoDeadline(ctx) + +//移除取消信息,保留超时和value信息 +ctx = hcontext.WithNoCancel(ctx) +``` diff --git a/util/hcontext/hcontext.go b/util/hcontext/hcontext.go new file mode 100644 index 00000000..29b8bb8e --- /dev/null +++ b/util/hcontext/hcontext.go @@ -0,0 +1,30 @@ +package hcontext + +import ( + "context" + "time" +) + +type valueOnlyContext struct{ context.Context } + +func (valueOnlyContext) Deadline() (deadline time.Time, ok bool) { return } +func (valueOnlyContext) Done() <-chan struct{} { return nil } +func (valueOnlyContext) Err() error { return nil } + +//WithNoDeadline 移除超时控制,保留value信息 +func WithNoDeadline(ctx context.Context) context.Context { + return valueOnlyContext{ctx} +} + +//WithNoCancel 不受上层context cancel的影响,但是保留上层ctx的Deadline信息 +func WithNoCancel(ctx context.Context) context.Context { + deadline, ok := ctx.Deadline() + if ok { + var cancel context.CancelFunc + ctx = WithNoDeadline(ctx) + ctx, cancel = context.WithDeadline(ctx, deadline) + _ = cancel + return ctx + } + return WithNoDeadline(ctx) +} diff --git a/util/hcontext/hcontext_test.go b/util/hcontext/hcontext_test.go new file mode 100644 index 00000000..a7ad500e --- /dev/null +++ b/util/hcontext/hcontext_test.go @@ -0,0 +1,152 @@ +package hcontext + +import ( + "context" + "testing" + "time" + + "gopkg.in/go-playground/assert.v1" +) + +type ctxtype string + +var k ctxtype = "k" + +func TestWithNoDeadline(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + stub func(*testing.T, context.Context) + }{ + { + name: "value正常传递", + args: args{ + context.WithValue(context.TODO(), k, "world"), + }, + stub: func(t *testing.T, ctx context.Context) { + assert.Equal(t, ctx.Value(k).(string), "world") + }, + }, + { + name: "nil Deadline()", + args: args{ + ctx: func() context.Context { + ctx, cancel := context.WithTimeout(context.TODO(), time.Second) + _ = cancel + return ctx + }(), + }, + stub: func(t *testing.T, ctx context.Context) { + deadline, ok := ctx.Deadline() + assert.Equal(t, deadline.IsZero(), true) + assert.Equal(t, ok, false) + + }, + }, + { + name: "nil Done()", + args: args{ + ctx: func() context.Context { + ctx, cancel := context.WithTimeout(context.TODO(), time.Microsecond) + _ = cancel + return ctx + }(), + }, + stub: func(t *testing.T, ctx context.Context) { + assert.Equal(t, ctx.Done(), nil) + }, + }, + { + name: "nil Err()", + args: args{ + ctx: func() context.Context { + ctx, cancel := context.WithTimeout(context.TODO(), time.Second) + cancel() + return ctx + }(), + }, + stub: func(t *testing.T, ctx context.Context) { + assert.Equal(t, ctx.Err(), nil) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := WithNoDeadline(tt.args.ctx) + tt.stub(t, got) + }) + } +} + +func TestWithNoCancel(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + stub func(*testing.T, context.Context) + }{ + { + name: "value正常传递", + args: args{ + context.WithValue(context.TODO(), k, "world"), + }, + stub: func(t *testing.T, ctx context.Context) { + assert.Equal(t, ctx.Value(k).(string), "world") + }, + }, + + { + name: "new Deadline()", + args: args{ + ctx: func() context.Context { + ctx, cancel := context.WithDeadline(context.TODO(), time.Date(2022, 1, 1, 1, 1, 1, 1, time.Local)) + _ = cancel + return ctx + }(), + }, + stub: func(t *testing.T, ctx context.Context) { + deadline, ok := ctx.Deadline() + assert.Equal(t, ok, true) + assert.Equal(t, deadline, time.Date(2022, 1, 1, 1, 1, 1, 1, time.Local)) + }, + }, + + { + name: "cancel withtimeout context", + args: args{ + ctx: func() context.Context { + now := time.Now() + ctx := context.WithValue(context.Background(), "t", now) + ctx, cancel := context.WithDeadline(ctx, now.Add(1000*time.Microsecond)) + go func() { + time.Sleep(100 * time.Microsecond) + cancel() + }() + return ctx + }(), + }, + + stub: func(t *testing.T, ctx context.Context) { + <-ctx.Done() + duration := time.Since(ctx.Value("t").(time.Time)) + if ctx.Err() == context.Canceled { + t.Error("context canceled") + } + if duration < 200*time.Microsecond { + t.Error("timeout cancel ") + } + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := WithNoCancel(tt.args.ctx) + tt.stub(t, got) + }) + } +} From a16bc4cc1f30809f8abdae2ba0f3a7280124e021 Mon Sep 17 00:00:00 2001 From: "dino.ma" Date: Mon, 28 Jun 2021 11:38:33 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=9C=A8=E5=8D=8F=E7=A8=8B=E6=B1=A0?= =?UTF-8?q?=E4=B8=AD=E5=A2=9E=E5=8A=A0=E4=BF=9D=E7=95=99=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E4=BF=A1=E6=81=AF=E5=B9=B6=E4=B8=8D=E4=BC=9A=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E3=80=81=E4=B8=8D=E4=BC=9A=E5=8F=96=E6=B6=88=E7=9A=84?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/gopool/pool.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/util/gopool/pool.go b/util/gopool/pool.go index f1949772..89c39ee9 100644 --- a/util/gopool/pool.go +++ b/util/gopool/pool.go @@ -16,6 +16,7 @@ package gopool import ( "context" + "github.com/bytedance/gopkg/util/hcontext" "runtime" "sync" "sync/atomic" @@ -30,6 +31,8 @@ type Pool interface { Go(f func()) // CtxGo executes f and accepts the context. CtxGo(ctx context.Context, f func()) + // CtxGoNoDeadlineOrCancel executes f and will be no timeouts and cancellations + CtxGoNoDeadlineOrCancel(ctx context.Context,f func()) // SetPanicHandler sets the panic handler. SetPanicHandler(f func(context.Context, interface{})) } @@ -138,6 +141,12 @@ func (p *pool) CtxGo(ctx context.Context, f func()) { } } +func (p *pool) CtxGoNoDeadlineOrCancel(ctx context.Context,f func()) { + ctx = hcontext.WithNoCancel(ctx) + ctx = hcontext.WithNoDeadline(ctx) + CtxGo(ctx,f) +} + // SetPanicHandler the func here will be called after the panic has been recovered. func (p *pool) SetPanicHandler(f func(context.Context, interface{})) { p.panicHandler = f From 720ca0e3bbe12a5d98eb69c2520b0177366d2722 Mon Sep 17 00:00:00 2001 From: "dino.ma" Date: Mon, 28 Jun 2021 15:05:45 +0800 Subject: [PATCH 3/4] change hcontext to contextx --- lang/contextx/README.md | 12 ++++++++++++ .../hcontext.go => lang/contextx/contextx.go | 6 +++--- .../contextx/contextx_test.go | 15 +++++++-------- util/gopool/pool.go | 9 --------- util/hcontext/README.md | 15 --------------- 5 files changed, 22 insertions(+), 35 deletions(-) create mode 100644 lang/contextx/README.md rename util/hcontext/hcontext.go => lang/contextx/contextx.go (80%) rename util/hcontext/hcontext_test.go => lang/contextx/contextx_test.go (93%) delete mode 100644 util/hcontext/README.md diff --git a/lang/contextx/README.md b/lang/contextx/README.md new file mode 100644 index 00000000..6abc41c8 --- /dev/null +++ b/lang/contextx/README.md @@ -0,0 +1,12 @@ +# contextx + + +## usage + +```golang +// only remove deadline value +ctx = contextx.WithNoDeadline(ctx) + +// only remove cancel value +ctx = contextx.WithNoCancel(ctx) +``` diff --git a/util/hcontext/hcontext.go b/lang/contextx/contextx.go similarity index 80% rename from util/hcontext/hcontext.go rename to lang/contextx/contextx.go index 29b8bb8e..4331ea7a 100644 --- a/util/hcontext/hcontext.go +++ b/lang/contextx/contextx.go @@ -1,4 +1,4 @@ -package hcontext +package contextx import ( "context" @@ -11,12 +11,12 @@ func (valueOnlyContext) Deadline() (deadline time.Time, ok bool) { return } func (valueOnlyContext) Done() <-chan struct{} { return nil } func (valueOnlyContext) Err() error { return nil } -//WithNoDeadline 移除超时控制,保留value信息 +//WithNoDeadline only remove deadline value func WithNoDeadline(ctx context.Context) context.Context { return valueOnlyContext{ctx} } -//WithNoCancel 不受上层context cancel的影响,但是保留上层ctx的Deadline信息 +//WithNoCancel only remove cancel value func WithNoCancel(ctx context.Context) context.Context { deadline, ok := ctx.Deadline() if ok { diff --git a/util/hcontext/hcontext_test.go b/lang/contextx/contextx_test.go similarity index 93% rename from util/hcontext/hcontext_test.go rename to lang/contextx/contextx_test.go index a7ad500e..863e41e2 100644 --- a/util/hcontext/hcontext_test.go +++ b/lang/contextx/contextx_test.go @@ -1,12 +1,11 @@ -package hcontext +package contextx import ( "context" + "github.com/stretchr/testify/assert" "testing" "time" - - "gopkg.in/go-playground/assert.v1" -) + ) type ctxtype string @@ -22,7 +21,7 @@ func TestWithNoDeadline(t *testing.T) { stub func(*testing.T, context.Context) }{ { - name: "value正常传递", + name: "value is correct", args: args{ context.WithValue(context.TODO(), k, "world"), }, @@ -56,7 +55,7 @@ func TestWithNoDeadline(t *testing.T) { }(), }, stub: func(t *testing.T, ctx context.Context) { - assert.Equal(t, ctx.Done(), nil) + assert.Equal(t, ctx.Done(), ctx.Done()) }, }, { @@ -91,7 +90,7 @@ func TestWithNoCancel(t *testing.T) { stub func(*testing.T, context.Context) }{ { - name: "value正常传递", + name: "value is correct", args: args{ context.WithValue(context.TODO(), k, "world"), }, @@ -117,7 +116,7 @@ func TestWithNoCancel(t *testing.T) { }, { - name: "cancel withtimeout context", + name: "cancel withTimeout context", args: args{ ctx: func() context.Context { now := time.Now() diff --git a/util/gopool/pool.go b/util/gopool/pool.go index 89c39ee9..f1949772 100644 --- a/util/gopool/pool.go +++ b/util/gopool/pool.go @@ -16,7 +16,6 @@ package gopool import ( "context" - "github.com/bytedance/gopkg/util/hcontext" "runtime" "sync" "sync/atomic" @@ -31,8 +30,6 @@ type Pool interface { Go(f func()) // CtxGo executes f and accepts the context. CtxGo(ctx context.Context, f func()) - // CtxGoNoDeadlineOrCancel executes f and will be no timeouts and cancellations - CtxGoNoDeadlineOrCancel(ctx context.Context,f func()) // SetPanicHandler sets the panic handler. SetPanicHandler(f func(context.Context, interface{})) } @@ -141,12 +138,6 @@ func (p *pool) CtxGo(ctx context.Context, f func()) { } } -func (p *pool) CtxGoNoDeadlineOrCancel(ctx context.Context,f func()) { - ctx = hcontext.WithNoCancel(ctx) - ctx = hcontext.WithNoDeadline(ctx) - CtxGo(ctx,f) -} - // SetPanicHandler the func here will be called after the panic has been recovered. func (p *pool) SetPanicHandler(f func(context.Context, interface{})) { p.panicHandler = f diff --git a/util/hcontext/README.md b/util/hcontext/README.md deleted file mode 100644 index 203733cf..00000000 --- a/util/hcontext/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# hcontext - -## 功能 - -对 context.Context 的包装函数 - -## usage - -```golang -//移除超时信息,保留value信息 -ctx = hcontext.WithNoDeadline(ctx) - -//移除取消信息,保留超时和value信息 -ctx = hcontext.WithNoCancel(ctx) -``` From 454541e65e6e4851dc3318fe900fbd9e6863d35f Mon Sep 17 00:00:00 2001 From: "dino.ma" Date: Tue, 29 Jun 2021 14:27:24 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lang/contextx/contextx.go | 12 ++++++------ lang/contextx/contextx_test.go | 17 +++++++++-------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lang/contextx/contextx.go b/lang/contextx/contextx.go index 4331ea7a..12bb99a8 100644 --- a/lang/contextx/contextx.go +++ b/lang/contextx/contextx.go @@ -11,20 +11,20 @@ func (valueOnlyContext) Deadline() (deadline time.Time, ok bool) { return } func (valueOnlyContext) Done() <-chan struct{} { return nil } func (valueOnlyContext) Err() error { return nil } -//WithNoDeadline only remove deadline value -func WithNoDeadline(ctx context.Context) context.Context { +//RemoveDeadline only remove deadline value +func RemoveDeadline(ctx context.Context) context.Context { return valueOnlyContext{ctx} } -//WithNoCancel only remove cancel value -func WithNoCancel(ctx context.Context) context.Context { +//RemoveCancel only remove cancel value +func RemoveCancel(ctx context.Context) context.Context { deadline, ok := ctx.Deadline() if ok { var cancel context.CancelFunc - ctx = WithNoDeadline(ctx) + ctx = RemoveDeadline(ctx) ctx, cancel = context.WithDeadline(ctx, deadline) _ = cancel return ctx } - return WithNoDeadline(ctx) + return RemoveDeadline(ctx) } diff --git a/lang/contextx/contextx_test.go b/lang/contextx/contextx_test.go index 863e41e2..4c4d5918 100644 --- a/lang/contextx/contextx_test.go +++ b/lang/contextx/contextx_test.go @@ -2,16 +2,17 @@ package contextx import ( "context" - "github.com/stretchr/testify/assert" "testing" "time" - ) -type ctxtype string + "github.com/stretchr/testify/assert" +) + +type ctxType string -var k ctxtype = "k" +var k ctxType = "k" -func TestWithNoDeadline(t *testing.T) { +func TestRemoveDeadline(t *testing.T) { type args struct { ctx context.Context } @@ -74,13 +75,13 @@ func TestWithNoDeadline(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := WithNoDeadline(tt.args.ctx) + got := RemoveDeadline(tt.args.ctx) tt.stub(t, got) }) } } -func TestWithNoCancel(t *testing.T) { +func TestRemoveCancel(t *testing.T) { type args struct { ctx context.Context } @@ -144,7 +145,7 @@ func TestWithNoCancel(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := WithNoCancel(tt.args.ctx) + got := RemoveCancel(tt.args.ctx) tt.stub(t, got) }) }