Skip to content

Commit

Permalink
Added GetExtents method
Browse files Browse the repository at this point in the history
  • Loading branch information
jo-asplin-met-no committed Nov 15, 2023
1 parent 9dd1546 commit 3b5d798
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 1 deletion.
18 changes: 18 additions & 0 deletions datastore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,24 @@ $ grpcurl -d '{"standard_names": ["wind_speed", "air_temperature"], "interval":
...
```

### Getting the time- and geo extent of all observations currently in the storage

```text
$ grpcurl -plaintext -proto protobuf/datastore.proto 127.0.0.1:50050 datastore.Datastore.GetExtents
{
"timeExtent": {
"start": "2022-12-31T00:00:00Z",
"end": "2022-12-31T23:50:00Z"
},
"geoExtent": {
"xMin": -68.2758333,
"yMin": 12.13,
"xMax": 7.1493220605216,
"yMax": 55.399166666667
}
}
```

## Testing the datastore service with a Python client

### Compiling the protobuf file
Expand Down
20 changes: 20 additions & 0 deletions datastore/dsimpl/getextents.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dsimpl

import (
"context"
"fmt"

"datastore/datastore"
)

func (svcInfo *ServiceInfo) GetExtents(
ctx context.Context, request *datastore.GetExtentsRequest) (
*datastore.GetExtentsResponse, error) {

response, err := svcInfo.Sbe.GetExtents(request)
if err != nil {
return nil, fmt.Errorf("svcInfo.Sbe.GetExtents() failed: %v", err)
}

return response, nil
}
22 changes: 21 additions & 1 deletion datastore/protobuf/datastore.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ option go_package = "./datastore";
service Datastore {
rpc PutObservations(PutObsRequest) returns (PutObsResponse);
rpc GetObservations(GetObsRequest) returns (GetObsResponse);
rpc GetExtents(GetExtentsRequest) returns (GetExtentsResponse);
}

//---------------------------------------------------------------------------
Expand All @@ -35,6 +36,13 @@ message Polygon { // horizontal area; three or more points
repeated Point points = 1;
}

message BoundingBox {
double xMin = 1;
double yMin = 2;
double xMax = 3;
double yMax = 4;
}

message TimeInterval {
google.protobuf.Timestamp start = 1;
google.protobuf.Timestamp end = 2;
Expand Down Expand Up @@ -127,9 +135,21 @@ message GetObsRequest {
// TODO: add search filters for other metadata
}


message GetObsResponse {
int32 status = 1;
string error = 2; // any error description (empty on success)
repeated Metadata2 observations = 3;
}

//---------------------------------------------------------------------------

message GetExtentsRequest {
// currently no args
}

message GetExtentsResponse {
int32 status = 1;
string error = 2; // any error description (empty on success)
TimeInterval time_extent = 3;
BoundingBox geo_extent = 4;
}
71 changes: 71 additions & 0 deletions datastore/storagebackend/postgresql/getextents.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package postgresql

import (
"database/sql"
"datastore/datastore"
"fmt"
"time"

_ "github.com/lib/pq"
"google.golang.org/protobuf/types/known/timestamppb"
)

// getTimeExtent gets the current time extent of all observations in the storage.
func getTimeExtent(db *sql.DB) (*datastore.TimeInterval, error) {
query := "SELECT min(obstime_instant), max(obstime_instant) FROM observation"
row := db.QueryRow(query)

var start, end time.Time

err := row.Scan(&start, &end)
if err != nil {
return nil, fmt.Errorf("row.Scan() failed: %v", err)
}

return &datastore.TimeInterval{
Start: timestamppb.New(start),
End: timestamppb.New(end),
}, nil
}

// getGeoExtent gets the current geo extent of all observations in the storage.
func getGeoExtent(db *sql.DB) (*datastore.BoundingBox, error) {
query := `
SELECT ST_XMin(ext), ST_YMin(ext), ST_XMax(ext), ST_YMax(ext)
FROM (SELECT ST_Extent(point::geometry) AS ext FROM geo_point) t
`
row := db.QueryRow(query)

var xmin, ymin, xmax, ymax float64

err := row.Scan(&xmin, &ymin, &xmax, &ymax)
if err != nil {
return nil, fmt.Errorf("row.Scan() failed: %v", err)
}

return &datastore.BoundingBox{
XMin: xmin,
YMin: ymin,
XMax: xmax,
YMax: ymax,
}, nil
}

// GetExtents ... (see documentation in StorageBackend interface)
func (sbe *PostgreSQL) GetExtents(request *datastore.GetExtentsRequest) (
*datastore.GetExtentsResponse, error) {

var err error

timeExtent, err := getTimeExtent(sbe.Db)
if err != nil {
return nil, fmt.Errorf("getTimeExtent() failed: %v", err)
}

geoExtent, err := getGeoExtent(sbe.Db)
if err != nil {
return nil, fmt.Errorf("getGeoExtent() failed: %v", err)
}

return &datastore.GetExtentsResponse{TimeExtent: timeExtent, GeoExtent: geoExtent}, nil
}
4 changes: 4 additions & 0 deletions datastore/storagebackend/storagebackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ type StorageBackend interface {
// GetObservations retrieves observations from the storage.
// Returns nil upon success, otherwise error.
GetObservations(*datastore.GetObsRequest) (*datastore.GetObsResponse, error)

// GetExtents gets the time- and geo extents of all currently stored observations.
// Returns nil upon success, otherwise error.
GetExtents(*datastore.GetExtentsRequest) (*datastore.GetExtentsResponse, error)
}

0 comments on commit 3b5d798

Please sign in to comment.