From ac11ea7d95abd5a6bbca1b0468404545eb1bf36c Mon Sep 17 00:00:00 2001 From: crusader Date: Wed, 23 Aug 2017 18:19:21 +0900 Subject: [PATCH] setting --- .gitignore | 68 +++++++++++++++ .vscode/launch.json | 32 +++++++ .vscode/settings.json | 11 +++ backend/client.go | 6 ++ backend/options.go | 28 ++++++ backend/pool.go | 144 +++++++++++++++++++++++++++++++ glide.yaml | 11 +++ main.go | 54 ++++++++++++ module/member/check_email.go | 16 ++++ module/member/forgot_password.go | 16 ++++ module/member/signin.go | 29 +++++++ module/member/signup.go | 16 ++++ server/context.go | 19 ++++ server/handler.go | 5 ++ server/server.go | 44 ++++++++++ 15 files changed, 499 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 backend/client.go create mode 100644 backend/options.go create mode 100644 backend/pool.go create mode 100644 glide.yaml create mode 100644 main.go create mode 100644 module/member/check_email.go create mode 100644 module/member/forgot_password.go create mode 100644 module/member/signin.go create mode 100644 module/member/signup.go create mode 100644 server/context.go create mode 100644 server/handler.go create mode 100644 server/server.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3733e36 --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Go template +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ +.idea/ +*.iml + +vendor/ +glide.lock +.DS_Store +dist/ +debug diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2ca2b1d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug", + "type": "go", + "request": "launch", + "mode": "debug", + "remotePath": "", + "port": 2345, + "host": "127.0.0.1", + "program": "${workspaceRoot}/main.go", + "env": {}, + "args": [], + "showLog": true + }, + { + "name": "File Debug", + "type": "go", + "request": "launch", + "mode": "debug", + "remotePath": "", + "port": 2345, + "host": "127.0.0.1", + "program": "${fileDirname}", + "env": {}, + "args": [], + "showLog": true + } + + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..46c249c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +// Place your settings in this file to overwrite default and user settings. +{ + // Specifies Lint tool name. + "go.lintTool": "gometalinter", + + // Flags to pass to Lint tool (e.g. ["-min_confidence=.8"]) + "go.lintFlags": [ + "--config=${workspaceRoot}/golint.json" + ] + +} \ No newline at end of file diff --git a/backend/client.go b/backend/client.go new file mode 100644 index 0000000..6381067 --- /dev/null +++ b/backend/client.go @@ -0,0 +1,6 @@ +package backend + +type PooledClient interface { + Exec(target string, method string, params []string) (string, error) + Close() +} diff --git a/backend/options.go b/backend/options.go new file mode 100644 index 0000000..492c823 --- /dev/null +++ b/backend/options.go @@ -0,0 +1,28 @@ +package backend + +import ( + "google.golang.org/grpc" +) + +type Options struct { + // Dial is an application supplied function for creating and configuring a + // grpc connection. + // + // The grpc.ClientConn returned from Dial + Dial func() (*grpc.ClientConn, error) + + // NewClient is an application supplied function for creating and configuring a + // client. + // + // The client returned from NewClient + NewClient func(*grpc.ClientConn) (interface{}, error) + + Exec func(client interface{}, target string, method string, params []string) (string, error) + + // Initial number of clients in the pool. + InitCapacity int + + // Maximum number of clients allocated by the pool at a given time. + // When zero, there is no limit on the number of clients in the pool. + MaxCapacity int +} diff --git a/backend/pool.go b/backend/pool.go new file mode 100644 index 0000000..27eaf75 --- /dev/null +++ b/backend/pool.go @@ -0,0 +1,144 @@ +package backend + +import ( + "fmt" + "sync" + + "google.golang.org/grpc" +) + +type Pool interface { + // Get gets a client. The application must close the returned client. + // This method always returns a valid client so that applications can defer + // error handling to the first use of the client. If there is an error + // getting an underlying client, then the client Err, Do, Send, Flush + // and Receive methods return that error. + Get() (PooledClient, error) + + // Capacity returns the number of maximum clients in the pool. + Capacity() int + + // Available returns the number of avaliable clients in the pool. + Available() int + + // Destroy releases the resources used by the pool. + Destroy() +} + +type pool struct { + dial func() (*grpc.ClientConn, error) + newClient func(*grpc.ClientConn) (interface{}, error) + exec func(client interface{}, target string, method string, params []string) (string, error) + initCapacity int + maxCapacity int + + conn *grpc.ClientConn + mtx sync.Mutex + clients chan PooledClient +} + +func NewPool(o Options) (Pool, error) { + if o.Dial == nil { + return nil, fmt.Errorf("invalid Dial settings") + } + + if o.NewClient == nil { + return nil, fmt.Errorf("invalid NewClient settings") + } + + if o.InitCapacity < 0 || o.MaxCapacity < 0 { + return nil, fmt.Errorf("invalid capacity settings") + } + + p := &pool{ + dial: o.Dial, + newClient: o.NewClient, + exec: o.Exec, + initCapacity: o.InitCapacity, + maxCapacity: o.MaxCapacity, + clients: make(chan PooledClient, o.InitCapacity), + } + + var err error + p.conn, err = p.dial() + if nil != err { + return nil, err + } + + for i := 0; i < p.initCapacity; i++ { + pc, err := p.create() + if err != nil { + p.conn.Close() + return nil, err + } + p.clients <- pc + } + + return p, nil +} + +func (p *pool) Capacity() int { + return cap(p.clients) +} + +func (p *pool) Available() int { + return len(p.clients) +} + +func (p *pool) Get() (PooledClient, error) { + if p.clients == nil { + // pool aleardy destroyed, returns new client + return p.create() + } + for { + select { + case c := <-p.clients: + return c, nil + default: + return p.create() + } + } +} + +func (p *pool) Destroy() { + p.mtx.Lock() + defer p.mtx.Unlock() + if p.clients == nil { + // pool aleardy destroyed + return + } + close(p.clients) + p.clients = nil + p.conn.Close() +} + +func (p *pool) create() (PooledClient, error) { + c, err := p.newClient(p.conn) + if err != nil { + return nil, err + } + pc := &pooledClient{ + p: p, + c: c, + } + return pc, nil +} + +type pooledClient struct { + p *pool + c interface{} +} + +func (pc *pooledClient) Exec(target string, method string, params []string) (string, error) { + return pc.p.exec(pc.c, target, method, params) +} + +func (pc *pooledClient) Close() { + select { + case pc.p.clients <- pc: + return + default: + // pool is full, close passed connection + return + } +} diff --git a/glide.yaml b/glide.yaml new file mode 100644 index 0000000..33f4555 --- /dev/null +++ b/glide.yaml @@ -0,0 +1,11 @@ +package: git.loafle.net/overflow/overflow_server_app +import: +- package: github.com/valyala/fasthttp + version: v20160617 +- package: github.com/buaazp/fasthttprouter + version: v0.1.1 +- package: google.golang.org/grpc + version: v1.5.2 +- package: git.loafle.net/overflow/overflow_api_server + subpackages: + - golang diff --git a/main.go b/main.go new file mode 100644 index 0000000..a33496f --- /dev/null +++ b/main.go @@ -0,0 +1,54 @@ +package main + +import ( + "context" + + "git.loafle.net/overflow/overflow_server_app/backend" + "git.loafle.net/overflow/overflow_server_app/module/member" + "git.loafle.net/overflow/overflow_server_app/server" + + grpcAPI "git.loafle.net/overflow/overflow_api_server/golang" + + "github.com/valyala/fasthttp" + "google.golang.org/grpc" +) + +func main() { + s := server.New() + + grpcPool, err := backend.NewPool(backend.Options{ + Dial: func() (*grpc.ClientConn, error) { + return grpc.Dial("192.168.1.101:50006", grpc.WithInsecure()) + }, + NewClient: func(conn *grpc.ClientConn) (interface{}, error) { + return grpcAPI.NewOverflowApiServerClient(conn), nil + }, + Exec: func(client interface{}, target string, method string, params []string) (string, error) { + ctx := context.Background() + c := client.(grpcAPI.OverflowApiServerClient) + si := &grpcAPI.ServerInput{ + Target: target, + Method: method, + Params: params, + } + so, err := c.Exec(ctx, si) + if nil != err { + return "", err + } + + return so.Result, nil + }, + }) + if nil != err { + + } + + s.SetContextValue("grpc", grpcPool) + + s.Route("POST", "/account/signin", member.SignIn) + s.Route("POST", "/account/signup", member.SignUp) + s.Route("POST", "/account/forgot_password", member.ForgotPassword) + s.Route("POST", "/account/check_email", member.CheckEmail) + + fasthttp.ListenAndServe(":19080", s.Handler) +} diff --git a/module/member/check_email.go b/module/member/check_email.go new file mode 100644 index 0000000..c0f9c19 --- /dev/null +++ b/module/member/check_email.go @@ -0,0 +1,16 @@ +package member + +import ( + "fmt" + + "git.loafle.net/overflow/overflow_server_app/server" + + "github.com/valyala/fasthttp" +) + +func CheckEmail(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) { + msg := sctx.Value("key1") + + fmt.Fprintf(ctx, "Welcome!!!!: %s \n", msg) + +} diff --git a/module/member/forgot_password.go b/module/member/forgot_password.go new file mode 100644 index 0000000..72ef8a7 --- /dev/null +++ b/module/member/forgot_password.go @@ -0,0 +1,16 @@ +package member + +import ( + "fmt" + + "git.loafle.net/overflow/overflow_server_app/server" + + "github.com/valyala/fasthttp" +) + +func ForgotPassword(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) { + msg := sctx.Value("key1") + + fmt.Fprintf(ctx, "Welcome!!!!: %s \n", msg) + +} diff --git a/module/member/signin.go b/module/member/signin.go new file mode 100644 index 0000000..2467ace --- /dev/null +++ b/module/member/signin.go @@ -0,0 +1,29 @@ +package member + +import ( + "fmt" + + "git.loafle.net/overflow/overflow_server_app/backend" + + "git.loafle.net/overflow/overflow_server_app/server" + + "github.com/valyala/fasthttp" +) + +func SignIn(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) { + grpcPool := sctx.Value("grpc").(backend.Pool) + c, err := grpcPool.Get() + if nil != err { + + } + + signinId := string(ctx.FormValue("signinId")) + signinPw := string(ctx.FormValue("signinPw")) + + params := []string{signinId, signinPw} + + r, err := c.Exec("MemberService", "signin", params) + + fmt.Fprintf(ctx, "Welcome!!!!: %s\n", r) + +} diff --git a/module/member/signup.go b/module/member/signup.go new file mode 100644 index 0000000..2315147 --- /dev/null +++ b/module/member/signup.go @@ -0,0 +1,16 @@ +package member + +import ( + "fmt" + + "git.loafle.net/overflow/overflow_server_app/server" + + "github.com/valyala/fasthttp" +) + +func SignUp(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) { + msg := sctx.Value("key1") + + fmt.Fprintf(ctx, "Welcome!: %s \n", msg) + +} diff --git a/server/context.go b/server/context.go new file mode 100644 index 0000000..fb111fc --- /dev/null +++ b/server/context.go @@ -0,0 +1,19 @@ +package server + +type ServerContext struct { + values map[interface{}]interface{} +} + +func (c *ServerContext) Value(key interface{}) interface{} { + if nil == c.values { + return nil + } + return c.values[key] +} + +func (c *ServerContext) setValue(key interface{}, value interface{}) { + if nil == c.values { + c.values = make(map[interface{}]interface{}, 1) + } + c.values[key] = value +} diff --git a/server/handler.go b/server/handler.go new file mode 100644 index 0000000..38a7635 --- /dev/null +++ b/server/handler.go @@ -0,0 +1,5 @@ +package server + +import "github.com/valyala/fasthttp" + +type RequestHandler func(sctx *ServerContext, ctx *fasthttp.RequestCtx) diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..5db9f94 --- /dev/null +++ b/server/server.go @@ -0,0 +1,44 @@ +package server + +import ( + "github.com/buaazp/fasthttprouter" + "github.com/valyala/fasthttp" +) + +type Server interface { + Handler(ctx *fasthttp.RequestCtx) + Route(method, path string, handler RequestHandler) + SetContextValue(key interface{}, value interface{}) +} + +type server struct { + ctx *ServerContext + router *fasthttprouter.Router +} + +func New() Server { + s := &server{} + + s.router = fasthttprouter.New() + s.ctx = &ServerContext{} + + return s +} + +func (s *server) SetContextValue(key interface{}, value interface{}) { + s.ctx.setValue(key, value) +} + +func (s *server) Handler(ctx *fasthttp.RequestCtx) { + s.router.Handler(ctx) +} + +func (s *server) Route(method, path string, handler RequestHandler) { + s.router.Handle(method, path, s.wrapHandler(handler)) +} + +func (s *server) wrapHandler(handler RequestHandler) fasthttp.RequestHandler { + return fasthttp.RequestHandler(func(ctx *fasthttp.RequestCtx) { + handler(s.ctx, ctx) + }) +}