mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-15 12:34:44 +00:00
Multitenant streams api (#72)
This commit is contained in:
@@ -93,7 +93,7 @@ func (l *Places) Last(ctx context.Context, req *pb.LastRequest, rsp *pb.ListResp
|
||||
}
|
||||
|
||||
// query the database
|
||||
q := l.DB.Raw("SELECT DISTINCT ON (place_id) place_id, timestamp, latitude, longitude FROM places WHERE place_id IN (?) ORDER BY place_id, timestamp DESC", req.Ids)
|
||||
q := l.DB.Raw("SELECT DISTINCT ON (place_id) place_id, timestamp, latitude, longitude FROM locations WHERE place_id IN (?) ORDER BY place_id, timestamp DESC", req.Ids)
|
||||
var locs []*model.Location
|
||||
if err := q.Find(&locs).Error; err != nil {
|
||||
logger.Errorf("Error reading from the database: %v", err)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"github.com/google/uuid"
|
||||
geo "github.com/hailocab/go-geoindex"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -22,29 +23,29 @@ import (
|
||||
|
||||
func testHandler(t *testing.T) pb.PlacesHandler {
|
||||
// connect to the database
|
||||
db, err := gorm.Open(postgres.Open("postgresql://postgres@localhost:5432/places?sslmode=disable"), &gorm.Config{})
|
||||
addr := os.Getenv("POSTGRES_URL")
|
||||
if len(addr) == 0 {
|
||||
addr = "postgresql://postgres@localhost:5432/postgres?sslmode=disable"
|
||||
}
|
||||
db, err := gorm.Open(postgres.Open(addr), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatalf("Error connecting to database: %v", err)
|
||||
}
|
||||
|
||||
// clean any data from a previous run
|
||||
if err := db.Exec("DROP TABLE IF EXISTS locations CASCADE").Error; err != nil {
|
||||
t.Fatalf("Error cleaning database: %v", err)
|
||||
}
|
||||
|
||||
// migrate the database
|
||||
if err := db.AutoMigrate(&model.Location{}); err != nil {
|
||||
t.Fatalf("Error migrating database: %v", err)
|
||||
}
|
||||
|
||||
// clean any data from a previous run
|
||||
if err := db.Exec("TRUNCATE TABLE places CASCADE").Error; err != nil {
|
||||
t.Fatalf("Error cleaning database: %v", err)
|
||||
}
|
||||
|
||||
return &handler.Places{DB: db, Geoindex: geo.NewPointsIndex(geo.Km(0.1))}
|
||||
}
|
||||
|
||||
func TestSave(t *testing.T) {
|
||||
if v := os.Getenv("IN_TRAVIS_CI"); v == "yes" {
|
||||
return
|
||||
}
|
||||
|
||||
tt := []struct {
|
||||
Name string
|
||||
Places []*pb.Location
|
||||
@@ -116,9 +117,6 @@ func TestSave(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLast(t *testing.T) {
|
||||
if v := os.Getenv("IN_TRAVIS_CI"); v == "yes" {
|
||||
return
|
||||
}
|
||||
h := testHandler(t)
|
||||
|
||||
t.Run("MissingIDs", func(t *testing.T) {
|
||||
@@ -134,24 +132,25 @@ func TestLast(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, rsp.Places)
|
||||
})
|
||||
tn := time.Now()
|
||||
|
||||
// generate some example data to work with
|
||||
loc1 := &pb.Location{
|
||||
Latitude: &wrapperspb.DoubleValue{Value: 51.5007},
|
||||
Longitude: &wrapperspb.DoubleValue{Value: 0.1246},
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Timestamp: timestamppb.New(tn),
|
||||
Id: "a",
|
||||
}
|
||||
loc2 := &pb.Location{
|
||||
Latitude: &wrapperspb.DoubleValue{Value: 51.6007},
|
||||
Longitude: &wrapperspb.DoubleValue{Value: 0.1546},
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Timestamp: timestamppb.New(tn.Add(1 * time.Microsecond)),
|
||||
Id: "b",
|
||||
}
|
||||
loc3 := &pb.Location{
|
||||
Latitude: &wrapperspb.DoubleValue{Value: 52.6007},
|
||||
Longitude: &wrapperspb.DoubleValue{Value: 0.2546},
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Timestamp: timestamppb.New(tn.Add(2 * time.Microsecond)),
|
||||
Id: loc2.Id,
|
||||
}
|
||||
err := h.Save(context.TODO(), &pb.SaveRequest{
|
||||
@@ -162,7 +161,7 @@ func TestLast(t *testing.T) {
|
||||
t.Run("OneUser", func(t *testing.T) {
|
||||
var rsp pb.ListResponse
|
||||
err := h.Last(context.Background(), &pb.LastRequest{
|
||||
Ids: []string{loc2.Id},
|
||||
Ids: []string{loc3.Id},
|
||||
}, &rsp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -172,8 +171,9 @@ func TestLast(t *testing.T) {
|
||||
assert.Equal(t, loc3.Id, rsp.Places[0].Id)
|
||||
assert.Equal(t, loc3.Latitude.Value, rsp.Places[0].Latitude.Value)
|
||||
assert.Equal(t, loc3.Longitude.Value, rsp.Places[0].Longitude.Value)
|
||||
assert.Equal(t, loc3.Timestamp.AsTime(), rsp.Places[0].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc3.Timestamp), microSecondTime(rsp.Places[0].Timestamp))
|
||||
})
|
||||
|
||||
t.Run("ManyUser", func(t *testing.T) {
|
||||
var rsp pb.ListResponse
|
||||
err := h.Last(context.Background(), &pb.LastRequest{
|
||||
@@ -193,19 +193,16 @@ func TestLast(t *testing.T) {
|
||||
assert.Equal(t, loc1.Id, rsp.Places[1].Id)
|
||||
assert.Equal(t, loc1.Latitude.Value, rsp.Places[1].Latitude.Value)
|
||||
assert.Equal(t, loc1.Longitude.Value, rsp.Places[1].Longitude.Value)
|
||||
assert.Equal(t, loc1.Timestamp.AsTime(), rsp.Places[1].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc1.Timestamp), microSecondTime(rsp.Places[1].Timestamp))
|
||||
|
||||
assert.Equal(t, loc3.Id, rsp.Places[0].Id)
|
||||
assert.Equal(t, loc3.Latitude.Value, rsp.Places[0].Latitude.Value)
|
||||
assert.Equal(t, loc3.Longitude.Value, rsp.Places[0].Longitude.Value)
|
||||
assert.Equal(t, loc3.Timestamp.AsTime(), rsp.Places[0].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc3.Timestamp), microSecondTime(rsp.Places[0].Timestamp))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNear(t *testing.T) {
|
||||
if v := os.Getenv("IN_TRAVIS_CI"); v == "yes" {
|
||||
return
|
||||
}
|
||||
lat := &wrapperspb.DoubleValue{Value: 51.510357}
|
||||
lng := &wrapperspb.DoubleValue{Value: -0.116773}
|
||||
rad := &wrapperspb.DoubleValue{Value: 2.0}
|
||||
@@ -401,9 +398,6 @@ func TestNear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRead(t *testing.T) {
|
||||
if v := os.Getenv("IN_TRAVIS_CI"); v == "yes" {
|
||||
return
|
||||
}
|
||||
h := testHandler(t)
|
||||
|
||||
baseTime := time.Now().Add(time.Hour * -24)
|
||||
@@ -482,12 +476,12 @@ func TestRead(t *testing.T) {
|
||||
assert.Equal(t, loc2.Id, rsp.Places[0].Id)
|
||||
assert.Equal(t, loc2.Latitude.Value, rsp.Places[0].Latitude.Value)
|
||||
assert.Equal(t, loc2.Longitude.Value, rsp.Places[0].Longitude.Value)
|
||||
assert.Equal(t, loc2.Timestamp.AsTime(), rsp.Places[0].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc2.Timestamp), microSecondTime(rsp.Places[0].Timestamp))
|
||||
|
||||
assert.Equal(t, loc3.Id, rsp.Places[1].Id)
|
||||
assert.Equal(t, loc3.Latitude.Value, rsp.Places[1].Latitude.Value)
|
||||
assert.Equal(t, loc3.Longitude.Value, rsp.Places[1].Longitude.Value)
|
||||
assert.Equal(t, loc3.Timestamp.AsTime(), rsp.Places[1].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc3.Timestamp), microSecondTime(rsp.Places[1].Timestamp))
|
||||
})
|
||||
|
||||
t.Run("OnePlaceIDReducedTime", func(t *testing.T) {
|
||||
@@ -505,7 +499,7 @@ func TestRead(t *testing.T) {
|
||||
assert.Equal(t, loc2.Id, rsp.Places[0].Id)
|
||||
assert.Equal(t, loc2.Latitude.Value, rsp.Places[0].Latitude.Value)
|
||||
assert.Equal(t, loc2.Longitude.Value, rsp.Places[0].Longitude.Value)
|
||||
assert.Equal(t, loc2.Timestamp.AsTime(), rsp.Places[0].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc2.Timestamp), microSecondTime(rsp.Places[0].Timestamp))
|
||||
})
|
||||
|
||||
t.Run("TwoPlaceIDs", func(t *testing.T) {
|
||||
@@ -523,11 +517,17 @@ func TestRead(t *testing.T) {
|
||||
assert.Equal(t, loc1.Id, rsp.Places[0].Id)
|
||||
assert.Equal(t, loc1.Latitude.Value, rsp.Places[0].Latitude.Value)
|
||||
assert.Equal(t, loc1.Longitude.Value, rsp.Places[0].Longitude.Value)
|
||||
assert.Equal(t, loc1.Timestamp.AsTime(), rsp.Places[0].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc1.Timestamp), microSecondTime(rsp.Places[0].Timestamp))
|
||||
|
||||
assert.Equal(t, loc2.Id, rsp.Places[1].Id)
|
||||
assert.Equal(t, loc2.Latitude.Value, rsp.Places[1].Latitude.Value)
|
||||
assert.Equal(t, loc2.Longitude.Value, rsp.Places[1].Longitude.Value)
|
||||
assert.Equal(t, loc2.Timestamp.AsTime(), rsp.Places[1].Timestamp.AsTime())
|
||||
assert.Equal(t, microSecondTime(loc2.Timestamp), microSecondTime(rsp.Places[1].Timestamp))
|
||||
})
|
||||
}
|
||||
|
||||
// postgres has a resolution of 100microseconds so just test that it's accurate to the second
|
||||
func microSecondTime(t *timestamp.Timestamp) time.Time {
|
||||
tt := t.AsTime()
|
||||
return time.Unix(tt.Unix(), int64(tt.Nanosecond()-tt.Nanosecond()%1000))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user