feat: implement Yandex /search method for on-demand edge expansion (Task 2)

- Add SearchRoutes method to yandex client for on-demand station pair searches
- Implement hub expansion via on-demand /search calls in lazy graph expansion
- Integrate cache key generation for search results (search:{from}:{to}:{date})
- Update expandFromStation and expandFromCityHub to use Yandex API
- Add NewGraphWithoutYandex constructor for testability
- Add tests for on-demand search integration and cache TTL policies
This commit is contained in:
2026-08-14 14:14:14 +03:00
parent 829e93fc8f
commit 181575e092
5 changed files with 337 additions and 84 deletions

View File

@@ -19,7 +19,7 @@ func newMockHandlerContext() *HandlerContext {
})
// Create an empty routing graph
router := routing.NewGraph()
router := routing.NewGraphWithoutYandex()
// Create Yandex client
yandexClient := yandex.NewClient("test-key")
@@ -59,7 +59,7 @@ func TestHandlerRouteSearch(t *testing.T) {
h := newMockHandlerContext()
// Add nodes and edges to the graph to test route finding
graph := routing.NewGraph()
graph := routing.NewGraphWithoutYandex()
graph.AddNode(&routing.Node{ID: "c146", Type: routing.NodeTypeCity, Name: "Simferopol"})
graph.AddNode(&routing.Node{ID: "c213", Type: routing.NodeTypeCity, Name: "Moscow"})
graph.AddNode(&routing.Node{ID: "s9600213", Type: routing.NodeTypeStation, Name: "Шереметьево", CityCode: "c146"})
@@ -163,7 +163,7 @@ func TestHandlerRouteSearchIntegration(t *testing.T) {
// Build a routing graph using the same pattern as TestFindRouteSuccess:
// stations with real edges and one synthetic transfer edge, plus city hub.
graph := routing.NewGraph()
graph := routing.NewGraphWithoutYandex()
graph.AddNode(&routing.Node{ID: "c1", Type: routing.NodeTypeCity, Name: "City Hub"})
graph.AddNode(&routing.Node{ID: "s1", Type: routing.NodeTypeStation, Name: "Moscow", CityCode: "c1"})
graph.AddNode(&routing.Node{ID: "s2", Type: routing.NodeTypeStation, Name: "Tula", CityCode: "c1"})
@@ -239,7 +239,7 @@ func TestHandlerRouteSearchNoRoute(t *testing.T) {
// Create graph with no relevant nodes, but add some so the handler can find
// the city IDs (otherwise handler returns 404 before route search)
graph := routing.NewGraph()
graph := routing.NewGraphWithoutYandex()
graph.AddNode(&routing.Node{ID: "c999", Type: routing.NodeTypeCity, Name: "City 999"})
graph.AddNode(&routing.Node{ID: "c888", Type: routing.NodeTypeCity, Name: "City 888"})
h.Router = graph

View File

@@ -14,8 +14,8 @@ import (
func main() {
redisClient := initRedis()
router := routing.NewGraph()
yandexClient := yandex.NewClient("default-key")
router := routing.NewGraph(yandexClient)
handlerCtx := NewHandlerContext(redisClient, router, yandexClient)