Skip to content

Commit

Permalink
Add a built in created time field for Tickets and the ability to filt…
Browse files Browse the repository at this point in the history
…er Tickets by created time.
  • Loading branch information
sawagh committed Mar 19, 2020
1 parent 6cb47ce commit ce7061e
Show file tree
Hide file tree
Showing 17 changed files with 402 additions and 100 deletions.
20 changes: 18 additions & 2 deletions api/backend.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@
"items": {
"$ref": "#/definitions/openmatchDoubleRangeFilter"
},
"description": "Set of Filters indicating the filtering criteria. Selected players must\nmatch every Filter."
"description": "Set of Filters indicating the filtering criteria. Selected tickets must\nmatch every Filter."
},
"string_equals_filters": {
"type": "array",
Expand All @@ -312,8 +312,19 @@
"items": {
"$ref": "#/definitions/openmatchTagPresentFilter"
}
},
"created_before": {
"type": "string",
"format": "date-time",
"description": "If specified, only Tickets created before the specified time are selected."
},
"created_after": {
"type": "string",
"format": "date-time",
"description": "If specified, only Tickets created after the specified time are selected."
}
}
},
"description": "Pool specfies a set of criteria that are used to select a subset of Tickets\nthat meet all the criteria."
},
"openmatchReleaseTicketsRequest": {
"type": "object",
Expand Down Expand Up @@ -401,6 +412,11 @@
"$ref": "#/definitions/protobufAny"
},
"description": "Customized information not inspected by Open Match, to be used by the match\nmaking function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
},
"create_time": {
"type": "string",
"format": "date-time",
"description": "Create time represents the time at which this Ticket was created. It is\npopulated by Open Match at the time of Ticket creation."
}
},
"description": "A Ticket is a basic matchmaking entity in Open Match. A Ticket represents either an\nindividual 'Player' or a 'Group' of players. Open Match will not interpret\nwhat the Ticket represents but just treat it as a matchmaking unit with a set\nof SearchFields. Open Match stores the Ticket in state storage and enables an\nAssignment to be associated with this Ticket."
Expand Down
5 changes: 5 additions & 0 deletions api/evaluator.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@
"$ref": "#/definitions/protobufAny"
},
"description": "Customized information not inspected by Open Match, to be used by the match\nmaking function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
},
"create_time": {
"type": "string",
"format": "date-time",
"description": "Create time represents the time at which this Ticket was created. It is\npopulated by Open Match at the time of Ticket creation."
}
},
"description": "A Ticket is a basic matchmaking entity in Open Match. A Ticket represents either an\nindividual 'Player' or a 'Group' of players. Open Match will not interpret\nwhat the Ticket represents but just treat it as a matchmaking unit with a set\nof SearchFields. Open Match stores the Ticket in state storage and enables an\nAssignment to be associated with this Ticket."
Expand Down
5 changes: 5 additions & 0 deletions api/frontend.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@
"$ref": "#/definitions/protobufAny"
},
"description": "Customized information not inspected by Open Match, to be used by the match\nmaking function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
},
"create_time": {
"type": "string",
"format": "date-time",
"description": "Create time represents the time at which this Ticket was created. It is\npopulated by Open Match at the time of Ticket creation."
}
},
"description": "A Ticket is a basic matchmaking entity in Open Match. A Ticket represents either an\nindividual 'Player' or a 'Group' of players. Open Match will not interpret\nwhat the Ticket represents but just treat it as a matchmaking unit with a set\nof SearchFields. Open Match stores the Ticket in state storage and enables an\nAssignment to be associated with this Ticket."
Expand Down
20 changes: 18 additions & 2 deletions api/matchfunction.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
"items": {
"$ref": "#/definitions/openmatchDoubleRangeFilter"
},
"description": "Set of Filters indicating the filtering criteria. Selected players must\nmatch every Filter."
"description": "Set of Filters indicating the filtering criteria. Selected tickets must\nmatch every Filter."
},
"string_equals_filters": {
"type": "array",
Expand All @@ -178,8 +178,19 @@
"items": {
"$ref": "#/definitions/openmatchTagPresentFilter"
}
},
"created_before": {
"type": "string",
"format": "date-time",
"description": "If specified, only Tickets created before the specified time are selected."
},
"created_after": {
"type": "string",
"format": "date-time",
"description": "If specified, only Tickets created after the specified time are selected."
}
}
},
"description": "Pool specfies a set of criteria that are used to select a subset of Tickets\nthat meet all the criteria."
},
"openmatchRunRequest": {
"type": "object",
Expand Down Expand Up @@ -270,6 +281,11 @@
"$ref": "#/definitions/protobufAny"
},
"description": "Customized information not inspected by Open Match, to be used by the match\nmaking function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
},
"create_time": {
"type": "string",
"format": "date-time",
"description": "Create time represents the time at which this Ticket was created. It is\npopulated by Open Match at the time of Ticket creation."
}
},
"description": "A Ticket is a basic matchmaking entity in Open Match. A Ticket represents either an\nindividual 'Player' or a 'Group' of players. Open Match will not interpret\nwhat the Ticket represents but just treat it as a matchmaking unit with a set\nof SearchFields. Open Match stores the Ticket in state storage and enables an\nAssignment to be associated with this Ticket."
Expand Down
15 changes: 14 additions & 1 deletion api/messages.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ option csharp_namespace = "OpenMatch";

