mirror of
https://github.com/googleforgames/open-match.git
synced 2025-03-25 13:24:18 +00:00
Use proto3's struct for properties, not string. (#430)
This makes the API more usuable for both json clients (who no longer have to encode json into a string and put that into their json) and also for proto clients (who no longer have to use json...). When converted to json, struct will be encoded directly into an object, which is much more convenient. The majority of the rest of this change is fixing tickets in tests. This removes the dependancy on the json parser that was used for reading from properties. I also added a test on indexing and filtering tickets from the state store, because I can't help myself and I have a problem.
This commit is contained in:
@ -244,7 +244,7 @@
|
||||
"title": "Set of Rosters that comprise this Match"
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Match properties for this Match. Open Match does not interpret this field."
|
||||
}
|
||||
},
|
||||
@ -258,7 +258,7 @@
|
||||
"description": "Name of this match profile."
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Set of properties associated with this MatchProfile. (Optional)\nOpen Match does not interpret these properties but passes them through to\nthe MatchFunction."
|
||||
},
|
||||
"pool": {
|
||||
@ -319,8 +319,8 @@
|
||||
"description": "The Ticket ID generated by Open Match."
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"description": "JSON string for properties associated with this Ticket. A subset of these\nproperties will be indexed based on the indexing configuration."
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Properties contains custom info about the ticket. Top level values can be\nused in indexing and filtering to find tickets."
|
||||
},
|
||||
"assignment": {
|
||||
"$ref": "#/definitions/apiAssignment",
|
||||
@ -344,6 +344,72 @@
|
||||
},
|
||||
"description": "`Any` contains an arbitrary serialized protocol buffer message along with a\nURL that describes the type of the serialized message.\n\nProtobuf library provides support to pack/unpack Any values in the form\nof utility functions or additional generated methods of the Any type.\n\nExample 1: Pack and unpack a message in C++.\n\n Foo foo = ...;\n Any any;\n any.PackFrom(foo);\n ...\n if (any.UnpackTo(\u0026foo)) {\n ...\n }\n\nExample 2: Pack and unpack a message in Java.\n\n Foo foo = ...;\n Any any = Any.pack(foo);\n ...\n if (any.is(Foo.class)) {\n foo = any.unpack(Foo.class);\n }\n\n Example 3: Pack and unpack a message in Python.\n\n foo = Foo(...)\n any = Any()\n any.Pack(foo)\n ...\n if any.Is(Foo.DESCRIPTOR):\n any.Unpack(foo)\n ...\n\n Example 4: Pack and unpack a message in Go\n\n foo := \u0026pb.Foo{...}\n any, err := ptypes.MarshalAny(foo)\n ...\n foo := \u0026pb.Foo{}\n if err := ptypes.UnmarshalAny(any, foo); err != nil {\n ...\n }\n\nThe pack methods provided by protobuf library will by default use\n'type.googleapis.com/full.type.name' as the type URL and the unpack\nmethods only use the fully qualified type name after the last '/'\nin the type URL, for example \"foo.bar.com/x/y.z\" will yield type\nname \"y.z\".\n\n\nJSON\n====\nThe JSON representation of an `Any` value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field `@type` which contains the type URL. Example:\n\n package google.profile;\n message Person {\n string first_name = 1;\n string last_name = 2;\n }\n\n {\n \"@type\": \"type.googleapis.com/google.profile.Person\",\n \"firstName\": \u003cstring\u003e,\n \"lastName\": \u003cstring\u003e\n }\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\n`value` which holds the custom JSON in addition to the `@type`\nfield. Example (for message [google.protobuf.Duration][]):\n\n {\n \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n \"value\": \"1.212s\"\n }"
|
||||
},
|
||||
"protobufListValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Repeated field of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
|
||||
},
|
||||
"protobufNullValue": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"NULL_VALUE"
|
||||
],
|
||||
"default": "NULL_VALUE",
|
||||
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
||||
},
|
||||
"protobufStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Unordered map of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
|
||||
},
|
||||
"protobufValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"null_value": {
|
||||
"$ref": "#/definitions/protobufNullValue",
|
||||
"description": "Represents a null value."
|
||||
},
|
||||
"number_value": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Represents a double value."
|
||||
},
|
||||
"string_value": {
|
||||
"type": "string",
|
||||
"description": "Represents a string value."
|
||||
},
|
||||
"bool_value": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "Represents a boolean value."
|
||||
},
|
||||
"struct_value": {
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Represents a structured value."
|
||||
},
|
||||
"list_value": {
|
||||
"$ref": "#/definitions/protobufListValue",
|
||||
"description": "Represents a repeated `Value`."
|
||||
}
|
||||
},
|
||||
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -209,8 +209,8 @@
|
||||
"description": "The Ticket ID generated by Open Match."
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"description": "JSON string for properties associated with this Ticket. A subset of these\nproperties will be indexed based on the indexing configuration."
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Properties contains custom info about the ticket. Top level values can be\nused in indexing and filtering to find tickets."
|
||||
},
|
||||
"assignment": {
|
||||
"$ref": "#/definitions/apiAssignment",
|
||||
@ -234,6 +234,72 @@
|
||||
},
|
||||
"description": "`Any` contains an arbitrary serialized protocol buffer message along with a\nURL that describes the type of the serialized message.\n\nProtobuf library provides support to pack/unpack Any values in the form\nof utility functions or additional generated methods of the Any type.\n\nExample 1: Pack and unpack a message in C++.\n\n Foo foo = ...;\n Any any;\n any.PackFrom(foo);\n ...\n if (any.UnpackTo(\u0026foo)) {\n ...\n }\n\nExample 2: Pack and unpack a message in Java.\n\n Foo foo = ...;\n Any any = Any.pack(foo);\n ...\n if (any.is(Foo.class)) {\n foo = any.unpack(Foo.class);\n }\n\n Example 3: Pack and unpack a message in Python.\n\n foo = Foo(...)\n any = Any()\n any.Pack(foo)\n ...\n if any.Is(Foo.DESCRIPTOR):\n any.Unpack(foo)\n ...\n\n Example 4: Pack and unpack a message in Go\n\n foo := \u0026pb.Foo{...}\n any, err := ptypes.MarshalAny(foo)\n ...\n foo := \u0026pb.Foo{}\n if err := ptypes.UnmarshalAny(any, foo); err != nil {\n ...\n }\n\nThe pack methods provided by protobuf library will by default use\n'type.googleapis.com/full.type.name' as the type URL and the unpack\nmethods only use the fully qualified type name after the last '/'\nin the type URL, for example \"foo.bar.com/x/y.z\" will yield type\nname \"y.z\".\n\n\nJSON\n====\nThe JSON representation of an `Any` value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field `@type` which contains the type URL. Example:\n\n package google.profile;\n message Person {\n string first_name = 1;\n string last_name = 2;\n }\n\n {\n \"@type\": \"type.googleapis.com/google.profile.Person\",\n \"firstName\": \u003cstring\u003e,\n \"lastName\": \u003cstring\u003e\n }\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\n`value` which holds the custom JSON in addition to the `@type`\nfield. Example (for message [google.protobuf.Duration][]):\n\n {\n \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n \"value\": \"1.212s\"\n }"
|
||||
},
|
||||
"protobufListValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Repeated field of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
|
||||
},
|
||||
"protobufNullValue": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"NULL_VALUE"
|
||||
],
|
||||
"default": "NULL_VALUE",
|
||||
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
||||
},
|
||||
"protobufStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Unordered map of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
|
||||
},
|
||||
"protobufValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"null_value": {
|
||||
"$ref": "#/definitions/protobufNullValue",
|
||||
"description": "Represents a null value."
|
||||
},
|
||||
"number_value": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Represents a double value."
|
||||
},
|
||||
"string_value": {
|
||||
"type": "string",
|
||||
"description": "Represents a string value."
|
||||
},
|
||||
"bool_value": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "Represents a boolean value."
|
||||
},
|
||||
"struct_value": {
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Represents a structured value."
|
||||
},
|
||||
"list_value": {
|
||||
"$ref": "#/definitions/protobufListValue",
|
||||
"description": "Represents a repeated `Value`."
|
||||
}
|
||||
},
|
||||
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -127,7 +127,7 @@
|
||||
"title": "Set of Rosters that comprise this Match"
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Match properties for this Match. Open Match does not interpret this field."
|
||||
}
|
||||
},
|
||||
@ -141,7 +141,7 @@
|
||||
"description": "Name of this match profile."
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Set of properties associated with this MatchProfile. (Optional)\nOpen Match does not interpret these properties but passes them through to\nthe MatchFunction."
|
||||
},
|
||||
"pool": {
|
||||
@ -223,8 +223,8 @@
|
||||
"description": "The Ticket ID generated by Open Match."
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"description": "JSON string for properties associated with this Ticket. A subset of these\nproperties will be indexed based on the indexing configuration."
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Properties contains custom info about the ticket. Top level values can be\nused in indexing and filtering to find tickets."
|
||||
},
|
||||
"assignment": {
|
||||
"$ref": "#/definitions/apiAssignment",
|
||||
@ -232,6 +232,72 @@
|
||||
}
|
||||
},
|
||||
"description": "A Ticket is a basic matchmaking entity in Open Match. In order to enter\nmatchmaking using Open Match, the client should generate a Ticket, passing in\nthe properties to be associated with this Ticket. Open Match will generate an\nID for a Ticket during creation. A Ticket could be used to represent 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 properties. Open Match stores the Ticket in state storage and enables an\nAssignment to be associated with this Ticket."
|
||||
},
|
||||
"protobufListValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Repeated field of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
|
||||
},
|
||||
"protobufNullValue": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"NULL_VALUE"
|
||||
],
|
||||
"default": "NULL_VALUE",
|
||||
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
||||
},
|
||||
"protobufStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Unordered map of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
|
||||
},
|
||||
"protobufValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"null_value": {
|
||||
"$ref": "#/definitions/protobufNullValue",
|
||||
"description": "Represents a null value."
|
||||
},
|
||||
"number_value": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Represents a double value."
|
||||
},
|
||||
"string_value": {
|
||||
"type": "string",
|
||||
"description": "Represents a string value."
|
||||
},
|
||||
"bool_value": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "Represents a boolean value."
|
||||
},
|
||||
"struct_value": {
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Represents a structured value."
|
||||
},
|
||||
"list_value": {
|
||||
"$ref": "#/definitions/protobufListValue",
|
||||
"description": "Represents a repeated `Value`."
|
||||
}
|
||||
},
|
||||
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
|
@ -16,6 +16,8 @@ syntax = "proto3";
|
||||
package api;
|
||||
option go_package = "internal/pb";
|
||||
|
||||
import "google/protobuf/struct.proto";
|
||||
|
||||
// A Ticket is a basic matchmaking entity in Open Match. In order to enter
|
||||
// matchmaking using Open Match, the client should generate a Ticket, passing in
|
||||
// the properties to be associated with this Ticket. Open Match will generate an
|
||||
@ -28,9 +30,9 @@ message Ticket {
|
||||
// The Ticket ID generated by Open Match.
|
||||
string id = 1;
|
||||
|
||||
// JSON string for properties associated with this Ticket. A subset of these
|
||||
// properties will be indexed based on the indexing configuration.
|
||||
string properties = 2;
|
||||
// Properties contains custom info about the ticket. Top level values can be
|
||||
// used in indexing and filtering to find tickets.
|
||||
google.protobuf.Struct properties = 2;
|
||||
|
||||
// Assignment associated with the Ticket.
|
||||
Assignment assignment = 3;
|
||||
@ -95,7 +97,7 @@ message MatchProfile {
|
||||
// Set of properties associated with this MatchProfile. (Optional)
|
||||
// Open Match does not interpret these properties but passes them through to
|
||||
// the MatchFunction.
|
||||
string properties = 2;
|
||||
google.protobuf.Struct properties = 2;
|
||||
|
||||
// Set of pools to be queried when generating a match for this MatchProfile.
|
||||
// The pool names can be used in empty Rosters to specify composition of a
|
||||
@ -129,5 +131,5 @@ message Match {
|
||||
repeated Roster roster = 5;
|
||||
|
||||
// Match properties for this Match. Open Match does not interpret this field.
|
||||
string properties = 6;
|
||||
google.protobuf.Struct properties = 6;
|
||||
}
|
||||
|
@ -142,8 +142,8 @@
|
||||
"description": "The Ticket ID generated by Open Match."
|
||||
},
|
||||
"properties": {
|
||||
"type": "string",
|
||||
"description": "JSON string for properties associated with this Ticket. A subset of these\nproperties will be indexed based on the indexing configuration."
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Properties contains custom info about the ticket. Top level values can be\nused in indexing and filtering to find tickets."
|
||||
},
|
||||
"assignment": {
|
||||
"$ref": "#/definitions/apiAssignment",
|
||||
@ -167,6 +167,72 @@
|
||||
},
|
||||
"description": "`Any` contains an arbitrary serialized protocol buffer message along with a\nURL that describes the type of the serialized message.\n\nProtobuf library provides support to pack/unpack Any values in the form\nof utility functions or additional generated methods of the Any type.\n\nExample 1: Pack and unpack a message in C++.\n\n Foo foo = ...;\n Any any;\n any.PackFrom(foo);\n ...\n if (any.UnpackTo(\u0026foo)) {\n ...\n }\n\nExample 2: Pack and unpack a message in Java.\n\n Foo foo = ...;\n Any any = Any.pack(foo);\n ...\n if (any.is(Foo.class)) {\n foo = any.unpack(Foo.class);\n }\n\n Example 3: Pack and unpack a message in Python.\n\n foo = Foo(...)\n any = Any()\n any.Pack(foo)\n ...\n if any.Is(Foo.DESCRIPTOR):\n any.Unpack(foo)\n ...\n\n Example 4: Pack and unpack a message in Go\n\n foo := \u0026pb.Foo{...}\n any, err := ptypes.MarshalAny(foo)\n ...\n foo := \u0026pb.Foo{}\n if err := ptypes.UnmarshalAny(any, foo); err != nil {\n ...\n }\n\nThe pack methods provided by protobuf library will by default use\n'type.googleapis.com/full.type.name' as the type URL and the unpack\nmethods only use the fully qualified type name after the last '/'\nin the type URL, for example \"foo.bar.com/x/y.z\" will yield type\nname \"y.z\".\n\n\nJSON\n====\nThe JSON representation of an `Any` value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field `@type` which contains the type URL. Example:\n\n package google.profile;\n message Person {\n string first_name = 1;\n string last_name = 2;\n }\n\n {\n \"@type\": \"type.googleapis.com/google.profile.Person\",\n \"firstName\": \u003cstring\u003e,\n \"lastName\": \u003cstring\u003e\n }\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\n`value` which holds the custom JSON in addition to the `@type`\nfield. Example (for message [google.protobuf.Duration][]):\n\n {\n \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n \"value\": \"1.212s\"\n }"
|
||||
},
|
||||
"protobufListValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Repeated field of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
|
||||
},
|
||||
"protobufNullValue": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"NULL_VALUE"
|
||||
],
|
||||
"default": "NULL_VALUE",
|
||||
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
||||
},
|
||||
"protobufStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufValue"
|
||||
},
|
||||
"description": "Unordered map of dynamically typed values."
|
||||
}
|
||||
},
|
||||
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
|
||||
},
|
||||
"protobufValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"null_value": {
|
||||
"$ref": "#/definitions/protobufNullValue",
|
||||
"description": "Represents a null value."
|
||||
},
|
||||
"number_value": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Represents a double value."
|
||||
},
|
||||
"string_value": {
|
||||
"type": "string",
|
||||
"description": "Represents a string value."
|
||||
},
|
||||
"bool_value": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "Represents a boolean value."
|
||||
},
|
||||
"struct_value": {
|
||||
"$ref": "#/definitions/protobufStruct",
|
||||
"description": "Represents a structured value."
|
||||
},
|
||||
"list_value": {
|
||||
"$ref": "#/definitions/protobufListValue",
|
||||
"description": "Represents a repeated `Value`."
|
||||
}
|
||||
},
|
||||
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
3
go.mod
3
go.mod
@ -41,9 +41,6 @@ require (
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
github.com/spf13/viper v1.3.2
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tidwall/gjson v1.2.1
|
||||
github.com/tidwall/match v1.0.1 // indirect
|
||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51 // indirect
|
||||
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583 // indirect
|
||||
go.opencensus.io v0.21.0
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
|
||||
|
6
go.sum
6
go.sum
@ -169,12 +169,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/tidwall/gjson v1.2.1 h1:j0efZLrZUvNerEf6xqoi0NjWMK5YlLrR7Guo/dxY174=
|
||||
github.com/tidwall/gjson v1.2.1/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
|
||||
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
||||
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51 h1:BP2bjP495BBPaBcS5rmqviTfrOkN5rO5ceKAMRZCRFc=
|
||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583 h1:SZPG5w7Qxq7bMcMVl6e3Ht2X7f+AAGQdzjkbyOnNNZ8=
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/alicebob/miniredis"
|
||||
structpb "github.com/golang/protobuf/ptypes/struct"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc"
|
||||
@ -44,7 +45,7 @@ func TestServerBinding(t *testing.T) {
|
||||
// validateTicket validates that the fetched ticket is identical to the expected ticket.
|
||||
func validateTicket(t *testing.T, got *pb.Ticket, want *pb.Ticket) {
|
||||
assert.Equal(t, got.Id, want.Id)
|
||||
assert.Equal(t, got.Properties, want.Properties)
|
||||
assert.Equal(t, got.Properties.Fields["test-property"].GetNumberValue(), want.Properties.Fields["test-property"].GetNumberValue())
|
||||
assert.Equal(t, got.Assignment.Connection, want.Assignment.Connection)
|
||||
assert.Equal(t, got.Assignment.Properties, want.Assignment.Properties)
|
||||
assert.Equal(t, got.Assignment.Error, want.Assignment.Error)
|
||||
@ -82,7 +83,11 @@ func TestFrontendService(t *testing.T) {
|
||||
assert.NotNil(fe)
|
||||
|
||||
ticket := &pb.Ticket{
|
||||
Properties: "test-property",
|
||||
Properties: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"test-property": {Kind: &structpb.Value_NumberValue{NumberValue: 1}},
|
||||
},
|
||||
},
|
||||
Assignment: &pb.Assignment{
|
||||
Connection: "test-tbd",
|
||||
},
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
structpb "github.com/golang/protobuf/ptypes/struct"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@ -70,7 +71,7 @@ type matchFunctionService struct {
|
||||
type MatchFunctionParams struct {
|
||||
Logger *logrus.Entry
|
||||
ProfileName string
|
||||
Properties string
|
||||
Properties *structpb.Struct
|
||||
Rosters []*pb.Roster
|
||||
PoolNameToTickets map[string][]*pb.Ticket
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package pb
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_struct "github.com/golang/protobuf/ptypes/struct"
|
||||
math "math"
|
||||
)
|
||||
|
||||
@ -31,9 +32,9 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
type Ticket struct {
|
||||
// The Ticket ID generated by Open Match.
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
// JSON string for properties associated with this Ticket. A subset of these
|
||||
// properties will be indexed based on the indexing configuration.
|
||||
Properties string `protobuf:"bytes,2,opt,name=properties,proto3" json:"properties,omitempty"`
|
||||
// Properties contains custom info about the ticket. Top level values can be
|
||||
// used in indexing and filtering to find tickets.
|
||||
Properties *_struct.Struct `protobuf:"bytes,2,opt,name=properties,proto3" json:"properties,omitempty"`
|
||||
// Assignment associated with the Ticket.
|
||||
Assignment *Assignment `protobuf:"bytes,3,opt,name=assignment,proto3" json:"assignment,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
@ -73,11 +74,11 @@ func (m *Ticket) GetId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Ticket) GetProperties() string {
|
||||
func (m *Ticket) GetProperties() *_struct.Struct {
|
||||
if m != nil {
|
||||
return m.Properties
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Ticket) GetAssignment() *Assignment {
|
||||
@ -321,7 +322,7 @@ type MatchProfile struct {
|
||||
// Set of properties associated with this MatchProfile. (Optional)
|
||||
// Open Match does not interpret these properties but passes them through to
|
||||
// the MatchFunction.
|
||||
Properties string `protobuf:"bytes,2,opt,name=properties,proto3" json:"properties,omitempty"`
|
||||
Properties *_struct.Struct `protobuf:"bytes,2,opt,name=properties,proto3" json:"properties,omitempty"`
|
||||
// Set of pools to be queried when generating a match for this MatchProfile.
|
||||
// The pool names can be used in empty Rosters to specify composition of a
|
||||
// match.
|
||||
@ -368,11 +369,11 @@ func (m *MatchProfile) GetName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MatchProfile) GetProperties() string {
|
||||
func (m *MatchProfile) GetProperties() *_struct.Struct {
|
||||
if m != nil {
|
||||
return m.Properties
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MatchProfile) GetPool() []*Pool {
|
||||
@ -404,10 +405,10 @@ type Match struct {
|
||||
// Set of Rosters that comprise this Match
|
||||
Roster []*Roster `protobuf:"bytes,5,rep,name=roster,proto3" json:"roster,omitempty"`
|
||||
// Match properties for this Match. Open Match does not interpret this field.
|
||||
Properties string `protobuf:"bytes,6,opt,name=properties,proto3" json:"properties,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
Properties *_struct.Struct `protobuf:"bytes,6,opt,name=properties,proto3" json:"properties,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Match) Reset() { *m = Match{} }
|
||||
@ -470,11 +471,11 @@ func (m *Match) GetRoster() []*Roster {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Match) GetProperties() string {
|
||||
func (m *Match) GetProperties() *_struct.Struct {
|
||||
if m != nil {
|
||||
return m.Properties
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -490,31 +491,33 @@ func init() {
|
||||
func init() { proto.RegisterFile("api/messages.proto", fileDescriptor_cb9fb1f207fd5b8c) }
|
||||
|
||||
var fileDescriptor_cb9fb1f207fd5b8c = []byte{
|
||||
// 408 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xcf, 0x8a, 0xdb, 0x30,
|
||||
0x10, 0xc6, 0xf1, 0x9f, 0xb8, 0xeb, 0xf1, 0xee, 0xb6, 0x88, 0x1e, 0x5c, 0xfa, 0x87, 0xe0, 0xa5,
|
||||
0x90, 0x53, 0x02, 0xdb, 0x53, 0x4f, 0xa5, 0x3d, 0x2c, 0x6c, 0xa1, 0x10, 0x44, 0x4f, 0xbd, 0x04,
|
||||
0xd9, 0x56, 0xd2, 0xa1, 0xb6, 0x24, 0x64, 0x05, 0xfa, 0x04, 0x7d, 0xc6, 0x3e, 0x4e, 0xd1, 0xc8,
|
||||
0x4d, 0xdc, 0x90, 0x92, 0x9b, 0xf4, 0x8d, 0xfc, 0xcd, 0x6f, 0x3e, 0xc9, 0xc0, 0x84, 0xc1, 0x55,
|
||||
0x2f, 0x87, 0x41, 0xec, 0xe4, 0xb0, 0x34, 0x56, 0x3b, 0xcd, 0x12, 0x61, 0xb0, 0x42, 0xc8, 0xbe,
|
||||
0x62, 0xf3, 0x43, 0x3a, 0x76, 0x0b, 0x31, 0xb6, 0x65, 0x34, 0x8f, 0x16, 0x39, 0x8f, 0xb1, 0x65,
|
||||
0x6f, 0x00, 0x8c, 0xd5, 0x46, 0x5a, 0x87, 0x72, 0x28, 0x63, 0xd2, 0x27, 0x0a, 0x5b, 0x01, 0x88,
|
||||
0x61, 0xc0, 0x9d, 0xea, 0xa5, 0x72, 0x65, 0x32, 0x8f, 0x16, 0xc5, 0xfd, 0xd3, 0xa5, 0x30, 0xb8,
|
||||
0xfc, 0x78, 0x90, 0xf9, 0xe4, 0x48, 0x55, 0x03, 0x1c, 0x2b, 0xde, 0xbe, 0xd1, 0x4a, 0xc9, 0xc6,
|
||||
0xa1, 0x56, 0x63, 0xdb, 0x89, 0x72, 0xb1, 0xfd, 0x73, 0x98, 0x49, 0x6b, 0xb5, 0xa5, 0xce, 0x39,
|
||||
0x0f, 0x9b, 0xea, 0x33, 0x64, 0x0f, 0xd8, 0x39, 0x69, 0xd9, 0x2b, 0xc8, 0x85, 0x73, 0x16, 0xeb,
|
||||
0xbd, 0x93, 0xa3, 0xfd, 0x51, 0x60, 0xcf, 0x20, 0xe9, 0xc5, 0x4f, 0xb2, 0x8d, 0xb8, 0x5f, 0x92,
|
||||
0x82, 0x8a, 0xdc, 0xbc, 0x82, 0xaa, 0xfa, 0x00, 0xe9, 0x5a, 0xeb, 0x8e, 0x31, 0x48, 0x95, 0xe8,
|
||||
0xff, 0x9a, 0xd0, 0x9a, 0xdd, 0x41, 0xb6, 0xa5, 0x3e, 0x65, 0x3c, 0x4f, 0x16, 0xc5, 0x7d, 0x41,
|
||||
0x83, 0x87, 0xd6, 0x7c, 0x2c, 0x55, 0xef, 0x21, 0xe3, 0x7a, 0xf0, 0x30, 0xe7, 0x2c, 0x5e, 0x42,
|
||||
0xee, 0x28, 0xf9, 0x0d, 0xb6, 0xe4, 0x92, 0xf3, 0xab, 0x20, 0x3c, 0xb6, 0xd5, 0xaf, 0x08, 0xae,
|
||||
0xbf, 0x08, 0xd7, 0x7c, 0x5f, 0x5b, 0xbd, 0xc5, 0x4e, 0x9e, 0x75, 0xb8, 0x14, 0xd1, 0x6b, 0x48,
|
||||
0x8d, 0xd6, 0x5d, 0x99, 0x10, 0x62, 0x4e, 0x88, 0x7e, 0x22, 0x4e, 0xb2, 0x9f, 0xc1, 0x12, 0x5e,
|
||||
0x99, 0x4e, 0x66, 0x08, 0xc4, 0x7c, 0x2c, 0x55, 0xbf, 0x23, 0x98, 0x11, 0x08, 0x7b, 0x01, 0x57,
|
||||
0xbd, 0x5f, 0x6c, 0x0e, 0xaf, 0xe4, 0x09, 0xed, 0x1f, 0x5b, 0x76, 0x07, 0x37, 0xa1, 0x64, 0x02,
|
||||
0xed, 0xc8, 0x72, 0xdd, 0x4f, 0x27, 0x78, 0x0b, 0xb7, 0xe1, 0xd0, 0x76, 0xaf, 0xc2, 0xa5, 0x87,
|
||||
0x9b, 0x0b, 0x9f, 0x3e, 0x8c, 0xa2, 0xa7, 0x0a, 0x29, 0xfc, 0x43, 0x15, 0xde, 0x28, 0x1f, 0x4b,
|
||||
0x13, 0xf4, 0xd9, 0x7f, 0xd1, 0x4f, 0xe2, 0xc9, 0x4e, 0xe3, 0xf9, 0x74, 0xf3, 0xad, 0x40, 0xe5,
|
||||
0xa4, 0x55, 0xa2, 0x5b, 0x99, 0xba, 0xce, 0xe8, 0xaf, 0x78, 0xf7, 0x27, 0x00, 0x00, 0xff, 0xff,
|
||||
0x0c, 0xf7, 0x2b, 0xea, 0x2b, 0x03, 0x00, 0x00,
|
||||
// 447 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0x41, 0x6b, 0x14, 0x31,
|
||||
0x14, 0x66, 0x76, 0x76, 0xc7, 0xce, 0xdb, 0xb6, 0x4a, 0x10, 0x1c, 0xb5, 0xca, 0x32, 0x45, 0xd8,
|
||||
0xd3, 0x0c, 0xd4, 0x83, 0x78, 0x12, 0x3d, 0x14, 0x2a, 0x08, 0x25, 0x7a, 0xf2, 0x52, 0x32, 0x33,
|
||||
0xd9, 0xf5, 0xe1, 0x4c, 0x12, 0x92, 0x2c, 0x78, 0xf6, 0x8f, 0xf8, 0x1b, 0xfd, 0x07, 0x92, 0x97,
|
||||
0x69, 0x3b, 0x2d, 0x2b, 0x88, 0xb7, 0xe4, 0xfb, 0x5e, 0xbe, 0xf7, 0x7d, 0x79, 0x0f, 0x98, 0x30,
|
||||
0x58, 0x0f, 0xd2, 0x39, 0xb1, 0x95, 0xae, 0x32, 0x56, 0x7b, 0xcd, 0x52, 0x61, 0xf0, 0xd9, 0xc9,
|
||||
0x56, 0xeb, 0x6d, 0x2f, 0x6b, 0x82, 0x9a, 0xdd, 0xa6, 0x76, 0xde, 0xee, 0x5a, 0x1f, 0x4b, 0xca,
|
||||
0x9f, 0x09, 0x64, 0x5f, 0xb0, 0xfd, 0x2e, 0x3d, 0x3b, 0x86, 0x19, 0x76, 0x45, 0xb2, 0x4a, 0xd6,
|
||||
0x39, 0x9f, 0x61, 0xc7, 0xde, 0x00, 0x18, 0xab, 0x8d, 0xb4, 0x1e, 0xa5, 0x2b, 0x66, 0xab, 0x64,
|
||||
0xbd, 0x3c, 0x7b, 0x52, 0x45, 0xb5, 0xea, 0x5a, 0xad, 0xfa, 0x4c, 0x6a, 0x7c, 0x52, 0xca, 0x6a,
|
||||
0x00, 0xe1, 0x1c, 0x6e, 0xd5, 0x20, 0x95, 0x2f, 0x52, 0x7a, 0xf8, 0xb0, 0x12, 0x06, 0xab, 0xf7,
|
||||
0x37, 0x30, 0x9f, 0x94, 0x94, 0x0d, 0xc0, 0x2d, 0xc3, 0x5e, 0x02, 0xb4, 0x5a, 0x29, 0xd9, 0x7a,
|
||||
0xd4, 0x6a, 0xf4, 0x33, 0x41, 0x02, 0x7f, 0xcf, 0x57, 0x7e, 0xa7, 0xfd, 0x63, 0x58, 0x48, 0x6b,
|
||||
0xb5, 0xa5, 0xce, 0x39, 0x8f, 0x97, 0xf2, 0x23, 0x64, 0xe7, 0xd8, 0x7b, 0x69, 0xd9, 0x09, 0xe4,
|
||||
0xc2, 0x7b, 0x8b, 0xcd, 0xce, 0xcb, 0x51, 0xfe, 0x16, 0x60, 0x8f, 0x20, 0x1d, 0xc4, 0x0f, 0x92,
|
||||
0x4d, 0x78, 0x38, 0x12, 0x82, 0x8a, 0xd4, 0x02, 0x82, 0xaa, 0x7c, 0x07, 0xf3, 0x4b, 0xad, 0x7b,
|
||||
0xc6, 0x60, 0xae, 0xc4, 0x70, 0x2d, 0x42, 0x67, 0x76, 0x0a, 0xd9, 0x86, 0xfa, 0x14, 0xb3, 0x55,
|
||||
0xba, 0x5e, 0x9e, 0x2d, 0x29, 0x78, 0x6c, 0xcd, 0x47, 0xaa, 0x7c, 0x0b, 0x19, 0xd7, 0x2e, 0x98,
|
||||
0xd9, 0x27, 0xf1, 0x1c, 0x72, 0x4f, 0x23, 0xb9, 0xc2, 0x8e, 0x54, 0x72, 0x7e, 0x10, 0x81, 0x8b,
|
||||
0xae, 0xfc, 0x95, 0xc0, 0xe1, 0x27, 0xe1, 0xdb, 0x6f, 0x97, 0x56, 0x6f, 0xb0, 0x97, 0x7b, 0x15,
|
||||
0xfe, 0x7b, 0x74, 0x2f, 0x60, 0x6e, 0xb4, 0xee, 0x8b, 0x94, 0xbc, 0xe7, 0xe4, 0x3d, 0x44, 0xe5,
|
||||
0x04, 0x87, 0x70, 0x96, 0x7c, 0x17, 0xf3, 0x49, 0xb8, 0x18, 0x85, 0x8f, 0x54, 0xf9, 0x3b, 0x81,
|
||||
0x05, 0x39, 0x64, 0x4f, 0xe1, 0x60, 0x08, 0x87, 0xab, 0x9b, 0xbd, 0x7a, 0x40, 0xf7, 0x8b, 0x8e,
|
||||
0x9d, 0xc2, 0x51, 0xa4, 0x4c, 0x8c, 0x31, 0xce, 0xf1, 0x70, 0x98, 0x46, 0x7b, 0x05, 0xc7, 0xb1,
|
||||
0x68, 0xb3, 0x53, 0x71, 0x1b, 0xe2, 0x48, 0xe3, 0xd3, 0xf3, 0x11, 0x0c, 0xae, 0xe2, 0xf7, 0xdc,
|
||||
0x71, 0x15, 0xb7, 0x9a, 0x8f, 0xd4, 0xc4, 0xfa, 0xe2, 0xaf, 0xd6, 0xef, 0xfd, 0x5b, 0xf6, 0xcf,
|
||||
0xff, 0xf6, 0xe1, 0xe8, 0xeb, 0x12, 0x95, 0x97, 0x56, 0x89, 0xbe, 0x36, 0x4d, 0x93, 0x51, 0xed,
|
||||
0xeb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x54, 0x5e, 0x21, 0x56, 0x95, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
@ -16,10 +16,12 @@ package statestore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alicebob/miniredis"
|
||||
structpb "github.com/golang/protobuf/ptypes/struct"
|
||||
"github.com/rs/xid"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -50,8 +52,12 @@ func TestTicketLifecycle(t *testing.T) {
|
||||
// Initialize test data
|
||||
id := xid.New().String()
|
||||
ticket := &pb.Ticket{
|
||||
Id: id,
|
||||
Properties: "test-property",
|
||||
Id: id,
|
||||
Properties: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"testindex1": {Kind: &structpb.Value_NumberValue{NumberValue: 42}},
|
||||
},
|
||||
},
|
||||
Assignment: &pb.Assignment{
|
||||
Connection: "test-tbd",
|
||||
},
|
||||
@ -79,7 +85,7 @@ func TestTicketLifecycle(t *testing.T) {
|
||||
assert.Nil(err)
|
||||
assert.NotNil(result)
|
||||
assert.Equal(ticket.Id, result.Id)
|
||||
assert.Equal(ticket.Properties, result.Properties)
|
||||
assert.Equal(ticket.Properties.Fields["testindex1"].GetNumberValue(), result.Properties.Fields["testindex1"].GetNumberValue())
|
||||
assert.Equal(ticket.Assignment.Connection, result.Assignment.Connection)
|
||||
|
||||
// Validate Ticket deletion
|
||||
@ -91,8 +97,74 @@ func TestTicketLifecycle(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTicketIndexing(t *testing.T) {
|
||||
// TODO: The change to filter tickets is currently in progress.
|
||||
// Testing Ticket indexing will be added along with this implementation.
|
||||
// Create State Store
|
||||
assert := assert.New(t)
|
||||
cfg := createBackend(t)
|
||||
service, err := New(cfg)
|
||||
assert.Nil(err)
|
||||
assert.NotNil(service)
|
||||
defer service.Close()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
id := fmt.Sprintf("ticket.no.%d", i)
|
||||
|
||||
ticket := &pb.Ticket{
|
||||
Id: id,
|
||||
Properties: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"testindex1": {Kind: &structpb.Value_NumberValue{NumberValue: float64(i)}},
|
||||
"testindex2": {Kind: &structpb.Value_NumberValue{NumberValue: 0.5}},
|
||||
},
|
||||
},
|
||||
Assignment: &pb.Assignment{
|
||||
Connection: "test-tbd",
|
||||
},
|
||||
}
|
||||
|
||||
err = service.CreateTicket(context.Background(), ticket)
|
||||
assert.Nil(err)
|
||||
|
||||
err = service.IndexTicket(context.Background(), ticket)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
// Remove one ticket, to test that it doesn't fall over.
|
||||
err = service.DeleteTicket(context.Background(), "ticket.no.5")
|
||||
assert.Nil(err)
|
||||
|
||||
// Remove ticket from index, should not show up.
|
||||
err = service.DeindexTicket(context.Background(), "ticket.no.6")
|
||||
assert.Nil(err)
|
||||
|
||||
found := make(map[string]struct{})
|
||||
|
||||
filters := []*pb.Filter{
|
||||
{
|
||||
Attribute: "testindex1",
|
||||
Min: 2.5,
|
||||
Max: 8.5,
|
||||
},
|
||||
{
|
||||
Attribute: "testindex2",
|
||||
Min: 0.49,
|
||||
Max: 0.51,
|
||||
},
|
||||
}
|
||||
|
||||
err = service.FilterTickets(context.Background(), filters, 2, func(tickets []*pb.Ticket) error {
|
||||
assert.True(len(tickets) <= 2)
|
||||
for _, ticket := range tickets {
|
||||
found[ticket.Id] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
assert.Nil(err)
|
||||
|
||||
assert.Equal(len(found), 4)
|
||||
assert.Contains(found, "ticket.no.3")
|
||||
assert.Contains(found, "ticket.no.4")
|
||||
assert.Contains(found, "ticket.no.7")
|
||||
assert.Contains(found, "ticket.no.8")
|
||||
}
|
||||
|
||||
func createBackend(t *testing.T) config.View {
|
||||
|
@ -17,13 +17,12 @@ package statestore
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
structpb "github.com/golang/protobuf/ptypes/struct"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
@ -266,30 +265,33 @@ func (rb *redisBackend) IndexTicket(ctx context.Context, ticket *pb.Ticket) erro
|
||||
// Alternatives for populating this information in proto fields are being considered.
|
||||
// Also, we need to add Ticket creation time to either the ticket or index.
|
||||
// Meta characters bein specified in JSON property keys is currently not supported.
|
||||
v := gjson.Get(ticket.Properties, attribute)
|
||||
v, ok := ticket.Properties.Fields[attribute]
|
||||
|
||||
// If this attribute wasn't provided in the JSON, continue to the next attribute to index.
|
||||
if !v.Exists() {
|
||||
// If this attribute wasn't provided, continue to the next attribute to index.
|
||||
if !ok {
|
||||
redisLogger.WithFields(logrus.Fields{
|
||||
"attribute": attribute}).Warning("Couldn't find index in Ticket Properties")
|
||||
continue
|
||||
}
|
||||
|
||||
// Value exists. Check if it is a supported value for indexed properties.
|
||||
if v.Int() < math.MaxInt64 || v.Int() > math.MaxInt64 {
|
||||
var d float64
|
||||
|
||||
switch v.Kind.(type) {
|
||||
case *structpb.Value_NumberValue:
|
||||
d = v.GetNumberValue()
|
||||
default:
|
||||
redisLogger.WithFields(logrus.Fields{
|
||||
"attribute": attribute}).Warning("Invalid value for attribute, skip indexing.")
|
||||
continue
|
||||
"attribute": attribute,
|
||||
}).Warning("Attribute not a number.")
|
||||
}
|
||||
|
||||
// Index the attribute by value.
|
||||
value := v.Int()
|
||||
err = redisConn.Send("ZADD", attribute, value, ticket.Id)
|
||||
err = redisConn.Send("ZADD", attribute, d, ticket.Id)
|
||||
if err != nil {
|
||||
redisLogger.WithFields(logrus.Fields{
|
||||
"cmd": "ZADD",
|
||||
"attribute": attribute,
|
||||
"value": value,
|
||||
"value": d,
|
||||
"ticket": ticket.Id,
|
||||
"error": err.Error(),
|
||||
}).Error("failed to index ticket attribute")
|
||||
|
Reference in New Issue
Block a user