diff --git a/astar.go b/astar.go index 7a4a860..83dea20 100644 --- a/astar.go +++ b/astar.go @@ -98,7 +98,7 @@ func (b *Bifrost) RouteOnlyTimeIndependent(rounds *Rounds, origins []SourceKey, _, ok := rounds.EarliestArrivals[destKey] if !ok { - panic("destination unreachable") + panic(NoRouteError(true)) } journey := b.ReconstructJourney(destKey, 1, rounds) diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..ebe3185 --- /dev/null +++ b/errors.go @@ -0,0 +1,9 @@ +package bifrost + +import "fmt" + +type NoRouteError bool + +func (e NoRouteError) Error() string { + return fmt.Sprintf("no route found") +} diff --git a/raptor.go b/raptor.go index 1e535ba..2642933 100644 --- a/raptor.go +++ b/raptor.go @@ -220,7 +220,7 @@ func (b *Bifrost) RouteTransit(rounds *Rounds, origins []SourceKey, destKey uint _, ok = rounds.EarliestArrivals[destKey] if !ok { - return nil, fmt.Errorf("destination unreachable") + return nil, NoRouteError(true) } journey := b.ReconstructJourney(destKey, lastRound, rounds) diff --git a/server/main.go b/server/main.go index 6e9a25c..18149ae 100644 --- a/server/main.go +++ b/server/main.go @@ -37,6 +37,19 @@ func (s *StringSlice) Set(value string) error { return nil } +func SemaphoreMiddleware(maxConcurrentRequests int) gin.HandlerFunc { + semaphore := make(chan bool, maxConcurrentRequests) + + return func(c *gin.Context) { + semaphore <- true + defer func() { + <-semaphore + }() + + c.Next() + } +} + func main() { var osmPath StringSlice var gtfsPath StringSlice @@ -84,23 +97,13 @@ func main() { *numHandlerThreads = roundChanSize } - threadChan := make(chan bool, *numHandlerThreads) - - for i := 0; i < *numHandlerThreads; i++ { - threadChan <- true - } - fmt.Println("Startup took", time.Since(start)) engine := gin.Default() - engine.POST("/bifrost", func(c *gin.Context) { - <-threadChan - - defer func() { - threadChan <- true - }() + engine.Use(SemaphoreMiddleware(*numHandlerThreads)) + engine.POST("/bifrost", func(c *gin.Context) { handle(c, b) }) @@ -112,13 +115,24 @@ func main() { func handle(c *gin.Context, b *bifrost.Bifrost) { defer func() { - if r := recover(); r != nil { - fmt.Println("Recovered in f", r) + r := recover() - debug.PrintStack() + if r == nil { + return + } - c.String(500, "Internal server error: %v", r) + if _, ok := r.(bifrost.NoRouteError); ok { + c.JSON(404, gin.H{ + "error": "no route found", + }) + return } + + fmt.Println("Recovered in f", r) + + debug.PrintStack() + + c.String(500, "Internal server error: %v", r) }() req := &JourneyRequest{}