-
Notifications
You must be signed in to change notification settings - Fork 225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
增加上下文时限管理能力 #54
base: develop
Are you sure you want to change the base?
增加上下文时限管理能力 #54
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# hcontext | ||
|
||
## 功能 | ||
|
||
对 context.Context 的包装函数 | ||
|
||
## usage | ||
|
||
```golang | ||
//移除超时信息,保留value信息 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 在 // 后加一个空格,并且 README.md 改为英文吧,中文的可以放在 README_ZH.md 中,同时记得英文和中文间加个空格,如下:
下同。 |
||
ctx = hcontext.WithNoDeadline(ctx) | ||
|
||
//移除取消信息,保留超时和value信息 | ||
ctx = hcontext.WithNoCancel(ctx) | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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信息 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment 改成英文吧,记得 // 后加空格,下同。 |
||
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) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package hcontext | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
"gopkg.in/go-playground/assert.v1" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 用 testify 吧,不引入新的依赖了 |
||
) | ||
|
||
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正常传递", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 改为英文吧,下同 |
||
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) | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
感觉像是对标准库 context 的增强,不如放在 lang 下,取名为 contextx?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done