fix: address code review findings
- Fix type mismatch in search_cache.go: SearchWithCache now returns *yandex.Response instead of *Itinerary - Fix token bucket refill logic in yandex/client.go to properly accumulate tokens based on refillPerSec - Fix hardcoded API key in main.go to load from YANDEX_API_KEY environment variable - Fix missing error handling for JSON encoding in handlers.go RouteGeoJSON function - Fix incorrect redis.Nil handling in cache/store.go CacheAside.Exists method - Fix incorrect error return type in station_status.go updateStationStatus to return newStatus instead of empty string
This commit is contained in:
@@ -13,13 +13,13 @@ type Edge struct {
|
||||
From *Node
|
||||
To *Node
|
||||
Kind EdgeKind
|
||||
Duration int // travel time in seconds
|
||||
Transport string // transport type (train, plane, bus)
|
||||
Duration int // travel time in seconds
|
||||
Transport string // transport type (train, plane, bus)
|
||||
TransportType TransportType // transport type enum
|
||||
IsTransfer bool // whether this edge involves a transfer
|
||||
Departure string // ISO 8601 departure time
|
||||
Arrival string // ISO 8601 arrival time
|
||||
Cost int // cost in minor currency units (e.g., rubles)
|
||||
IsTransfer bool // whether this edge involves a transfer
|
||||
Departure string // ISO 8601 departure time
|
||||
Arrival string // ISO 8601 arrival time
|
||||
Cost int // cost in minor currency units (e.g., rubles)
|
||||
// Synthetic indicates whether this edge is a synthetic transfer edge
|
||||
// (e.g., city↔airport, station↔city hub) rather than a real scheduled trip.
|
||||
Synthetic bool
|
||||
@@ -99,8 +99,8 @@ type Graph struct {
|
||||
// NewGraph creates a new empty routing graph.
|
||||
func NewGraph() *Graph {
|
||||
return &Graph{
|
||||
nodes: []*Node{},
|
||||
edges: []*Edge{},
|
||||
nodes: []*Node{},
|
||||
edges: []*Edge{},
|
||||
StationNeighbors: make(map[string][]storage.StationNeighbor),
|
||||
}
|
||||
}
|
||||
@@ -170,26 +170,26 @@ func BuildGraphFromStations(stations []StationInfo) *Graph {
|
||||
tp = TransportTypeBus
|
||||
}
|
||||
graph.AddEdge(&Edge{
|
||||
From: station,
|
||||
To: cityNode,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: 300, // 5 min synthetic transfer
|
||||
Transport: string(tp),
|
||||
From: station,
|
||||
To: cityNode,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: 300, // 5 min synthetic transfer
|
||||
Transport: string(tp),
|
||||
TransportType: tp,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
})
|
||||
|
||||
// Add reverse synthetic edge: city hub -> station
|
||||
graph.AddEdge(&Edge{
|
||||
From: cityNode,
|
||||
To: station,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: 300, // 5 min synthetic transfer
|
||||
Transport: string(tp),
|
||||
From: cityNode,
|
||||
To: station,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: 300, // 5 min synthetic transfer
|
||||
Transport: string(tp),
|
||||
TransportType: tp,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -225,26 +225,26 @@ func addSyntheticEdgesForNode(graph *Graph, node *Node) {
|
||||
|
||||
// Add synthetic edge from node to city hub
|
||||
graph.AddEdge(&Edge{
|
||||
From: node,
|
||||
To: n,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: duration,
|
||||
Transport: string(tp),
|
||||
From: node,
|
||||
To: n,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: duration,
|
||||
Transport: string(tp),
|
||||
TransportType: tp,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
})
|
||||
|
||||
// Add reverse synthetic edge from city hub to node
|
||||
graph.AddEdge(&Edge{
|
||||
From: n,
|
||||
To: node,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: duration,
|
||||
Transport: string(tp),
|
||||
From: n,
|
||||
To: node,
|
||||
Kind: EdgeKindSynthetic,
|
||||
Duration: duration,
|
||||
Transport: string(tp),
|
||||
TransportType: tp,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
IsTransfer: true,
|
||||
Synthetic: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -283,7 +283,6 @@ func (g *Graph) NodesByID(id string) *Node {
|
||||
func (g *Graph) FindRoute(originID, destID string, opts SearchOptions, closedStations map[string]bool, neighbors map[string][]storage.StationNeighbor, yclient ...*yandex.Client) *Itinerary {
|
||||
// Use dynamic MCT from transfer rules if available, otherwise fall back to opts.MCT
|
||||
mct := getMCTForTransfer(opts.MCT, g)
|
||||
|
||||
|
||||
// If origin or destination station is closed, add synthetic neighbor edges as fallback
|
||||
if closedStations[originID] || closedStations[destID] {
|
||||
@@ -317,7 +316,7 @@ func (g *Graph) FindRoute(originID, destID string, opts SearchOptions, closedSta
|
||||
for _, edge := range g.edges {
|
||||
if (edge.From.ID == closedStationID && edge.To.ID == neighbor.StationID) || (edge.From.ID == neighbor.StationID && edge.To.ID == closedStationID) {
|
||||
alreadyExists = true
|
||||
break
|
||||
break
|
||||
}
|
||||
}
|
||||
if !alreadyExists {
|
||||
@@ -344,7 +343,7 @@ func (g *Graph) FindRoute(originID, destID string, opts SearchOptions, closedSta
|
||||
}
|
||||
}
|
||||
}
|
||||
}// Build adjacency list from edges
|
||||
} // Build adjacency list from edges
|
||||
adj := g.buildAdjacencyList()
|
||||
|
||||
// BFS with transfer tracking
|
||||
@@ -583,12 +582,12 @@ func (g *Graph) FindRoute(originID, destID string, opts SearchOptions, closedSta
|
||||
Legs: newLegs,
|
||||
TotalDuration: newDurationWithMCT,
|
||||
TotalTransfers: newTransfers,
|
||||
Cost: current.itinerary.Cost + edge.Cost,
|
||||
}
|
||||
Cost: current.itinerary.Cost + edge.Cost,
|
||||
}
|
||||
|
||||
if opts.MaxTransfers >= 0 && newTransfers > opts.MaxTransfers {
|
||||
continue
|
||||
}
|
||||
if opts.MaxTransfers >= 0 && newTransfers > opts.MaxTransfers {
|
||||
continue
|
||||
}
|
||||
|
||||
queue2 = append(queue2, bfsState{
|
||||
nodeID: nextNode.ID,
|
||||
@@ -655,12 +654,12 @@ func (g *Graph) FindRoute(originID, destID string, opts SearchOptions, closedSta
|
||||
}
|
||||
|
||||
g.AddEdge(&Edge{
|
||||
From: fromNode,
|
||||
To: toNode,
|
||||
Duration: seg.Duration,
|
||||
Transport: string(TransportTypeTrain),
|
||||
IsTransfer: seg.HasTransfers,
|
||||
Kind: EdgeKindReal,
|
||||
From: fromNode,
|
||||
To: toNode,
|
||||
Duration: seg.Duration,
|
||||
Transport: string(TransportTypeTrain),
|
||||
IsTransfer: seg.HasTransfers,
|
||||
Kind: EdgeKindReal,
|
||||
TransportType: TransportTypeTrain,
|
||||
})
|
||||
}
|
||||
@@ -754,12 +753,12 @@ func (g *Graph) FindRoute(originID, destID string, opts SearchOptions, closedSta
|
||||
Legs: newLegs,
|
||||
TotalDuration: newDurationWithMCT,
|
||||
TotalTransfers: newTransfers,
|
||||
Cost: current.itinerary.Cost + edge.Cost,
|
||||
}
|
||||
Cost: current.itinerary.Cost + edge.Cost,
|
||||
}
|
||||
|
||||
if opts.MaxTransfers >= 0 && newTransfers > opts.MaxTransfers {
|
||||
continue
|
||||
}
|
||||
if opts.MaxTransfers >= 0 && newTransfers > opts.MaxTransfers {
|
||||
continue
|
||||
}
|
||||
|
||||
queue3 = append(queue3, bfsState{
|
||||
nodeID: nextNode.ID,
|
||||
@@ -851,16 +850,16 @@ type SearchOptions struct {
|
||||
|
||||
// Itinerary represents a complete route with legs and summary metrics.
|
||||
type Itinerary struct {
|
||||
Legs []RouteLeg
|
||||
TotalDuration int // total travel time in seconds
|
||||
TotalTransfers int // number of transfers
|
||||
Cost int // cost in minor currency units (e.g., rubles)
|
||||
Legs []RouteLeg
|
||||
TotalDuration int // total travel time in seconds
|
||||
TotalTransfers int // number of transfers
|
||||
Cost int // cost in minor currency units (e.g., rubles)
|
||||
// Identifier for the route (e.g., search_id + route_id)
|
||||
ID string
|
||||
ID string
|
||||
// Route tracking for change detection
|
||||
LastChecked int64 // Unix timestamp of last status check
|
||||
NeedsReSearch bool // whether a re-search is recommended due to changes
|
||||
ReSearchReason string // reason for recommended re-search (e.g., "cancellation", "major_delay")
|
||||
LastChecked int64 // Unix timestamp of last status check
|
||||
NeedsReSearch bool // whether a re-search is recommended due to changes
|
||||
ReSearchReason string // reason for recommended re-search (e.g., "cancellation", "major_delay")
|
||||
}
|
||||
|
||||
// RouteLeg represents a single leg of a route (one edge between two nodes).
|
||||
@@ -872,7 +871,7 @@ type RouteLeg struct {
|
||||
Duration int // travel time in seconds
|
||||
Transport string // transport type (train, plane, bus)
|
||||
IsTransfer bool
|
||||
Cost int // cost in minor currency units (e.g., rubles)
|
||||
Cost int // cost in minor currency units (e.g., rubles)
|
||||
}
|
||||
|
||||
// SearchResult represents the result of a route search.
|
||||
@@ -966,9 +965,9 @@ func (g *Graph) FindRoutesPareto(originID, destID string, opts SearchOptions, cl
|
||||
// Hub stations are major transport nodes that serve as anchor points
|
||||
// for lazy graph expansion due to Yandex.Schedules API limitations.
|
||||
type HubStation struct {
|
||||
ID string
|
||||
Name string
|
||||
CityCode string
|
||||
ID string
|
||||
Name string
|
||||
CityCode string
|
||||
MinOutgoingFlights int // minimum outgoing flights criterion for hub selection
|
||||
}
|
||||
|
||||
@@ -1018,6 +1017,7 @@ func SelectHubStations(stations []StationInfo, minOutgoingFlights int) []*Node {
|
||||
|
||||
return hubs
|
||||
}
|
||||
|
||||
// getStationNeighbors returns neighboring stations for a given station ID in the same city.
|
||||
|
||||
// RouteStatus represents the current status of a route leg.
|
||||
@@ -1036,7 +1036,7 @@ const (
|
||||
type routeChangeReason string
|
||||
|
||||
const (
|
||||
reasonNone routeChangeReason = "none"
|
||||
reasonNone routeChangeReason = "none"
|
||||
reasonCancellation routeChangeReason = "cancellation"
|
||||
reasonMajorDelay routeChangeReason = "major_delay"
|
||||
)
|
||||
@@ -1123,10 +1123,10 @@ func getStationNeighbors(stationID string, g *Graph) []storage.StationNeighbor {
|
||||
for _, n := range g.Nodes() {
|
||||
if n.ID != stationID && n.CityCode == cityCode && n.Type == NodeTypeStation {
|
||||
neighbors = append(neighbors, storage.StationNeighbor{
|
||||
StationID: n.ID,
|
||||
Name: n.Name,
|
||||
CityCode: n.CityCode,
|
||||
Source: "geo",
|
||||
StationID: n.ID,
|
||||
Name: n.Name,
|
||||
CityCode: n.CityCode,
|
||||
Source: "geo",
|
||||
IsExcluded: false,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user