ridgelines / fireball Goto Github PK
View Code? Open in Web Editor NEWGo web framework with a natural feel
License: MIT License
Go web framework with a natural feel
License: MIT License
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
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()
If you create:
type Handlers map[string]Handler
Then you can write:
indexRoute := &fireball.Route{
Path: "/",
Handlers: fireball.Handlers{
"GET": index,
},
}
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
}
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.