From 162eec5cc10907c32ab313ae57e19a94fc301cfe Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Tue, 17 Aug 2021 12:42:51 +1000 Subject: [PATCH 01/10] =?UTF-8?q?Race=20List=20--=20racing.proto:=20?= =?UTF-8?q?=E2=80=A2=20Add=20optional=20`visible`=20parameter=20to=20ListR?= =?UTF-8?q?acesRequestFilter.=20races.proto:=20=E2=80=A2=20Use=20optional?= =?UTF-8?q?=20visibility=20filter=20parameter=20to=20filter=20returned=20d?= =?UTF-8?q?ataset.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/proto/racing/racing.pb.go | 57 +++++++++++++++++++------------- api/proto/racing/racing.proto | 1 + racing/db/races.go | 12 +++++-- racing/proto/racing/racing.pb.go | 54 ++++++++++++++++++------------ racing/proto/racing/racing.proto | 1 + 5 files changed, 79 insertions(+), 46 deletions(-) diff --git a/api/proto/racing/racing.pb.go b/api/proto/racing/racing.pb.go index 532aa22..f47b04c 100644 --- a/api/proto/racing/racing.pb.go +++ b/api/proto/racing/racing.pb.go @@ -125,6 +125,7 @@ type ListRacesRequestFilter struct { unknownFields protoimpl.UnknownFields MeetingIds []int64 `protobuf:"varint,1,rep,packed,name=meeting_ids,json=meetingIds,proto3" json:"meeting_ids,omitempty"` + Visible *bool `protobuf:"varint,2,opt,name=visible,proto3,oneof" json:"visible,omitempty"` } func (x *ListRacesRequestFilter) Reset() { @@ -166,6 +167,13 @@ func (x *ListRacesRequestFilter) GetMeetingIds() []int64 { return nil } +func (x *ListRacesRequestFilter) GetVisible() bool { + if x != nil && x.Visible != nil { + return *x.Visible + } + return false +} + // A race resource. type Race struct { state protoimpl.MessageState @@ -277,31 +285,33 @@ var file_racing_racing_proto_rawDesc = []byte{ 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x61, 0x63, 0x65, 0x52, 0x05, 0x72, 0x61, 0x63, 0x65, - 0x73, 0x22, 0x39, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x22, 0x64, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, - 0x52, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x73, 0x22, 0xcb, 0x01, 0x0a, - 0x04, 0x52, 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, 0x65, 0x65, 0x74, 0x69, - 0x6e, 0x67, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0x18, 0x0a, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x4e, 0x0a, 0x15, 0x61, 0x64, - 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x13, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, - 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x32, 0x65, 0x0a, 0x06, 0x52, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x12, 0x5b, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, - 0x73, 0x12, 0x18, 0x2e, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x22, 0x0e, - 0x2f, 0x76, 0x31, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x72, 0x61, 0x63, 0x65, 0x73, 0x3a, 0x01, - 0x2a, 0x42, 0x09, 0x5a, 0x07, 0x2f, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x07, + 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, + 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, + 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0xcb, 0x01, 0x0a, 0x04, 0x52, 0x61, 0x63, 0x65, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x4e, 0x0a, 0x15, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, + 0x73, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x13, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x32, 0x65, 0x0a, 0x06, 0x52, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x12, + 0x5b, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x72, + 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6c, + 0x69, 0x73, 0x74, 0x2d, 0x72, 0x61, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x42, 0x09, 0x5a, 0x07, + 0x2f, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -392,6 +402,7 @@ func file_racing_racing_proto_init() { } } } + file_racing_racing_proto_msgTypes[2].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/api/proto/racing/racing.proto b/api/proto/racing/racing.proto index 416faab..f77fb48 100644 --- a/api/proto/racing/racing.proto +++ b/api/proto/racing/racing.proto @@ -28,6 +28,7 @@ message ListRacesResponse { // Filter for listing races. message ListRacesRequestFilter { repeated int64 meeting_ids = 1; + optional bool visible = 2; } /* Resources */ diff --git a/racing/db/races.go b/racing/db/races.go index df14a14..0d42b3e 100644 --- a/racing/db/races.go +++ b/racing/db/races.go @@ -2,12 +2,13 @@ package db import ( "database/sql" - "github.com/golang/protobuf/ptypes" - _ "github.com/mattn/go-sqlite3" "strings" "sync" "time" + "github.com/golang/protobuf/ptypes" + _ "github.com/mattn/go-sqlite3" + "git.neds.sh/matty/entain/racing/proto/racing" ) @@ -71,6 +72,13 @@ func (r *racesRepo) applyFilter(query string, filter *racing.ListRacesRequestFil return query, args } + if filter.Visible != nil { + // Visibility is optional. If nil, then allow non filtering of + // visibility. + clauses = append(clauses, "visible = ?") + args = append(args, filter.Visible) + } + if len(filter.MeetingIds) > 0 { clauses = append(clauses, "meeting_id IN ("+strings.Repeat("?,", len(filter.MeetingIds)-1)+"?)") diff --git a/racing/proto/racing/racing.pb.go b/racing/proto/racing/racing.pb.go index 7f8f979..a59fc97 100644 --- a/racing/proto/racing/racing.pb.go +++ b/racing/proto/racing/racing.pb.go @@ -123,6 +123,7 @@ type ListRacesRequestFilter struct { unknownFields protoimpl.UnknownFields MeetingIds []int64 `protobuf:"varint,1,rep,packed,name=meeting_ids,json=meetingIds,proto3" json:"meeting_ids,omitempty"` + Visible *bool `protobuf:"varint,2,opt,name=visible,proto3,oneof" json:"visible,omitempty"` } func (x *ListRacesRequestFilter) Reset() { @@ -164,6 +165,13 @@ func (x *ListRacesRequestFilter) GetMeetingIds() []int64 { return nil } +func (x *ListRacesRequestFilter) GetVisible() bool { + if x != nil && x.Visible != nil { + return *x.Visible + } + return false +} + // A race resource. type Race struct { state protoimpl.MessageState @@ -273,29 +281,32 @@ var file_racing_racing_proto_rawDesc = []byte{ 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x61, 0x63, 0x65, 0x52, 0x05, 0x72, 0x61, - 0x63, 0x65, 0x73, 0x22, 0x39, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, + 0x63, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x03, 0x52, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x73, 0x22, 0xcb, - 0x01, 0x0a, 0x04, 0x52, 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, - 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, 0x65, 0x65, - 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x4e, 0x0a, 0x15, - 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x13, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x73, 0x65, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x32, 0x4c, 0x0a, 0x06, - 0x52, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x42, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, - 0x63, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x09, 0x5a, 0x07, 0x2f, 0x72, - 0x61, 0x63, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x03, 0x52, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x73, 0x12, 0x1d, + 0x0a, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, + 0x00, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, + 0x08, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0xcb, 0x01, 0x0a, 0x04, 0x52, 0x61, + 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x49, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x4e, 0x0a, 0x15, 0x61, 0x64, 0x76, 0x65, 0x72, + 0x74, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x13, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x32, 0x4c, 0x0a, 0x06, 0x52, 0x61, 0x63, 0x69, 0x6e, + 0x67, 0x12, 0x42, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x12, 0x18, + 0x2e, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x61, 0x63, 0x69, 0x6e, + 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x09, 0x5a, 0x07, 0x2f, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -386,6 +397,7 @@ func file_racing_racing_proto_init() { } } } + file_racing_racing_proto_msgTypes[2].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/racing/proto/racing/racing.proto b/racing/proto/racing/racing.proto index 0a1f183..424152d 100644 --- a/racing/proto/racing/racing.proto +++ b/racing/proto/racing/racing.proto @@ -24,6 +24,7 @@ message ListRacesResponse { // Filter for listing races. message ListRacesRequestFilter { repeated int64 meeting_ids = 1; + optional bool visible = 2; } /* Resources */ From 19be6d18bb137f59773543f5412656a11bbf6c32 Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Wed, 18 Aug 2021 14:05:23 +1000 Subject: [PATCH 02/10] =?UTF-8?q?racing.proto:=20=E2=80=A2=20Provide=20des?= =?UTF-8?q?cription=20of=20`visible`=20request=20filter.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/proto/racing/racing.proto | 1 + racing/proto/racing/racing.proto | 1 + 2 files changed, 2 insertions(+) diff --git a/api/proto/racing/racing.proto b/api/proto/racing/racing.proto index f77fb48..ab51a4e 100644 --- a/api/proto/racing/racing.proto +++ b/api/proto/racing/racing.proto @@ -28,6 +28,7 @@ message ListRacesResponse { // Filter for listing races. message ListRacesRequestFilter { repeated int64 meeting_ids = 1; + // Returns Races that have `visible` set to the requested value. optional bool visible = 2; } diff --git a/racing/proto/racing/racing.proto b/racing/proto/racing/racing.proto index 424152d..6167103 100644 --- a/racing/proto/racing/racing.proto +++ b/racing/proto/racing/racing.proto @@ -24,6 +24,7 @@ message ListRacesResponse { // Filter for listing races. message ListRacesRequestFilter { repeated int64 meeting_ids = 1; + // Returns Races that have `visible` set to the requested value. optional bool visible = 2; } From dc52f2db8b3138b3a68bb9d9f7635404092d08dc Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Wed, 18 Aug 2021 21:30:25 +1000 Subject: [PATCH 03/10] =?UTF-8?q?races=5Ftest.go:=20=E2=80=A2=20Added=20ba?= =?UTF-8?q?sic=20test=20case=20for=20filtering=20with=20visibility.=20db.g?= =?UTF-8?q?o:=20=E2=80=A2=20Allow=20for=20clearing=20and=20insertion=20of?= =?UTF-8?q?=20database=20records.=20races.go:=20=E2=80=A2=20Added=20`Inser?= =?UTF-8?q?tRace`=20and=20`Clear`=20to=20RacesRepo=20interface=20for=20tes?= =?UTF-8?q?ting=20purposes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- api/go.mod | 2 +- api/main.go | 2 +- racing/db/db.go | 28 +++++++ racing/db/races.go | 15 +++- racing/db/races_test.go | 161 +++++++++++++++++++++++++++++++++++++++ racing/db/racing.db | Bin 16384 -> 0 bytes racing/go.mod | 2 +- racing/main.go | 27 +++++-- racing/service/racing.go | 4 +- 10 files changed, 231 insertions(+), 13 deletions(-) create mode 100644 racing/db/races_test.go delete mode 100644 racing/db/racing.db diff --git a/.gitignore b/.gitignore index 1851331..12443b3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ racing/racing *.out .idea .vscode -*/*.exe \ No newline at end of file +*/*.exe +*/**/*_testdata \ No newline at end of file diff --git a/api/go.mod b/api/go.mod index 9ff97b2..dccf52d 100644 --- a/api/go.mod +++ b/api/go.mod @@ -1,4 +1,4 @@ -module git.neds.sh/matty/entain/api +module github.com/ashleyjlive/entain/api go 1.16 diff --git a/api/main.go b/api/main.go index 5eb0368..a751648 100644 --- a/api/main.go +++ b/api/main.go @@ -5,8 +5,8 @@ import ( "flag" "net/http" + "github.com/ashleyjlive/entain/api/proto/racing" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "git.neds.sh/matty/entain/api/proto/racing" log "github.com/sirupsen/logrus" "google.golang.org/grpc" ) diff --git a/racing/db/db.go b/racing/db/db.go index 0980815..5422f91 100644 --- a/racing/db/db.go +++ b/racing/db/db.go @@ -1,8 +1,11 @@ package db import ( + "database/sql" "time" + "github.com/ashleyjlive/entain/racing/proto/racing" + "github.com/golang/protobuf/ptypes" "syreclabs.com/go/faker" ) @@ -28,3 +31,28 @@ func (r *racesRepo) seed() error { return err } + +func (r *racesRepo) insert(race *racing.Race) error { + var statement *sql.Stmt + ts, err := ptypes.Timestamp(race.AdvertisedStartTime) + if err != nil { + return err + } + statement, err = r.db.Prepare(`INSERT INTO races(id, meeting_id, name, number, visible, advertised_start_time) VALUES (?,?,?,?,?,?)`) + if err == nil { + _, err = statement.Exec( + &race.Id, + &race.MeetingId, + &race.Name, + &race.Number, + &race.Visible, + ts, + ) + } + return err +} + +func (r *racesRepo) clear() error { + _, err := r.db.Exec("DELETE FROM races") + return err +} diff --git a/racing/db/races.go b/racing/db/races.go index 0d42b3e..7a0a582 100644 --- a/racing/db/races.go +++ b/racing/db/races.go @@ -9,14 +9,15 @@ import ( "github.com/golang/protobuf/ptypes" _ "github.com/mattn/go-sqlite3" - "git.neds.sh/matty/entain/racing/proto/racing" + "github.com/ashleyjlive/entain/racing/proto/racing" ) // RacesRepo provides repository access to races. type RacesRepo interface { // Init will initialise our races repository. Init() error - + Clear() error + InsertRace(*racing.Race) error // List will return a list of races. List(filter *racing.ListRacesRequestFilter) ([]*racing.Race, error) } @@ -43,6 +44,16 @@ func (r *racesRepo) Init() error { return err } +// Clears all data in the races repository. +func (r *racesRepo) Clear() error { + return r.clear() +} + +// Allows insertions of a race into the repository. +func (r *racesRepo) InsertRace(race *racing.Race) error { + return r.insert(race) +} + func (r *racesRepo) List(filter *racing.ListRacesRequestFilter) ([]*racing.Race, error) { var ( err error diff --git a/racing/db/races_test.go b/racing/db/races_test.go new file mode 100644 index 0000000..850e3ef --- /dev/null +++ b/racing/db/races_test.go @@ -0,0 +1,161 @@ +package db_test + +import ( + "database/sql" + "strconv" + "testing" + "time" + + "github.com/ashleyjlive/entain/racing/db" + "github.com/ashleyjlive/entain/racing/proto/racing" + "github.com/golang/protobuf/ptypes" + "syreclabs.com/go/faker" +) + +func GetTestDB() (*sql.DB, error) { + return sql.Open("sqlite3", "races_testdata/test.db") +} + +func EnsureDB(t *testing.T) { + _, err := GetTestDB() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } +} + +func TestRepo(t *testing.T) { + racingDB, err := GetTestDB() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + racesRepo := db.NewRacesRepo(racingDB) + if err := racesRepo.Init(); err != nil { + t.Fatalf("Unexpected error %v", err) + } +} + +func TestNewRepo(t *testing.T) { + racingDB, err := GetTestDB() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + racesRepo := db.NewRacesRepo(racingDB) + err1 := racesRepo.Clear() + + if err1 != nil { + t.Fatalf("Unable to clear test database %v", err) + } +} + +func TestPopulateRepo(t *testing.T) { + racingDB, err := GetTestDB() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + racesRepo := db.NewRacesRepo(racingDB) + err = racesRepo.Clear() + if err != nil { + t.Fatalf("Unable to clear test database %v", err) + } + + if err != nil { + t.Fatalf("Unabale to convert time.") + } + races := getRaces() + err = racesRepo.InsertRace(races[0]) + if err != nil { + t.Fatalf("Unable to insert record into database.") + } +} + +func TestPopulateAndFetchRepo(t *testing.T) { + racingDB, err := GetTestDB() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + racesRepo := db.NewRacesRepo(racingDB) + err = racesRepo.Clear() + if err != nil { + t.Fatalf("Unable to clear test database %v", err) + } + + races := getRaces() + err = racesRepo.InsertRace(races[0]) + if err != nil { + t.Fatalf("Unable to insert record into database.") + } + var a []int64 + filter := racing.ListRacesRequestFilter{MeetingIds: a} + a = append(a, races[0].MeetingId) + rsp, err := racesRepo.List(&filter) + if err != nil { + t.Fatalf("Unable to retrieve races list.") + } + if len(rsp) != 1 { + t.Fatalf("Returned incorrect amount of races.") + } + if rsp[0].MeetingId != a[0] { + t.Fatalf("Incorrect item returned.") + } +} + +func TestPopulateAndFilterVisible(t *testing.T) { + racingDB, err := GetTestDB() + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + + racesRepo := db.NewRacesRepo(racingDB) + err = racesRepo.Clear() + if err != nil { + t.Fatalf("Unable to clear test database %v", err) + } + + races := getRaces() + err = racesRepo.InsertRace(races[0]) + if err != nil { + t.Fatalf("Unable to insert record into database.") + } + visible := true + filter := racing.ListRacesRequestFilter{Visible: &visible} + rsp, err := racesRepo.List(&filter) + if err != nil { + t.Fatalf("Unable to retrieve races list.") + } + if len(rsp) == 0 && races[0].Visible == true { + t.Fatalf("Unable to retrieve visible races list.") + } +} + +func getRaces() []*racing.Race { + var ( + races []*racing.Race + ) + for i := 1; i <= 100; i++ { + meetingId, _ := strconv.Atoi(faker.Number().Between(1, 10)) + name := faker.Team().Name() + number, _ := strconv.Atoi(faker.Number().Between(1, 12)) + visible := randBool() + tm, _ := ptypes.TimestampProto( + faker.Time().Between( + time.Now().AddDate(0, 0, -1), time.Now().AddDate(0, 0, 2))) + race := + racing.Race{Id: int64(i), MeetingId: int64(meetingId), + Name: name, Number: int64(number), + Visible: visible, AdvertisedStartTime: tm} + races = append(races, &race) + } + return races +} + +func randBool() bool { + v := faker.Number().Between(0, 1) + if v == "0" { + return false + } + return true +} diff --git a/racing/db/racing.db b/racing/db/racing.db deleted file mode 100644 index d262612517d723b7ab22029222363cd2e96fb3b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 Date: Thu, 19 Aug 2021 16:23:33 +1000 Subject: [PATCH 04/10] =?UTF-8?q?db.go,=20races=5Ftest:=20=E2=80=A2=20Impl?= =?UTF-8?q?ement=20ListAll=20without=20filter=20for=20test=20cases.=20?= =?UTF-8?q?=E2=80=A2=20Disable=20automatic=20seeding.=20races=5Ftest:=20?= =?UTF-8?q?=E2=80=A2=20Refined=20database=20and=20repo=20initialisation.?= =?UTF-8?q?=20=E2=80=A2=20Added=20tests=20for=20fetching=20empty=20repos?= =?UTF-8?q?=20and=20repo=20insertion.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racing/db/db.go | 44 +++++++++++++++-- racing/db/races.go | 8 +++- racing/db/races_test.go | 103 +++++++++++++++++++++++++++++++--------- 3 files changed, 127 insertions(+), 28 deletions(-) diff --git a/racing/db/db.go b/racing/db/db.go index 5422f91..272fdf3 100644 --- a/racing/db/db.go +++ b/racing/db/db.go @@ -9,14 +9,22 @@ import ( "syreclabs.com/go/faker" ) -func (r *racesRepo) seed() error { +func (r *racesRepo) init_tbl() error { statement, err := r.db.Prepare(`CREATE TABLE IF NOT EXISTS races (id INTEGER PRIMARY KEY, meeting_id INTEGER, name TEXT, number INTEGER, visible INTEGER, advertised_start_time DATETIME)`) if err == nil { _, err = statement.Exec() + return err + } else { + return err } +} +func (r *racesRepo) seed() error { + var ( + err error + ) for i := 1; i <= 100; i++ { - statement, err = r.db.Prepare(`INSERT OR IGNORE INTO races(id, meeting_id, name, number, visible, advertised_start_time) VALUES (?,?,?,?,?,?)`) + statement, err := r.db.Prepare(`INSERT OR IGNORE INTO races(id, meeting_id, name, number, visible, advertised_start_time) VALUES (?,?,?,?,?,?)`) if err == nil { _, err = statement.Exec( i, @@ -28,10 +36,40 @@ func (r *racesRepo) seed() error { ) } } - return err } +func (r *racesRepo) listAll() ([]*racing.Race, error) { + var races []*racing.Race + rows, err := + r.db.Query( + "SELECT id, meeting_id, name, number, visible, advertised_start_time FROM races") + if err != nil { + return nil, err + } + for rows.Next() { + var race racing.Race + var advertisedStart time.Time + + if err := rows.Scan(&race.Id, &race.MeetingId, &race.Name, &race.Number, &race.Visible, &advertisedStart); err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + + return nil, err + } + ts, err := ptypes.TimestampProto(advertisedStart) + if err != nil { + return nil, err + } + + race.AdvertisedStartTime = ts + + races = append(races, &race) + } + return races, nil +} + func (r *racesRepo) insert(race *racing.Race) error { var statement *sql.Stmt ts, err := ptypes.Timestamp(race.AdvertisedStartTime) diff --git a/racing/db/races.go b/racing/db/races.go index 7a0a582..fa8e41a 100644 --- a/racing/db/races.go +++ b/racing/db/races.go @@ -20,6 +20,7 @@ type RacesRepo interface { InsertRace(*racing.Race) error // List will return a list of races. List(filter *racing.ListRacesRequestFilter) ([]*racing.Race, error) + ListAll() ([]*racing.Race, error) } type racesRepo struct { @@ -37,8 +38,7 @@ func (r *racesRepo) Init() error { var err error r.init.Do(func() { - // For test/example purposes, we seed the DB with some dummy races. - err = r.seed() + err = r.init_tbl() }) return err @@ -73,6 +73,10 @@ func (r *racesRepo) List(filter *racing.ListRacesRequestFilter) ([]*racing.Race, return r.scanRaces(rows) } +func (r *racesRepo) ListAll() ([]*racing.Race, error) { + return r.listAll() +} + func (r *racesRepo) applyFilter(query string, filter *racing.ListRacesRequestFilter) (string, []interface{}) { var ( clauses []string diff --git a/racing/db/races_test.go b/racing/db/races_test.go index 850e3ef..e0fb43a 100644 --- a/racing/db/races_test.go +++ b/racing/db/races_test.go @@ -2,6 +2,8 @@ package db_test import ( "database/sql" + "os" + "path/filepath" "strconv" "testing" "time" @@ -12,19 +14,8 @@ import ( "syreclabs.com/go/faker" ) -func GetTestDB() (*sql.DB, error) { - return sql.Open("sqlite3", "races_testdata/test.db") -} - -func EnsureDB(t *testing.T) { - _, err := GetTestDB() - if err != nil { - t.Fatalf("Unexpected error %v", err) - } -} - func TestRepo(t *testing.T) { - racingDB, err := GetTestDB() + racingDB, err := GetTestDB("races", "TestRepo") if err != nil { t.Fatalf("Unexpected error %v", err) } @@ -36,26 +27,27 @@ func TestRepo(t *testing.T) { } func TestNewRepo(t *testing.T) { - racingDB, err := GetTestDB() + racingDB, err := GetTestDB("races", "TestNewRepo") if err != nil { t.Fatalf("Unexpected error %v", err) } racesRepo := db.NewRacesRepo(racingDB) - err1 := racesRepo.Clear() + races, err := racesRepo.ListAll() - if err1 != nil { - t.Fatalf("Unable to clear test database %v", err) + if len(races) != 0 { + t.Fatal("New repo contains elements") } } func TestPopulateRepo(t *testing.T) { - racingDB, err := GetTestDB() + racingDB, err := GetTestDB("races", "TestPopulateRepo") if err != nil { t.Fatalf("Unexpected error %v", err) } racesRepo := db.NewRacesRepo(racingDB) + _ = racesRepo.Init() err = racesRepo.Clear() if err != nil { t.Fatalf("Unable to clear test database %v", err) @@ -64,7 +56,7 @@ func TestPopulateRepo(t *testing.T) { if err != nil { t.Fatalf("Unabale to convert time.") } - races := getRaces() + races := GetRaces() err = racesRepo.InsertRace(races[0]) if err != nil { t.Fatalf("Unable to insert record into database.") @@ -72,18 +64,19 @@ func TestPopulateRepo(t *testing.T) { } func TestPopulateAndFetchRepo(t *testing.T) { - racingDB, err := GetTestDB() + racingDB, err := GetTestDB("races", "TestPopulateAndFetchRepo") if err != nil { t.Fatalf("Unexpected error %v", err) } racesRepo := db.NewRacesRepo(racingDB) + _ = racesRepo.Init() err = racesRepo.Clear() if err != nil { t.Fatalf("Unable to clear test database %v", err) } - races := getRaces() + races := GetRaces() err = racesRepo.InsertRace(races[0]) if err != nil { t.Fatalf("Unable to insert record into database.") @@ -104,18 +97,19 @@ func TestPopulateAndFetchRepo(t *testing.T) { } func TestPopulateAndFilterVisible(t *testing.T) { - racingDB, err := GetTestDB() + racingDB, err := GetTestDB("races", "TestPopulateAndFilterVisible") if err != nil { t.Fatalf("Unexpected error %v", err) } racesRepo := db.NewRacesRepo(racingDB) + _ = racesRepo.Init() err = racesRepo.Clear() if err != nil { t.Fatalf("Unable to clear test database %v", err) } - races := getRaces() + races := GetRaces() err = racesRepo.InsertRace(races[0]) if err != nil { t.Fatalf("Unable to insert record into database.") @@ -131,7 +125,57 @@ func TestPopulateAndFilterVisible(t *testing.T) { } } -func getRaces() []*racing.Race { +func TestFetchAllEmpty(t *testing.T) { + racingDB, err := GetTestDB("races", "TestFetchAllEmpty") + if err != nil { + t.Fatalf("Failed to open testdb %v", err) + } + racesRepo := db.NewRacesRepo(racingDB) + _ = racesRepo.Init() + + races, err := racesRepo.ListAll() + if err != nil { + t.Fatalf("Failed to fetch all races %v.", err) + } + if len(races) > 0 { + t.Fatalf("List all request returned invalid dataset.") + } +} + +func TestFetchAll(t *testing.T) { + racingDB, err := GetTestDB("db", "TestPopulateAndFetchRepo") + if err != nil { + t.Fatalf("Failed to open testdb %v", err) + } + racesRepo := db.NewRacesRepo(racingDB) + _ = racesRepo.Init() + + races, _ := racesRepo.ListAll() + if len(races) > 0 { + t.Fatalf("List all request returned invalid dataset.") + } + races = GetRaces() + err = racesRepo.InsertRace(races[0]) + if err != nil { + t.Fatalf("Failed to insert race record.") + } + + outRaces, err := racesRepo.ListAll() + if err != nil { + t.Fatalf("Failed to list all list races %v", err) + } + if len(races) > 0 { + if outRaces[0].Id != races[0].Id { + t.Fatalf("Invalid race ID returned. Got %v, expected %v", outRaces[0].Id, races[0].Id) + } + } else { + t.Fatalf("Failed to fetch inserted race.") + } +} + +// Helpers // + +func GetRaces() []*racing.Race { var ( races []*racing.Race ) @@ -159,3 +203,16 @@ func randBool() bool { } return true } + +func GetTestDB(testType string, testName string) (*sql.DB, error) { + dir := filepath.Join(testType+"_testdata", testName) + err := os.RemoveAll(dir) + if err != nil { + return nil, err + } + err = os.MkdirAll(dir, os.ModeDir) + if err != nil { + return nil, err + } + return sql.Open("sqlite3", filepath.Join(dir, "test.db")) +} From 5584acf19f2c03c262239fd133c286d04ec80280 Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Thu, 19 Aug 2021 23:16:00 +1000 Subject: [PATCH 05/10] =?UTF-8?q?=E2=80=A2=20Add=20README.md=20for=20racin?= =?UTF-8?q?g=20service.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- racing/README.md | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 racing/README.md diff --git a/README.md b/README.md index f582e43..1c0b363 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Please treat the services provided as if they would live in a real-world environ ### Directory Structure - `api`: A basic REST gateway, forwarding requests onto service(s). -- `racing`: A very bare-bones racing service. +- [`racing`](racing/README.md): A very bare-bones racing service. ``` entain/ diff --git a/racing/README.md b/racing/README.md new file mode 100644 index 0000000..a646edd --- /dev/null +++ b/racing/README.md @@ -0,0 +1,26 @@ +# Racing Service +The racing service provides the ability to access racing events over a gRPC server. + +## Building +To build a executable simply call + + $ go build + +This will place a racing executable in the root directory. + +## Command Line + +You may provide optional command line arguments to the executable. +Currently, you may configure: +- `grpc-endpoint` - This is the endpoint that the front facing API server will speak to. +- `db_path` - This is the path of the database that the service will utilise. + +For example: + + $ ./racing --grpc-endpoint=localhost:8080 --db_path:/foo/bar/db.db + +## Testing + +To test individual packages: + + $ go test ./... \ No newline at end of file From 632547705a819d753a9d4dcf452690e874abc15e Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Thu, 19 Aug 2021 23:21:37 +1000 Subject: [PATCH 06/10] =?UTF-8?q?racing/proto/README.md:=20=E2=80=A2=20Add?= =?UTF-8?q?ed=20README.md=20file.=20racing/README.md:=20=E2=80=A2=20Added?= =?UTF-8?q?=20link=20to=20proto/README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racing/README.md | 4 ++++ racing/proto/README.md | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 racing/proto/README.md diff --git a/racing/README.md b/racing/README.md index a646edd..5733aa9 100644 --- a/racing/README.md +++ b/racing/README.md @@ -19,6 +19,10 @@ For example: $ ./racing --grpc-endpoint=localhost:8080 --db_path:/foo/bar/db.db +## API + +Please [see](proto/README.md) the documentation for the protobuf definitions. + ## Testing To test individual packages: diff --git a/racing/proto/README.md b/racing/proto/README.md new file mode 100644 index 0000000..da38d2d --- /dev/null +++ b/racing/proto/README.md @@ -0,0 +1,26 @@ +# racing/proto +This defines the protobuf message types for the racing API. + +## Racing API + +**RPCS** + +- `ListRaces(ListRacesRequest) (ListRacesResponse)` + +### ListRacesRequest +- Supports a filter parameter of type `ListRacesRequestFilter`. +- Supports a order_by parameter of the form defined by [Google API Design](https://cloud.google.com/apis/design/design_patterns#sorting_order). + +### ListRacesRequestFilter +- A list of integer IDs can be supplied to perform a bulk lookup request. (optional) +- A category filter can be supplied which finds any races which match the category (optional, case-insensitive). + +### ListRacesResponse +- Contains a list of all matching races for the given lookup. + +### Race +- The ID of the race (int64). +- The unique identifier for the races meeting (int64). +- The name of the race (string). +- The visibility of the race (bool). +- The advertised start time of the race (Timestamp). \ No newline at end of file From 25e8d9afaebc1e92e905ec93951c0463e38f1315 Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Thu, 19 Aug 2021 23:23:05 +1000 Subject: [PATCH 07/10] =?UTF-8?q?=E2=80=A2=20Fixed=20typo=20in=20racing/pr?= =?UTF-8?q?oto/README.md=20file.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racing/proto/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/racing/proto/README.md b/racing/proto/README.md index da38d2d..f6821c7 100644 --- a/racing/proto/README.md +++ b/racing/proto/README.md @@ -5,7 +5,7 @@ This defines the protobuf message types for the racing API. **RPCS** -- `ListRaces(ListRacesRequest) (ListRacesResponse)` +- `ListRaces(ListRacesRequest) ListRacesResponse` ### ListRacesRequest - Supports a filter parameter of type `ListRacesRequestFilter`. From 01a092de8a363c321465fcdeb8568fbd7bbfa460 Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Thu, 19 Aug 2021 23:26:11 +1000 Subject: [PATCH 08/10] =?UTF-8?q?=E2=80=A2=20Removed=20README=20line=20whi?= =?UTF-8?q?ch=20was=20in=20the=20wrong=20branch.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racing/proto/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/racing/proto/README.md b/racing/proto/README.md index f6821c7..58b5e2b 100644 --- a/racing/proto/README.md +++ b/racing/proto/README.md @@ -9,7 +9,6 @@ This defines the protobuf message types for the racing API. ### ListRacesRequest - Supports a filter parameter of type `ListRacesRequestFilter`. -- Supports a order_by parameter of the form defined by [Google API Design](https://cloud.google.com/apis/design/design_patterns#sorting_order). ### ListRacesRequestFilter - A list of integer IDs can be supplied to perform a bulk lookup request. (optional) From 576b82cd3b29c280d9bb499f277090c425cbcfa4 Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Thu, 19 Aug 2021 23:45:11 +1000 Subject: [PATCH 09/10] =?UTF-8?q?racing/db/races=5Ftest:=20=E2=80=A2=20Fix?= =?UTF-8?q?ed=20invalid=20testType=20of=20"db"=20for=20races=5Ftest.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racing/db/races_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/racing/db/races_test.go b/racing/db/races_test.go index e0fb43a..e3d9581 100644 --- a/racing/db/races_test.go +++ b/racing/db/races_test.go @@ -143,7 +143,7 @@ func TestFetchAllEmpty(t *testing.T) { } func TestFetchAll(t *testing.T) { - racingDB, err := GetTestDB("db", "TestPopulateAndFetchRepo") + racingDB, err := GetTestDB("races", "TestPopulateAndFetchRepo") if err != nil { t.Fatalf("Failed to open testdb %v", err) } From 7fca28870d71becd65475670157106c3b07ed71a Mon Sep 17 00:00:00 2001 From: "ASHLEYDESKTOP\\Ashley" Date: Fri, 20 Aug 2021 00:14:44 +1000 Subject: [PATCH 10/10] =?UTF-8?q?Seeding=20--=20=E2=80=A2=20Added=20seedin?= =?UTF-8?q?g=20as=20an=20optional=20start=20argument.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racing/db/races.go | 12 +++++++++--- racing/db/races_test.go | 12 ++++++------ racing/main.go | 3 ++- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/racing/db/races.go b/racing/db/races.go index fa8e41a..81e607f 100644 --- a/racing/db/races.go +++ b/racing/db/races.go @@ -15,7 +15,7 @@ import ( // RacesRepo provides repository access to races. type RacesRepo interface { // Init will initialise our races repository. - Init() error + Init(bool) error Clear() error InsertRace(*racing.Race) error // List will return a list of races. @@ -34,11 +34,17 @@ func NewRacesRepo(db *sql.DB) RacesRepo { } // Init prepares the race repository dummy data. -func (r *racesRepo) Init() error { +func (r *racesRepo) Init(seed bool) error { var err error r.init.Do(func() { - err = r.init_tbl() + if seed { + if err = r.seed(); err != nil { + err = r.init_tbl() + } + } else { + err = r.init_tbl() + } }) return err diff --git a/racing/db/races_test.go b/racing/db/races_test.go index e3d9581..9292baf 100644 --- a/racing/db/races_test.go +++ b/racing/db/races_test.go @@ -21,7 +21,7 @@ func TestRepo(t *testing.T) { } racesRepo := db.NewRacesRepo(racingDB) - if err := racesRepo.Init(); err != nil { + if err := racesRepo.Init(false); err != nil { t.Fatalf("Unexpected error %v", err) } } @@ -47,7 +47,7 @@ func TestPopulateRepo(t *testing.T) { } racesRepo := db.NewRacesRepo(racingDB) - _ = racesRepo.Init() + _ = racesRepo.Init(false) err = racesRepo.Clear() if err != nil { t.Fatalf("Unable to clear test database %v", err) @@ -70,7 +70,7 @@ func TestPopulateAndFetchRepo(t *testing.T) { } racesRepo := db.NewRacesRepo(racingDB) - _ = racesRepo.Init() + _ = racesRepo.Init(false) err = racesRepo.Clear() if err != nil { t.Fatalf("Unable to clear test database %v", err) @@ -103,7 +103,7 @@ func TestPopulateAndFilterVisible(t *testing.T) { } racesRepo := db.NewRacesRepo(racingDB) - _ = racesRepo.Init() + _ = racesRepo.Init(false) err = racesRepo.Clear() if err != nil { t.Fatalf("Unable to clear test database %v", err) @@ -131,7 +131,7 @@ func TestFetchAllEmpty(t *testing.T) { t.Fatalf("Failed to open testdb %v", err) } racesRepo := db.NewRacesRepo(racingDB) - _ = racesRepo.Init() + _ = racesRepo.Init(false) races, err := racesRepo.ListAll() if err != nil { @@ -148,7 +148,7 @@ func TestFetchAll(t *testing.T) { t.Fatalf("Failed to open testdb %v", err) } racesRepo := db.NewRacesRepo(racingDB) - _ = racesRepo.Init() + _ = racesRepo.Init(false) races, _ := racesRepo.ListAll() if len(races) > 0 { diff --git a/racing/main.go b/racing/main.go index e66dcd9..4aa4475 100644 --- a/racing/main.go +++ b/racing/main.go @@ -18,6 +18,7 @@ var ( grpcEndpoint = flag.String("grpc-endpoint", "localhost:9000", "gRPC server endpoint") dflt_db_path = filepath.Join(homeDir(), "entain", "racing", "data.db") db_path = flag.String("db_path", dflt_db_path, "The path of the database.") + seed = flag.Bool("seed", false, "Determines if sample data is to be inserted into the database") ) func main() { @@ -52,7 +53,7 @@ func run() error { } racesRepo := db.NewRacesRepo(racingDB) - if err := racesRepo.Init(); err != nil { + if err := racesRepo.Init(*seed); err != nil { return err }