Skip to content
This repository was archived by the owner on Jan 15, 2026. It is now read-only.

Commit b18cf13

Browse files
draft
1 parent f32e0df commit b18cf13

15 files changed

Lines changed: 133 additions & 73 deletions

File tree

README.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,15 @@ and [h3](https://h3geo.org/) (a hexagonal hierarchical geospatial indexing syste
2929

3030
## Project structure
3131

32-
| Directory | Description |
33-
|-----------------------------------------------------|-------------------------------------------|
34-
| [`./cmd`](./cmd) | CLI for making gRPC requests |
35-
| [`./idl`](./idl/coop/drivers/dispatch/v1beta1) | Protobufs (Interface Definition Language) |
36-
| [`./internal/app`](./internal/app) | App dependency injection / initialization |
37-
| [`./internal/distance`](internal/service/distance) | Google Maps Distance Matrix logic |
38-
| [`./internal/idl`](./internal/idl) | Auto-generated protobufs |
39-
| [`./internal/models`](./internal/models) | Auto-generated ORM / models |
40-
| [`./internal/service`](./internal/service) | Service layer / Business logic |
41-
| [`./schema`](./schema) | SQL migration scripts |
32+
| Directory | Description |
33+
|--------------------------------------------------|-------------------------------------------|
34+
| [`./cmd`](./cmd) | CLI for making gRPC requests |
35+
| [`./idl`](./idl/coop/drivers/dispatch/v1beta1) | Protobufs (Interface Definition Language) |
36+
| [`./internal/app`](./internal/app) | App dependency injection / initialization |
37+
| [`./internal/idl`](./internal/idl) | Auto-generated protobufs |
38+
| [`./internal/models`](./internal/models) | Auto-generated ORM / models |
39+
| [`./internal/service`](./internal/service) | Service layer / Business logic |
40+
| [`./schema`](./schema) | SQL migration scripts |
4241

4342
## How does it work
4443

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ go 1.18
55
require (
66
github.com/XSAM/otelsql v0.14.1
77
github.com/envoyproxy/protoc-gen-validate v0.1.0
8+
github.com/codingsince1985/geo-golang v1.8.1
89
github.com/friendsofgo/errors v0.9.2
910
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
1011
github.com/gojuno/go.osrm v0.1.0
1112
github.com/google/go-cmp v0.5.8
1213
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
1314
github.com/kat-co/vala v0.0.0-20170210184112-42e1d8b61f12
15+
github.com/kr/pretty v0.2.0
1416
github.com/lib/pq v1.10.5
1517
github.com/paulmach/go.geo v0.0.0-20180829195134-22b514266d33
1618
github.com/rs/xid v1.4.0
@@ -55,6 +57,7 @@ require (
5557
github.com/google/uuid v1.3.0 // indirect
5658
github.com/hashicorp/hcl v1.0.0 // indirect
5759
github.com/inconshreveable/mousetrap v1.0.0 // indirect
60+
github.com/kr/text v0.1.0 // indirect
5861
github.com/magiconair/properties v1.8.5 // indirect
5962
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
6063
github.com/mitchellh/mapstructure v1.4.2 // indirect

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
9595
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
9696
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
9797
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
98+
github.com/codingsince1985/geo-golang v1.8.1 h1:6B+Ce5QkbSglCtesiNRkSYMRDDQsYrv4XKM3jJVdyTw=
99+
github.com/codingsince1985/geo-golang v1.8.1/go.mod h1:Ue7HAjKwwCAbqB5Q0YskqqnIX8XjMHL5Jq2fsSrI2T8=
98100
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
99101
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
100102
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -337,6 +339,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
337339
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
338340
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
339341
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
342+
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
340343
github.com/paulmach/go.geo v0.0.0-20180829195134-22b514266d33 h1:doG/0aLlWE6E4ndyQlkAQrPwaojghwz1IlmH0kjTdyk=
341344
github.com/paulmach/go.geo v0.0.0-20180829195134-22b514266d33/go.mod h1:btFYk/ltlMU7ZKguHS7zQrwHYCtLoXGTaa44OsPbEVw=
342345
github.com/paulmach/go.geojson v1.4.0 h1:5x5moCkCtDo5x8af62P9IOAYGQcYHtxz2QJ3x1DoCgY=

internal/app/service/service.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import (
66
"github.com/friendsofgo/errors"
77
"github.com/kevinmichaelchen/api-dispatch/internal/service"
88
"github.com/kevinmichaelchen/api-dispatch/internal/service/db"
9-
"github.com/kevinmichaelchen/api-dispatch/internal/service/distance"
9+
"github.com/kevinmichaelchen/api-dispatch/internal/service/maps"
1010
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
1111
"go.uber.org/fx"
1212
"go.uber.org/zap"
13-
"googlemaps.github.io/maps"
13+
gmaps "googlemaps.github.io/maps"
1414
"os"
1515
)
1616

@@ -26,7 +26,7 @@ var Module = fx.Module("service",
2626
type Params struct {
2727
fx.In
2828
DataStore *db.Store
29-
DistanceService *distance.Service `optional:"true"`
29+
DistanceService *maps.Service `optional:"true"`
3030
}
3131

3232
func NewService(p Params) *service.Service {
@@ -37,24 +37,24 @@ func NewDataStore(sqlDB *sql.DB) *db.Store {
3737
return db.NewStore(sqlDB)
3838
}
3939

40-
func NewMapsClient() (*maps.Client, error) {
40+
func NewMapsClient() (*gmaps.Client, error) {
4141
apiKey := os.Getenv("API_KEY")
4242
if apiKey == "" {
4343
return nil, errors.New("missing API_KEY for Google Maps")
4444
}
45-
c, err := maps.NewClient(
46-
maps.WithAPIKey(apiKey),
47-
maps.WithHTTPClient(otelhttp.DefaultClient),
45+
c, err := gmaps.NewClient(
46+
gmaps.WithAPIKey(apiKey),
47+
gmaps.WithHTTPClient(otelhttp.DefaultClient),
4848
)
4949
if err != nil {
5050
return nil, fmt.Errorf("failed to build Google Maps client: %w", err)
5151
}
5252
return c, nil
5353
}
5454

55-
func NewDistanceService(logger *zap.Logger, client *maps.Client) (*distance.Service, error) {
55+
func NewDistanceService(logger *zap.Logger, client *gmaps.Client) (*maps.Service, error) {
5656
if client == nil {
5757
return nil, errors.New("no maps client")
5858
}
59-
return distance.NewService(client), nil
59+
return maps.NewService(client), nil
6060
}

internal/service/dispatch.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"context"
55
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
66
"github.com/kevinmichaelchen/api-dispatch/internal/idl/coop/drivers/dispatch/v1beta1"
7-
"github.com/kevinmichaelchen/api-dispatch/internal/service/distance"
7+
"github.com/kevinmichaelchen/api-dispatch/internal/service/maps"
88
"github.com/kevinmichaelchen/api-dispatch/internal/service/money"
99
"github.com/kevinmichaelchen/api-dispatch/internal/service/ranking"
1010
"go.uber.org/zap"
@@ -66,9 +66,10 @@ func (s *Service) GetNearestDrivers(
6666
}
6767
var pickupAddress string
6868
if trafficAware {
69-
out, err := s.distanceSvc.BetweenPoints(ctx, distance.BetweenPointsInput{
70-
PickupLocations: []*v1beta1.LatLng{req.GetPickupLocation()},
71-
DriverLocations: driverLocations,
69+
out, err := s.distanceSvc.BetweenPoints(ctx, maps.BetweenPointsInput{
70+
// the driver location(s) is/are always the origin(s)
71+
Origins: driverLocations,
72+
Destinations: []*v1beta1.LatLng{req.GetPickupLocation()},
7273
})
7374
if err != nil {
7475
return nil, err
@@ -144,9 +145,10 @@ func (s *Service) GetNearestTrips(
144145
locations = append(locations, result.GetLocation())
145146
}
146147
if trafficAware {
147-
out, err := s.distanceSvc.BetweenPoints(ctx, distance.BetweenPointsInput{
148-
PickupLocations: locations,
149-
DriverLocations: []*v1beta1.LatLng{req.GetDriverLocation()},
148+
out, err := s.distanceSvc.BetweenPoints(ctx, maps.BetweenPointsInput{
149+
// the driver location(s) is/are always the origin(s)
150+
Origins: []*v1beta1.LatLng{req.GetDriverLocation()},
151+
Destinations: locations,
150152
})
151153
if err != nil {
152154
return nil, err
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package distance
1+
package maps
22

33
import (
44
"context"
@@ -18,8 +18,8 @@ func NewService(client *maps.Client) *Service {
1818
}
1919

2020
type BetweenPointsInput struct {
21-
PickupLocations []*v1beta1.LatLng
22-
DriverLocations []*v1beta1.LatLng
21+
Destinations []*v1beta1.LatLng
22+
Origins []*v1beta1.LatLng
2323
}
2424

2525
type BetweenPointsOutput struct {
@@ -34,19 +34,21 @@ type Info struct {
3434
}
3535

3636
func (s *Service) BetweenPoints(ctx context.Context, in BetweenPointsInput) (*BetweenPointsOutput, error) {
37-
driverPlaceIDs, err := locationsToPlaceIDs(ctx, s.client, in.DriverLocations)
37+
origins, err := locationsToPlaceIDs(ctx, s.client, in.Origins)
3838
if err != nil {
3939
return nil, err
4040
}
4141

42-
pickupPlaceIDs, err := locationsToPlaceIDs(ctx, s.client, in.PickupLocations)
42+
destinations, err := locationsToPlaceIDs(ctx, s.client, in.Destinations)
4343
if err != nil {
4444
return nil, err
4545
}
4646

47+
// TODO if len(origins) > 25 || len(destinations) > 25, we need to partition/batch
48+
4749
res, err := betweenPlaces(ctx, s.client, betweenPlacesInput{
48-
originPlaceIDs: driverPlaceIDs,
49-
destinationPlaceIDs: pickupPlaceIDs,
50+
originPlaceIDs: origins,
51+
destinationPlaceIDs: destinations,
5052
})
5153
if err != nil {
5254
return nil, err
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package google
2+
3+
import (
4+
"context"
5+
"errors"
6+
"github.com/kevinmichaelchen/api-dispatch/internal/idl/coop/drivers/dispatch/v1beta1"
7+
"googlemaps.github.io/maps"
8+
)
9+
10+
var errNoResults = errors.New("no results found for coordinates")
11+
12+
func ReverseGeocode(ctx context.Context, c *maps.Client, location *v1beta1.LatLng) ([]maps.GeocodingResult, error) {
13+
results, err := c.ReverseGeocode(ctx, &maps.GeocodingRequest{
14+
LatLng: &maps.LatLng{
15+
Lat: location.GetLatitude(),
16+
Lng: location.GetLongitude(),
17+
},
18+
ResultType: nil,
19+
LocationType: nil,
20+
PlaceID: "",
21+
Language: "",
22+
Custom: nil,
23+
})
24+
if err != nil {
25+
return nil, err
26+
}
27+
if len(results) == 0 {
28+
return nil, errNoResults
29+
}
30+
return results, err
31+
}
File renamed without changes.

internal/service/maps/osrm/doc.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
Package osrm provides functions over the Open Source Routing Machine project.
3+
4+
We use OSRM's Table service when we want to quickly determine the duration
5+
and/or distance between two points (without traffic awareness). This could be
6+
useful for saving money/requests to Google Maps API every time an anonymous end
7+
user sees an estimate quote for a potential trip.
8+
https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#table-service
9+
10+
We use OpenStreetMap's /reverse endpoint for reverse geocoding.
11+
https://nominatim.org/release-docs/develop/api/Reverse/
12+
*/
13+
package osrm

0 commit comments

Comments
 (0)