GithubHelp home page GithubHelp logo

fireball's People

Contributors

flowonyx avatar zpatrick avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

fireball's Issues

Default Router needs to be thread safe

The map in the router can hit concurrent writes. This needs to be thread safe:

goroutine 2145 [running]:
runtime.throw(0xeadf3c, 0x15)
	/home/jparsons/Downloads/go/src/runtime/panic.go:605 +0x95 fp=0xc4204f5ba8 sp=0xc4204f5b88 pc=0x42a335
runtime.mapassign_faststr(0xd16c20, 0xc4201f3a70, 0xc420222040, 0x3e, 0x15ffae0)
	/home/jparsons/Downloads/go/src/runtime/hashmap_fast.go:607 +0x4f5 fp=0xc4204f5c28 sp=0xc4204f5ba8 pc=0x40cc25
github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball.(*BasicRouter).Match(0xc4203d7160, 0xc4201a6d00, 0x159f100, 0xc42034a7e0, 0xc4201a6d00)
	/home/jparsons/dev/go/src/github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball/router.go:54 +0x110 fp=0xc4204f5c88 sp=0xc4204f5c28 pc=0x81d640
github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball.(*App).ServeHTTP(0xc4201ee480, 0x159f100, 0xc42034a7e0, 0xc4201a6d00)
	/home/jparsons/dev/go/src/github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball/app.go:40 +0xac fp=0xc4204f5cd8 sp=0xc4204f5c88 pc=0x81bcec
net/http.(*ServeMux).ServeHTTP(0x15df200, 0x159f100, 0xc42034a7e0, 0xc4201a6d00)
	/home/jparsons/Downloads/go/src/net/http/server.go:2254 +0x130 fp=0xc4204f5d18 sp=0xc4204f5cd8 pc=0x65bad0
net/http.serverHandler.ServeHTTP(0xc4203645b0, 0x159f100, 0xc42034a7e0, 0xc4201a6d00)
	/home/jparsons/Downloads/go/src/net/http/server.go:2619 +0xb4 fp=0xc4204f5d48 sp=0xc4204f5d18 pc=0x65d044
net/http.(*conn).serve(0xc420645220, 0x159fac0, 0xc420059840)
	/home/jparsons/Downloads/go/src/net/http/server.go:1801 +0x71d fp=0xc4204f5fc8 sp=0xc4204f5d48 pc=0x6591ed
runtime.goexit()
	/home/jparsons/Downloads/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc4204f5fd0 sp=0xc4204f5fc8 pc=0x457ca1
created by net/http.(*Server).Serve
	/home/jparsons/Downloads/go/src/net/http/server.go:2720 +0x288

Fatal error: concurrent map writes

There are intermittent concurrent map write errors that occur when using fireball router. The stack trace below, indicates it is occurring with the route cache logic. I was able to reproduce it by sending a lot of GET requests to an endpoint. But is is an intermittent error so I don't know how much benefit there maybe to get consistent reproducible steps (if it is even possible).

2018/03/27 22:22:19 [INFO] Listening on port 9090
fatal error: concurrent map writes
fatal error: concurrent map writes

goroutine 87 [running]:
runtime.throw(0x1b01774, 0x15)
        /usr/local/Cellar/go/1.10/libexec/src/runtime/panic.go:619 +0x81 fp=0xc420269c00 sp=0xc420269be0 pc=0x102b361
runtime.mapassign_faststr(0x1942440, 0xc420349410, 0xc42034e048, 0x4, 0x22c2720)
        /usr/local/Cellar/go/1.10/libexec/src/runtime/hashmap_fast.go:703 +0x3e9 fp=0xc420269c70 sp=0xc420269c00 pc=0x100d5c9
github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball.(*BasicRouter).Match(0xc420399280, 0xc42042a000, 0x1bb0360, 0xc4203782a0, 0xc42042a000)
        /Users/schemudugunta/go/src/github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball/router.go:54 +0x10d fp=0xc420269cd0 sp=0xc420269c70 pc=0x140d6cd
github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball.(*App).ServeHTTP(0xc4204de380, 0x1bb0360, 0xc4203782a0, 0xc42042a000)
        /Users/schemudugunta/go/src/github.com/quintilesims/layer0/vendor/github.com/zpatrick/fireball/app.go:40 +0xac fp=0xc420269d18 sp=0xc420269cd0 pc=0x140c4ec
