From 52a570f813cc699ad84496d215a1af25e3365acf Mon Sep 17 00:00:00 2001 From: zxl Date: Wed, 5 Jan 2022 11:01:13 +0800 Subject: [PATCH] refactor: reset ctx when session allocate one --- Makefile | 20 ++------------------ router.go | 9 +++++---- router_context.go | 6 +++--- router_context_test.go | 12 +++++++----- session.go | 18 ++++++++++-------- session_test.go | 22 +++++++++++----------- 6 files changed, 38 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index 4372e86..1c86cfd 100644 --- a/Makefile +++ b/Makefile @@ -1,53 +1,39 @@ -ldflags=-ldflags="-s" -os=`uname` - export CGO_ENABLED=0 -.PHONY: default default: build - -.PHONY: build +ldflags=-ldflags="-s" build: go build ${ldflags} -v -.PHONY: build-all build-all: go build ${ldflags} -v ./... -.PHONY: lint lint: golangci-lint run --concurrency=2 -.PHONY: lint-fix lint-fix: golangci-lint run --concurrency=2 --fix -.PHONY: test test: CGO_ENABLED=1 go test -count=1 -race -covermode=atomic -coverprofile=.testCoverage.txt -timeout=2m . ./message -.PHONY: test-v test-v: CGO_ENABLED=1 go test -count=1 -race -covermode=atomic -coverprofile=.testCoverage.txt -timeout=2m -v . ./message -.PHONY: cover-view cover-view: go tool cover -func .testCoverage.txt go tool cover -html .testCoverage.txt -.PHONY: spec spec: test lint go tool cover -func .testCoverage.txt -.PHONY: bench bench: go test -bench=. -run=none -benchmem -benchtime=250000x -.PHONY: tidy tidy: go mod tidy -v -.PHONY: gen +os=`uname` gen: ifeq (${os}, $(filter ${os}, Windows Windows_NT)) # If on windows, there might be something unexpected. rm -rf ./**/gomock_reflect_* @@ -57,10 +43,8 @@ else go generate -v endif -.PHONY: release-local release-local: goreleaser release --rm-dist --skip-announce --skip-publish --snapshot -.PHONY: clean clean: go clean -r -x -cache -i diff --git a/router.go b/router.go index 042952a..c1c1b4b 100644 --- a/router.go +++ b/router.go @@ -50,17 +50,18 @@ var nilHandler HandlerFunc = func(ctx Context) {} // handleRequest walks ctx through middlewares and handler, // and returns response message entry. -func (r *Router) handleRequest(ctx *routeContext) { - if ctx.reqEntry == nil { +func (r *Router) handleRequest(ctx Context) { + reqEntry := ctx.Request() + if reqEntry == nil { return } var handler HandlerFunc - if v, has := r.handlerMapper[ctx.reqEntry.ID]; has { + if v, has := r.handlerMapper[reqEntry.ID]; has { handler = v } var mws = r.globalMiddlewares - if v, has := r.middlewaresMapper[ctx.reqEntry.ID]; has { + if v, has := r.middlewaresMapper[reqEntry.ID]; has { mws = append(mws, v...) // append to global ones } diff --git a/router_context.go b/router_context.go index 8830ecc..e2a30d5 100644 --- a/router_context.go +++ b/router_context.go @@ -255,10 +255,10 @@ func (c *routeContext) Copy() Context { } } -func (c *routeContext) reset(sess *session, reqEntry *message.Entry) { +func (c *routeContext) reset() { c.rawCtx = context.Background() - c.session = sess - c.reqEntry = reqEntry + c.session = nil + c.reqEntry = nil c.respEntry = nil c.storage = nil } diff --git a/router_context_test.go b/router_context_test.go index 74145bb..92053b0 100644 --- a/router_context_test.go +++ b/router_context_test.go @@ -1,6 +1,7 @@ package easytcp import ( + "context" "fmt" "github.com/DarthPestilane/easytcp/internal/mock" "github.com/DarthPestilane/easytcp/message" @@ -179,17 +180,18 @@ func Test_routeContext_SendTo(t *testing.T) { } func Test_routeContext_reset(t *testing.T) { - ctx := newContext(nil, nil) sess := newSession(nil, &sessionOption{}) entry := &message.Entry{ ID: 1, Data: []byte("test"), } - ctx.reset(sess, entry) - assert.Equal(t, ctx.session, sess) - assert.Equal(t, ctx.reqEntry, entry) - assert.Nil(t, ctx.storage) + ctx := newContext(sess, entry) + ctx.reset() + assert.Equal(t, ctx.rawCtx, context.Background()) + assert.Nil(t, ctx.session) + assert.Nil(t, ctx.reqEntry) assert.Nil(t, ctx.respEntry) + assert.Empty(t, ctx.storage) } func Test_routeContext_Copy(t *testing.T) { diff --git a/session.go b/session.go index 6e7bf62..9036911 100644 --- a/session.go +++ b/session.go @@ -18,11 +18,11 @@ type Session interface { // Codec returns the codec, can be nil. Codec() Codec - // Close closes session. + // Close closes current session. Close() - // NewContext creates a Context. - NewContext() Context + // AllocateContext gets a Context ships with current session. + AllocateContext() Context } type session struct { @@ -88,9 +88,12 @@ func (s *session) Close() { s.closeOne.Do(func() { close(s.closed) }) } -// NewContext creates a Context from pool, and sets context session with s. -func (s *session) NewContext() Context { - return s.ctxPool.Get().(*routeContext).SetSession(s) +// AllocateContext gets a Context from pool and reset all but session. +func (s *session) AllocateContext() Context { + c := s.ctxPool.Get().(*routeContext) + c.reset() + c.SetSession(s) + return c } // readInbound reads message packet from connection in a loop. @@ -120,8 +123,7 @@ func (s *session) readInbound(router *Router, timeout time.Duration) { // don't block the loop. go func() { - ctx := s.NewContext().(*routeContext) - ctx.reset(s, reqEntry) + ctx := s.AllocateContext().SetRequestMessage(reqEntry) router.handleRequest(ctx) s.Send(ctx) }() diff --git a/session_test.go b/session_test.go index 51a9e49..2da4b04 100644 --- a/session_test.go +++ b/session_test.go @@ -161,13 +161,13 @@ func TestTCPSession_Send(t *testing.T) { } sess := newSession(nil, &sessionOption{}) sess.Close() // close session - assert.False(t, sess.NewContext().SetRequestMessage(entry).Send()) + assert.False(t, sess.AllocateContext().SetRequestMessage(entry).Send()) }) t.Run("when ctx is done", func(t *testing.T) { sess := newSession(nil, &sessionOption{}) ctx, cancel := context.WithCancel(context.Background()) - c := sess.NewContext().WithContext(ctx) + c := sess.AllocateContext().WithContext(ctx) done := make(chan struct{}) go func() { assert.False(t, c.Send()) @@ -187,7 +187,7 @@ func TestTCPSession_Send(t *testing.T) { sess.respQueue = make(chan Context) // no buffer go func() { <-sess.respQueue }() - assert.True(t, sess.NewContext().SetRequestMessage(entry).Send()) + assert.True(t, sess.AllocateContext().SetRequestMessage(entry).Send()) sess.Close() }) } @@ -218,7 +218,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { packer.EXPECT().Pack(gomock.Any()).AnyTimes().Return(nil, nil) sess := newSession(nil, &sessionOption{Packer: packer, respQueueSize: 1024}) - sess.respQueue <- sess.NewContext() + sess.respQueue <- sess.AllocateContext() doneLoop := make(chan struct{}) go func() { sess.writeOutbound(0, 10) // should stop looping and return @@ -242,7 +242,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { sess := newSession(nil, &sessionOption{Packer: packer}) done := make(chan struct{}) go func() { - sess.respQueue <- sess.NewContext().SetResponseMessage(entry) + sess.respQueue <- sess.AllocateContext().SetResponseMessage(entry) close(done) }() time.Sleep(time.Microsecond * 15) @@ -263,7 +263,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { packer.EXPECT().Pack(gomock.Any()).Return(nil, nil) sess := newSession(nil, &sessionOption{Packer: packer, respQueueSize: 100}) - sess.respQueue <- sess.NewContext().SetResponseMessage(entry) // push to queue + sess.respQueue <- sess.AllocateContext().SetResponseMessage(entry) // push to queue doneLoop := make(chan struct{}) go func() { sess.writeOutbound(0, 10) @@ -286,7 +286,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { p1, _ := net.Pipe() _ = p1.Close() sess := newSession(p1, &sessionOption{Packer: packer}) - go func() { sess.respQueue <- sess.NewContext().SetResponseMessage(entry) }() + go func() { sess.respQueue <- sess.AllocateContext().SetResponseMessage(entry) }() go sess.writeOutbound(time.Millisecond*10, 10) _, ok := <-sess.closed assert.False(t, ok) @@ -304,7 +304,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { p1, _ := net.Pipe() sess := newSession(p1, &sessionOption{Packer: packer}) - go func() { sess.respQueue <- sess.NewContext().SetResponseMessage(entry) }() + go func() { sess.respQueue <- sess.AllocateContext().SetResponseMessage(entry) }() go sess.writeOutbound(time.Millisecond*10, 10) _, ok := <-sess.closed assert.False(t, ok) @@ -324,7 +324,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { p1, _ := net.Pipe() assert.NoError(t, p1.Close()) sess := newSession(p1, &sessionOption{Packer: packer}) - go func() { sess.respQueue <- sess.NewContext().SetResponseMessage(entry) }() + go func() { sess.respQueue <- sess.AllocateContext().SetResponseMessage(entry) }() sess.writeOutbound(0, 10) // should stop looping and return _, ok := <-sess.closed assert.False(t, ok) @@ -356,7 +356,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { }) sess := newSession(conn, &sessionOption{Packer: packer}) - go func() { sess.respQueue <- sess.NewContext().SetResponseMessage(entry) }() + go func() { sess.respQueue <- sess.AllocateContext().SetResponseMessage(entry) }() sess.writeOutbound(0, 10) // should stop looping and return _, ok := <-sess.closed assert.False(t, ok) @@ -374,7 +374,7 @@ func TestTCPSession_writeOutbound(t *testing.T) { p1, p2 := net.Pipe() sess := newSession(p1, &sessionOption{Packer: packer}) - go func() { sess.NewContext().SetResponseMessage(entry).Send() }() + go func() { sess.AllocateContext().SetResponseMessage(entry).Send() }() done := make(chan struct{}) go func() { sess.writeOutbound(0, 10)