import "google/rpc/status.proto";
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

// A Ticket is a basic matchmaking entity in Open Match. A Ticket represents either an
// individual 'Player' or a 'Group' of players. Open Match will not interpret
Expand All @@ -42,6 +43,10 @@ message Ticket {
// Optional, depending on the requirements of the connected systems.
map<string, google.protobuf.Any> extensions = 5;

// Create time represents the time at which this Ticket was created. It is
// populated by Open Match at the time of Ticket creation.
google.protobuf.Timestamp create_time = 6;

// Deprecated fields.
reserved 2;
}
Expand Down Expand Up @@ -126,18 +131,26 @@ message TagPresentFilter {
string tag = 1;
}

// Pool specfies a set of criteria that are used to select a subset of Tickets
// that meet all the criteria.
message Pool {
// A developer-chosen human-readable name for this Pool.
string name = 1;

// Set of Filters indicating the filtering criteria. Selected players must
// Set of Filters indicating the filtering criteria. Selected tickets must
// match every Filter.
repeated DoubleRangeFilter double_range_filters = 2;

repeated StringEqualsFilter string_equals_filters = 4;

repeated TagPresentFilter tag_present_filters = 5;

// If specified, only Tickets created before the specified time are selected.
google.protobuf.Timestamp created_before = 6;

// If specified, only Tickets created after the specified time are selected.
google.protobuf.Timestamp created_after = 7;

// Deprecated fields.
reserved 3;
}
Expand Down
20 changes: 18 additions & 2 deletions api/query.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
"items": {
"$ref": "#/definitions/openmatchDoubleRangeFilter"
},
"description": "Set of Filters indicating the filtering criteria. Selected players must\nmatch every Filter."
"description": "Set of Filters indicating the filtering criteria. Selected tickets must\nmatch every Filter."
},
"string_equals_filters": {
"type": "array",
Expand All @@ -156,8 +156,19 @@
"items": {
"$ref": "#/definitions/openmatchTagPresentFilter"
}
},
"created_before": {
"type": "string",
"format": "date-time",
"description": "If specified, only Tickets created before the specified time are selected."
},
"created_after": {
"type": "string",
"format": "date-time",
"description": "If specified, only Tickets created after the specified time are selected."
}
}
},
"description": "Pool specfies a set of criteria that are used to select a subset of Tickets\nthat meet all the criteria."
},
"openmatchQueryTicketIdsRequest": {
"type": "object",
Expand Down Expand Up @@ -272,6 +283,11 @@
"$ref": "#/definitions/protobufAny"
},
"description": "Customized information not inspected by Open Match, to be used by the match\nmaking function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
},
"create_time": {
"type": "string",
"format": "date-time",
"description": "Create time represents the time at which this Ticket was created. It is\npopulated by Open Match at the time of Ticket creation."
}
},
"description": "A Ticket is a basic matchmaking entity in Open Match. A Ticket represents either an\nindividual 'Player' or a 'Group' of players. Open Match will not interpret\nwhat the Ticket represents but just treat it as a matchmaking unit with a set\nof SearchFields. Open Match stores the Ticket in state storage and enables an\nAssignment to be associated with this Ticket."
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
Expand Down
44 changes: 40 additions & 4 deletions internal/app/query/query_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ package query
import (
"context"
"sync"
"time"

"github.com/golang/protobuf/ptypes"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
Expand Down Expand Up @@ -49,10 +51,15 @@ func (s *queryService) QueryTickets(req *pb.QueryTicketsRequest, responseServer
return status.Error(codes.InvalidArgument, ".pool is required")
}

fc, err := filterCriteriaFromPool(pool)
if err != nil {
return err
}

var results []*pb.Ticket
err := s.tc.request(responseServer.Context(), func(tickets map[string]*pb.Ticket) {
err = s.tc.request(responseServer.Context(), func(tickets map[string]*pb.Ticket) {
for _, ticket := range tickets {
if filter.InPool(ticket, pool) {
if filter.MeetsCriteria(ticket, fc) {
results = append(results, ticket)
}
}
Expand Down Expand Up @@ -86,10 +93,15 @@ func (s *queryService) QueryTicketIds(req *pb.QueryTicketIdsRequest, responseSer
return status.Error(codes.InvalidArgument, ".pool is required")
}

fc, err := filterCriteriaFromPool(pool)
if err != nil {
return err
}

var results []string
err := s.tc.request(responseServer.Context(), func(tickets map[string]*pb.Ticket) {
err = s.tc.request(responseServer.Context(), func(tickets map[string]*pb.Ticket) {
for id, ticket := range tickets {
if filter.InPool(ticket, pool) {
if filter.MeetsCriteria(ticket, fc) {
results = append(results, id)
}
}
Expand Down Expand Up @@ -117,6 +129,30 @@ func (s *queryService) QueryTicketIds(req *pb.QueryTicketIdsRequest, responseSer
return nil
}

func filterCriteriaFromPool(pool *pb.Pool) (*filter.FilterCriteria, error) {
var ca, cb time.Time
var err error
if pool.GetCreatedAfter() != nil {
if ca, err = ptypes.Timestamp(pool.GetCreatedAfter()); err != nil {
return nil, status.Error(codes.InvalidArgument, ".invalid created_after value")
}
}

if pool.GetCreatedBefore() != nil {
if cb, err = ptypes.Timestamp(pool.GetCreatedBefore()); err != nil {
return nil, status.Error(codes.InvalidArgument, ".invalid created_before value")
}
}

return &filter.FilterCriteria{
DoubleRangeFilters: pool.GetDoubleRangeFilters(),
StringEqualsFilters: pool.GetStringEqualsFilters(),
TagPresentFilters: pool.GetTagPresentFilters(),
CreatedBefore: cb,
CreatedAfter: ca,
}, nil
}

func getPageSize(cfg config.View) int {
const (
name = "storage.page.size"
Expand Down
52 changes: 47 additions & 5 deletions internal/filter/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,60 @@
package filter

import (
"time"

"github.com/golang/protobuf/ptypes"
"github.com/sirupsen/logrus"
"open-match.dev/open-match/pkg/pb"
)

var emptySearchFields = &pb.SearchFields{}

// InPool returns whether the ticket meets all the criteria of the pool.
func InPool(ticket *pb.Ticket, pool *pb.Pool) bool {
var (
logger = logrus.WithFields(logrus.Fields{
"app": "openmatch",
"component": "filter",
})
)

// FilterCriteria specifies all the criteria that the Ticket needs to meet to
// be selected. This is used instead of the Pool directly to avoid any
// criteria validation logic in the filter package.
type FilterCriteria struct {
DoubleRangeFilters []*pb.DoubleRangeFilter
StringEqualsFilters []*pb.StringEqualsFilter
TagPresentFilters []*pb.TagPresentFilter
CreatedBefore time.Time
CreatedAfter time.Time
}

// MeetsCriteria returns whether the ticket meets all the criteria of the pool.
func MeetsCriteria(ticket *pb.Ticket, fc *FilterCriteria) bool {
s := ticket.GetSearchFields()
if s == nil {
s = emptySearchFields
}
for _, f := range pool.GetDoubleRangeFilters() {

// CreateTime is only populated by Open Match and hence expected to be valid.
if ct, err := ptypes.Timestamp(ticket.CreateTime); err == nil {
if !fc.CreatedAfter.IsZero() {
if !ct.After(fc.CreatedAfter) {
return false
}
}

if !fc.CreatedBefore.IsZero() {
if !ct.Before(fc.CreatedBefore) {
return false
}
}
} else {
logger.WithFields(logrus.Fields{
"error": err.Error(),
}).Warn("failed to get time from Timestamp proto")
}

for _, f := range fc.DoubleRangeFilters {
v, ok := s.DoubleArgs[f.DoubleArg]
if !ok {
return false
Expand All @@ -40,7 +82,7 @@ func InPool(ticket *pb.Ticket, pool *pb.Pool) bool {
}
}

for _, f := range pool.GetStringEqualsFilters() {
for _, f := range fc.StringEqualsFilters {
v, ok := s.StringArgs[f.StringArg]
if !ok {
return false
Expand All @@ -51,7 +93,7 @@ func InPool(ticket *pb.Ticket, pool *pb.Pool) bool {
}

outer:
for _, f := range pool.GetTagPresentFilters() {
for _, f := range fc.TagPresentFilters {
for _, v := range s.Tags {
if v == f.Tag {
continue outer
Expand Down
Loading

0 comments on commit ce7061e

Please sign in to comment.