net/http.(*ServeMux).ServeHTTP(0x22a4020, 0x1bb0360, 0xc4203782a0, 0xc42042a000)
        /usr/local/Cellar/go/1.10/libexec/src/net/http/server.go:2337 +0x130 fp=0xc420269d58 sp=0xc420269d18 pc=0x1265f50
net/http.serverHandler.ServeHTTP(0xc420445ee0, 0x1bb0360, 0xc4203782a0,0xc42042a000)
        /usr/local/Cellar/go/1.10/libexec/src/net/http/server.go:2694 +0xbc fp=0xc420269d88 sp=0xc420269d58 pc=0x1266ffc
net/http.(*conn).serve(0xc4205ce500, 0x1bb09a0, 0xc4204ac040)
        /usr/local/Cellar/go/1.10/libexec/src/net/http/server.go:1830 +0x651 fp=0xc420269fc8 sp=0xc420269d88 pc=0x1263201
runtime.goexit()

The underlying logic that does maps writes seems to be incorrect as it does not account for concurrent map writes. This blog post seems to have good information on how to handle concurrent access to a map, https://blog.golang.org/go-maps-in-action.

Specifically using a sync.RWMutex

// This statement declares a counter variable that is an anonymous struct 
// containing a map and an embedded sync.RWMutex.
var counter = struct{
    sync.RWMutex
    m map[string]int
}{m: make(map[string]int)}

// To read from the counter, take the read lock:
counter.RLock()
n := counter.m["some_key"]
counter.RUnlock()
fmt.Println("some_key:", n)

// To write to the counter, take the write lock:
counter.Lock()
counter.m["some_key"]++
counter.Unlock()

Create a type fireball.Handlers

If you create:

type Handlers map[string]Handler

Then you can write:

indexRoute := &fireball.Route{
Path: "/",
Handlers: fireball.Handlers{
"GET": index,
},
}

Add swagger plugin

Add a plugin that allows users to provide a swagger webserver using fireball.
It should be similar to: https://github.com/emicklei/go-restful-openapi/blob/master/examples/user-resource.go

Initial design thoughts: users create the swagger object and it returns a Route that can serve swagger requests:

func main() {
    swagger := fireball.Swagger {
        Routes: []fireball.SwaggerRoute{
            {
                Path: "/people",
                Method: "GET",
                Returns: []Person{},
             },
             {
                Path: "/people/:name",
                Method: "GET",
                PathParams: []swagger.PathParam{
                    {
                         Name: "name",
                         Description: "Name of the person",
                    },
                },
                Returns: Person{},
             },
        },
    }
    
    swaggerRoute := swagger.Route()

    routes := []*fireball.Route{swaggerRoute}
    app := fireball.NewApp(routes)
}

This could also be a generic, standalone repository that make it easy to serve using whichever mux you want, given it has a ServeHTTP function - e.g.:

    swagger := &swagger.Swagger{
        Routes: []swagger.Routes{},
        ...
    }

    http.Serve(swagger)

... or in fireball:

func ServeSwagger(c *fireball.Context) (fireball.Response, error) {
    response := fireball.ResponseFunc(func(w http.ResponseWriter, r *http.Request) {
        swagger.ServeHTTP(w, r)
    })

    return response, nil
}

url with trailingslash /user/100/ match Path: "/user/:id" shoud return 404

package main

import (
	"github.com/zpatrick/fireball"
	"net/http"
)

func index(c *fireball.Context) (fireball.Response, error) {
	return fireball.NewResponse(200, []byte("Hello, World!"), nil), nil
}

func main() {
	indexRoute := &fireball.Route{
		Path: "/user/:id",
		Handlers: fireball.Handlers{
			"GET": index,
		},
	}

	routes := []*fireball.Route{indexRoute}
	app := fireball.NewApp(routes)
	http.ListenAndServe(":8000", app)
}

$ curl http://localhost:8000/user/100/
Hello, World!

package main
import (
    "fmt"
    "net/http"
)
func main() {
    http.HandleFunc("/user/100", func (w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Welcome to my website!")
    })
   http.ListenAndServe(":80", nil)
}

$ curl http://localhost:80/user/100/
404 page not found

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.