Add simple client API, add airport type to API response
This commit is contained in:
parent
54e312dccc
commit
15bc706d7a
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
data
|
||||
locationcode
|
||||
/locationcode
|
||||
|
47
airports.go
47
airports.go
@ -10,7 +10,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
@ -24,14 +23,9 @@ import (
|
||||
"go.ntppool.org/common/tracing"
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type Airport struct {
|
||||
Name string
|
||||
Code string
|
||||
Distance float64
|
||||
data *alphafoxtrot.Airport
|
||||
}
|
||||
"go.askask.com/locationcode/types"
|
||||
)
|
||||
|
||||
type Finder struct {
|
||||
f *alphafoxtrot.AirportFinder
|
||||
@ -191,7 +185,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Finder) GetAirports(ctx context.Context, cc string, radiusKM, latitude, longitude float64) ([]*Airport, error) {
|
||||
func (f *Finder) GetAirports(ctx context.Context, cc string, radiusKM, latitude, longitude float64) ([]*types.Airport, error) {
|
||||
log := logger.FromContext(ctx)
|
||||
log.InfoContext(ctx, fmt.Sprintf("GetAirports(%s %.2f %.4f %.4f)", cc, radiusKM, latitude, longitude))
|
||||
|
||||
@ -215,39 +209,24 @@ func (f *Finder) GetAirports(ctx context.Context, cc string, radiusKM, latitude,
|
||||
airports = append(airports, ap)
|
||||
}
|
||||
|
||||
llCache := map[int]s2.LatLng{}
|
||||
for i, ap := range airports {
|
||||
ll := s2.LatLngFromDegrees(ap.LatitudeDeg, ap.LongitudeDeg)
|
||||
llCache[i] = ll
|
||||
}
|
||||
r := []*types.Airport{}
|
||||
|
||||
r := []*Airport{}
|
||||
for _, airport := range airports {
|
||||
// fmt.Printf("%d %s: %+v\n", i, airport.Name, airport)
|
||||
|
||||
for i, airport := range airports {
|
||||
fmt.Printf("%d %s: %+v\n", i, airport.Name, airport)
|
||||
a := types.NewAirport(airport)
|
||||
|
||||
code := strings.ToLower(airport.Country.ISOCode + airport.IATACode)
|
||||
ll := s2.LatLngFromDegrees(airport.LatitudeDeg, airport.LongitudeDeg)
|
||||
a.Distance = float64(ipLocation.Distance(ll)) * 6371.01
|
||||
|
||||
distance := float64(ipLocation.Distance(llCache[i])) * 6371.01
|
||||
|
||||
a := &Airport{
|
||||
Name: airport.Name,
|
||||
Code: code,
|
||||
Distance: distance,
|
||||
data: airport,
|
||||
}
|
||||
r = append(r, a)
|
||||
}
|
||||
|
||||
sort.Slice(r, func(i, j int) bool {
|
||||
if r[i].data.Type == r[j].data.Type {
|
||||
return r[i].Distance < r[j].Distance
|
||||
}
|
||||
return airports[i].Type < airports[j].Type
|
||||
})
|
||||
types.SortAirports(r)
|
||||
|
||||
if len(r) > 15 {
|
||||
r = r[0:15]
|
||||
maxReturns := 20
|
||||
if len(r) > maxReturns {
|
||||
r = r[0:maxReturns]
|
||||
}
|
||||
|
||||
log.InfoContext(ctx, "got airports", "count", len(airportsRaw), "filtered", len(airports), "returning", len(r))
|
||||
|
85
client/locationcode/locationcodeclient.go
Normal file
85
client/locationcode/locationcodeclient.go
Normal file
@ -0,0 +1,85 @@
|
||||
package locationcode
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"go.askask.com/locationcode/types"
|
||||
)
|
||||
|
||||
var client http.Client
|
||||
|
||||
func init() {
|
||||
netTransport := &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
}
|
||||
client = http.Client{
|
||||
Timeout: time.Second * 10,
|
||||
Transport: netTransport,
|
||||
}
|
||||
}
|
||||
|
||||
func GetAirports(ctx context.Context, countryCode string, lat, lng float64, radiusKM float64) ([]*types.Airport, error) {
|
||||
ctx, span := otel.Tracer("locationcode").Start(ctx, "locationcode.GetAirports")
|
||||
defer span.End()
|
||||
|
||||
baseURL := os.Getenv("locationcode_service")
|
||||
if len(baseURL) == 0 {
|
||||
return nil, fmt.Errorf("locationcode_service not configured")
|
||||
}
|
||||
|
||||
q := url.Values{}
|
||||
q.Set("cc", countryCode)
|
||||
if radiusKM > 0 {
|
||||
q.Set("radius", fmt.Sprintf("%f", radiusKM))
|
||||
}
|
||||
q.Set("lat", fmt.Sprintf("%f", lat))
|
||||
q.Set("lng", fmt.Sprintf("%f", lng))
|
||||
|
||||
reqURL, err := url.Parse(fmt.Sprintf("http://%s/v1/code?%s", baseURL, q.Encode()))
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
span.SetAttributes(attribute.String("url", reqURL.String()))
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", reqURL.String(), nil)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// io.Copy(os.Stdout, resp.Body)
|
||||
// return nil, nil
|
||||
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
|
||||
airports := []*types.Airport{}
|
||||
err = dec.Decode(&airports)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return airports, nil
|
||||
}
|
2
go.mod
2
go.mod
@ -12,6 +12,7 @@ require (
|
||||
github.com/samber/slog-echo v1.15.0
|
||||
go.ntppool.org/common v0.3.1
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.58.0
|
||||
go.opentelemetry.io/otel v1.33.0
|
||||
golang.org/x/sync v0.10.0
|
||||
)
|
||||
|
||||
@ -44,7 +45,6 @@ require (
|
||||
go.opentelemetry.io/contrib/bridges/otelslog v0.8.0 // indirect
|
||||
go.opentelemetry.io/contrib/bridges/prometheus v0.58.0 // indirect
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.58.0 // indirect
|
||||
go.opentelemetry.io/otel v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.9.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.9.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0 // indirect
|
||||
|
57
types/airport_type.go
Normal file
57
types/airport_type.go
Normal file
@ -0,0 +1,57 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
alphafoxtrot "github.com/grumpypixel/go-airport-finder"
|
||||
)
|
||||
|
||||
type Airport struct {
|
||||
Name string
|
||||
Code string
|
||||
Distance float64
|
||||
Type string
|
||||
|
||||
data *alphafoxtrot.Airport
|
||||
}
|
||||
|
||||
func NewAirport(airport *alphafoxtrot.Airport) *Airport {
|
||||
code := strings.ToLower(airport.Country.ISOCode + airport.IATACode)
|
||||
|
||||
a := &Airport{
|
||||
Name: airport.Name,
|
||||
Code: code,
|
||||
Type: airport.Type,
|
||||
data: airport,
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Airport) String() string {
|
||||
return a.Name
|
||||
}
|
||||
|
||||
func UniqAirports(r []*Airport) []*Airport {
|
||||
seen := make(map[string]struct{})
|
||||
j := 0
|
||||
for _, v := range r {
|
||||
if _, ok := seen[v.Code]; ok {
|
||||
continue
|
||||
}
|
||||
seen[v.Code] = struct{}{}
|
||||
r[j] = v
|
||||
j++
|
||||
}
|
||||
return r[:j]
|
||||
}
|
||||
|
||||
func SortAirports(r []*Airport) {
|
||||
sort.Slice(r, func(i, j int) bool {
|
||||
if r[i].data.Type == r[j].data.Type {
|
||||
return r[i].Distance < r[j].Distance
|
||||
}
|
||||
return r[i].data.Type < r[j].data.Type
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user