mirror of
https://github.com/googleforgames/open-match.git
synced 2025-04-06 12:13:47 +00:00
Compare commits
56 Commits
release-1.
...
v1.8.0-rc.
Author | SHA1 | Date | |
---|---|---|---|
64f0ec7f05 | |||
98e7a02ebf | |||
3d1bae2021 | |||
7070f056df | |||
4c2544f043 | |||
2e6aa4f36f | |||
50b4063bee | |||
31a4a45d73 | |||
67be35006c | |||
d0ce1b317f | |||
93cd5c7a9f | |||
3193921816 | |||
7a3bb82089 | |||
a4eb6d6cbd | |||
927a976a10 | |||
33efc848ff | |||
04c019c6cb | |||
1e51ad859c | |||
fdd8783a34 | |||
036be6455d | |||
5d5f4de7a7 | |||
a9f985d217 | |||
6598a55e74 | |||
4d6da1632a | |||
40a06447d0 | |||
a9d122f50c | |||
73ec73f2e8 | |||
361f8ff3db | |||
8297cac2b8 | |||
120a114647 | |||
7af54ee1bc | |||
68cecb91e5 | |||
67dc60dba8 | |||
09d1ff7171 | |||
b6e5114715 | |||
23d2fd5042 | |||
2b73d52e0c | |||
47c34587dc | |||
76937b6350 | |||
2e03c1a197 | |||
eca40e3298 | |||
902c9d69b4 | |||
67767cf1cd | |||
6f46731b15 | |||
0d1a77c5de | |||
f2a23f5ba1 | |||
3fa588c1f8 | |||
cc08f39205 | |||
ec9cf00bcf | |||
8b8617f68d | |||
ce9b989e58 | |||
5c00395c78 | |||
faf3eded1f | |||
250d44aefd | |||
13fdf5960f | |||
aa5a1f9da1 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1 +1 @@
|
||||
* @laremere @aLekSer @HazWard @calebatwd @jonfoust @sawagh
|
||||
* @laremere @aLekSer @HazWard @calebatwd @syntxerror @sawagh @amg84 @scosgrave @mridulji @markmandel @joeholley
|
||||
|
2
.github/ISSUE_TEMPLATE/bugreport.md
vendored
2
.github/ISSUE_TEMPLATE/bugreport.md
vendored
@ -27,4 +27,4 @@ If the matter is security related, please disclose it privately via
|
||||
|
||||
**Open Match Release Version**:
|
||||
|
||||
**Install Method(yaml/helm):**:
|
||||
**Install Method(yaml/helm)**:
|
||||
|
23
.github/ISSUE_TEMPLATE/release.md
vendored
23
.github/ISSUE_TEMPLATE/release.md
vendored
@ -37,7 +37,7 @@ then you'll need to create the release branch.
|
||||
|
||||
```shell
|
||||
# Create a local release branch.
|
||||
git checkout -b release-0.5 upstream/master
|
||||
git checkout -b release-0.5 upstream/main
|
||||
# Push the branch upstream.
|
||||
git push upstream release-0.5
|
||||
```
|
||||
@ -76,7 +76,7 @@ Hot Fixes:
|
||||
|
||||
Preview:
|
||||
|
||||
* Rare, a one off release cut from the master branch to provide early access
|
||||
* Rare, a one off release cut from the main branch to provide early access
|
||||
to APIs or some other major change.
|
||||
* **NOTE: There's no branch for this release.**
|
||||
* Example: 0.5-preview.1
|
||||
@ -98,7 +98,7 @@ only required once.**
|
||||
|
||||
- [ ] Create the branch in the **upstream** repository. It should be named
|
||||
release-X.Y. Example: release-0.5. At this point there's effectively a code
|
||||
freeze for this version and all work on master will be included in a future
|
||||
freeze for this version and all work on main will be included in a future
|
||||
version. If you're on the branch that you created in the *getting setup*
|
||||
section above you should be able to push upstream.
|
||||
|
||||
@ -131,12 +131,12 @@ git push origin release-0.5
|
||||
only required once.**
|
||||
- [ ] Create the next [version milestone](https://github.com/googleforgames/open-match/milestones) and use [semantic versioning](https://semver.org/) when naming it to be consistent with the [Go community](https://blog.golang.org/versioning-proposal).
|
||||
- [ ] Create a *draft* [release](https://github.com/googleforgames/open-match/releases). Note that github has both "Pre-release" and "draft" as different concepts for a release. Until the release is finalized, only use "Save draft", and do not use "Publish release".
|
||||
- [ ] Use the [release template](https://github.com/googleforgames/open-match/blob/master/docs/governance/templates/release.md)
|
||||
- [ ] Use the [release template](https://github.com/googleforgames/open-match/blob/main/docs/governance/templates/release.md)
|
||||
- [ ] `Tag` = v{version}. Example: v0.5.0. Append -rc.# for release candidates. Example: v0.5.0-rc.1.
|
||||
- [ ] `Target` = release-X.Y. Example: release-0.5.
|
||||
- [ ] `Release Title` = `Tag`
|
||||
- [ ] `Write` section will contain the contents from the [release template](https://github.com/googleforgames/open-match/blob/master/docs/governance/templates/release.md).
|
||||
- [ ] Add the milestone to all PRs and issues that were merged since the last milestone. Look at the [releases page](https://github.com/googleforgames/open-match/releases) and look for the "X commits to master since this release" for the diff.
|
||||
- [ ] `Write` section will contain the contents from the [release template](https://github.com/googleforgames/open-match/blob/main/docs/governance/templates/release.md).
|
||||
- [ ] Add the milestone to all PRs and issues that were merged since the last milestone. Look at the [releases page](https://github.com/googleforgames/open-match/releases) and look for the "X commits to main since this release" for the diff.
|
||||
- [ ] Review all [milestone-less closed issues](https://github.com/googleforgames/open-match/issues?q=is%3Aissue+is%3Aclosed+no%3Amilestone) and assign the appropriate milestone.
|
||||
- [ ] Review all [issues in milestone](https://github.com/googleforgames/open-match/milestones) for proper [labels](https://github.com/googleforgames/open-match/labels) (ex: area/build).
|
||||
- [ ] Review all [milestone-less closed PRs](https://github.com/googleforgames/open-match/pulls?q=is%3Apr+is%3Aclosed+no%3Amilestone) and assign the appropriate milestone.
|
||||
@ -151,6 +151,7 @@ only required once.**
|
||||
- [ ] Go to the History section and find the "Post Submit" build of the merged commit that's running. Wait for it to go Green. If it's red, fix error repeat this section. Take note of the docker image version tag for next step. Example: 0.5.0-a4706cb.
|
||||
- [ ] Run `./docs/governance/templates/release.sh {source version tag} {version}` to copy the images to open-match-public-images.
|
||||
- [ ] If this is a new minor version in the newest major version then run `./docs/governance/templates/release.sh {source version tag} latest`.
|
||||
- [ ] Once the images have successfully been pushed to the registry, modify the line `open-match.dev/open-match v0.0.0-dev` in all `go.mod` files in the [Tutorials] (https://github.com/googleforgames/open-match/tree/main/tutorials) directory to use the current release version. This includes all solution subdirectories as well
|
||||
- [ ] Use the files under the `build/release/` directory for the Open Match installation guide. Make sure the artifacts work as expected - these are the artifacts that will be published to the GCS bucket and used in our release assets.
|
||||
- [ ] Copy the files from `build/release/` generated from `make release` to the release draft you created. You can drag and drop the files using the Github UI.
|
||||
- [ ] Update [Slack invitation link](https://slack.com/help/articles/201330256-invite-new-members-to-your-workspace#share-an-invite-link) in [open-match.dev](https://open-match.dev/site/docs/contribute/#get-involved).
|
||||
@ -174,9 +175,9 @@ only required once.**
|
||||
|
||||
[om-slack]: https://open-match.slack.com/
|
||||
[mailing-list-post]: https://groups.google.com/forum/#!newtopic/open-match-discuss
|
||||
[release-template]: https://github.com/googleforgames/open-match/blob/master/docs/governance/templates/release.md
|
||||
[makefile-version]: https://github.com/googleforgames/open-match/blob/master/Makefile#L53
|
||||
[om-chart-yaml-version]: https://github.com/googleforgames/open-match/blob/master/install/helm/open-match/Chart.yaml#L16
|
||||
[om-values-yaml-version]: https://github.com/googleforgames/open-match/blob/master/install/helm/open-match/values.yaml#L16
|
||||
[release-template]: https://github.com/googleforgames/open-match/blob/main/docs/governance/templates/release.md
|
||||
[makefile-version]: https://github.com/googleforgames/open-match/blob/main/Makefile#L53
|
||||
[om-chart-yaml-version]: https://github.com/googleforgames/open-match/blob/main/install/helm/open-match/Chart.yaml#L16
|
||||
[om-values-yaml-version]: https://github.com/googleforgames/open-match/blob/main/install/helm/open-match/values.yaml#L16
|
||||
[om-release]: https://github.com/googleforgames/open-match/releases/new
|
||||
[readme-deploy]: https://github.com/googleforgames/open-match/blob/master/README.md#deploy-to-kubernetes
|
||||
[readme-deploy]: https://github.com/googleforgames/open-match/blob/main/README.md#deploy-to-kubernetes
|
||||
|
@ -175,6 +175,7 @@ linters:
|
||||
- gosec
|
||||
- interfacer # deprecated - "A tool that suggests interfaces is prone to bad suggestions"
|
||||
- lll
|
||||
- typecheck
|
||||
|
||||
#linters:
|
||||
# enable-all: true
|
||||
|
@ -13,8 +13,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
# When updating Go version, update Dockerfile.ci, Dockerfile.base-build, and go.mod
|
||||
FROM golang:1.14.0
|
||||
ENV GO111MODULE=on
|
||||
FROM golang:1.21.0
|
||||
|
||||
WORKDIR /go/src/open-match.dev/open-match
|
||||
|
||||
|
100
Dockerfile.ci
100
Dockerfile.ci
@ -11,47 +11,65 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
FROM debian:bookworm
|
||||
|
||||
FROM debian
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y -qq git make python3 virtualenv curl sudo unzip apt-transport-https ca-certificates curl software-properties-common gnupg2
|
||||
|
||||
# Docker
|
||||
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
|
||||
RUN sudo apt-key fingerprint 0EBFCD88
|
||||
RUN sudo add-apt-repository \
|
||||
"deb [arch=amd64] https://download.docker.com/linux/debian \
|
||||
stretch \
|
||||
stable"
|
||||
RUN sudo apt-get update
|
||||
RUN sudo apt-get install -y -qq docker-ce docker-ce-cli containerd.io
|
||||
|
||||
# Cloud SDK
|
||||
RUN export CLOUD_SDK_REPO="cloud-sdk-stretch" && \
|
||||
echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \
|
||||
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
|
||||
apt-get update -y && apt-get install google-cloud-sdk google-cloud-sdk-app-engine-go -y -qq
|
||||
|
||||
# Install Golang
|
||||
# https://github.com/docker-library/golang/blob/master/1.14/stretch/Dockerfile
|
||||
RUN mkdir -p /toolchain/golang
|
||||
WORKDIR /toolchain/golang
|
||||
RUN sudo rm -rf /usr/local/go/
|
||||
|
||||
# When updating Go version, update Dockerfile.ci, Dockerfile.base-build, and go.mod
|
||||
RUN curl -L https://golang.org/dl/go1.14.linux-amd64.tar.gz | sudo tar -C /usr/local -xz
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
RUN sudo mkdir -p "$GOPATH/src" "$GOPATH/bin" \
|
||||
&& sudo chmod -R 777 "$GOPATH"
|
||||
|
||||
# Prepare toolchain and workspace
|
||||
RUN mkdir -p /toolchain
|
||||
|
||||
WORKDIR /workspace
|
||||
# set env vars
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV OPEN_MATCH_CI_MODE=1
|
||||
ENV KUBECONFIG=$HOME/.kube/config
|
||||
RUN mkdir -p $HOME/.kube/
|
||||
ENV GOPATH=/go
|
||||
ENV PATH=$GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y -qq --no-install-recommends \
|
||||
apt-utils \
|
||||
git \
|
||||
make \
|
||||
python3 \
|
||||
virtualenv \
|
||||
curl \
|
||||
sudo \
|
||||
unzip \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
curl \
|
||||
software-properties-common \
|
||||
gnupg2 \
|
||||
libc6 \
|
||||
build-essential
|
||||
RUN mkdir -p /usr/share/keyrings/
|
||||
|
||||
# Docker
|
||||
RUN echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" | tee -a /etc/apt/sources.list.d/docker.list \
|
||||
&& curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker.gpg \
|
||||
&& apt-get update -y \
|
||||
&& apt-get install -y -qq \
|
||||
docker-ce \
|
||||
docker-ce-cli \
|
||||
containerd.io
|
||||
|
||||
# Cloud SDK
|
||||
RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
|
||||
&& curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - \
|
||||
&& apt-get update -y \
|
||||
&& apt-get install -y -qq \
|
||||
google-cloud-cli \
|
||||
google-cloud-sdk-gke-gcloud-auth-plugin
|
||||
|
||||
# Install Golang
|
||||
RUN mkdir -p /toolchain/golang
|
||||
WORKDIR /toolchain/golang
|
||||
RUN rm -rf /usr/local/go/
|
||||
|
||||
# When updating Go version, update Dockerfile.ci, Dockerfile.base-build, and go.mod
|
||||
# reference: https://github.com/docker-library/golang/blob/master/1.20/bookworm/Dockerfile
|
||||
RUN curl -L https://golang.org/dl/go1.21.0.linux-amd64.tar.gz | tar -C /usr/local -xz
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" \
|
||||
&& chmod -R 777 "$GOPATH"
|
||||
|
||||
# Prepare toolchain, workspace, homedir
|
||||
RUN mkdir -p \
|
||||
/toolchain \
|
||||
/workspace \
|
||||
$HOME/.kube/
|
||||
WORKDIR /workspace
|
||||
|
@ -18,7 +18,9 @@ WORKDIR /go/src/open-match.dev/open-match
|
||||
|
||||
ARG IMAGE_TITLE
|
||||
|
||||
RUN make "build/cmd/${IMAGE_TITLE}"
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
make "build/cmd/${IMAGE_TITLE}"
|
||||
|
||||
FROM gcr.io/distroless/static:nonroot
|
||||
ARG IMAGE_TITLE
|
||||
|
154
Makefile
154
Makefile
@ -53,7 +53,7 @@
|
||||
# If you want information on how to edit this file checkout,
|
||||
# http://makefiletutorial.com/
|
||||
|
||||
BASE_VERSION = 0.0.0-dev
|
||||
BASE_VERSION = 1.8.0-rc.1
|
||||
SHORT_SHA = $(shell git rev-parse --short=7 HEAD | tr -d [:punct:])
|
||||
BRANCH_NAME = $(shell git rev-parse --abbrev-ref HEAD | tr -d [:punct:])
|
||||
VERSION = $(BASE_VERSION)-$(SHORT_SHA)
|
||||
@ -61,15 +61,15 @@ BUILD_DATE = $(shell date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
YEAR_MONTH = $(shell date -u +'%Y%m')
|
||||
YEAR_MONTH_DAY = $(shell date -u +'%Y%m%d')
|
||||
MAJOR_MINOR_VERSION = $(shell echo $(BASE_VERSION) | cut -d '.' -f1).$(shell echo $(BASE_VERSION) | cut -d '.' -f2)
|
||||
PROTOC_VERSION = 3.10.1
|
||||
HELM_VERSION = 3.0.0
|
||||
KUBECTL_VERSION = 1.16.2
|
||||
PROTOC_VERSION = 24.0
|
||||
HELM_VERSION = 3.12.3
|
||||
KUBECTL_VERSION = 1.27.3
|
||||
MINIKUBE_VERSION = latest
|
||||
GOLANGCI_VERSION = 1.18.0
|
||||
KIND_VERSION = 0.5.1
|
||||
SWAGGERUI_VERSION = 3.24.2
|
||||
GOOGLE_APIS_VERSION = aba342359b6743353195ca53f944fe71e6fb6cd4
|
||||
GRPC_GATEWAY_VERSION = 1.14.3
|
||||
GRPC_GATEWAY_VERSION = 2.16.2
|
||||
TERRAFORM_VERSION = 0.12.13
|
||||
CHART_TESTING_VERSION = 2.4.0
|
||||
|
||||
@ -77,7 +77,7 @@ CHART_TESTING_VERSION = 2.4.0
|
||||
REDIS_DEV_PASSWORD = helloworld
|
||||
|
||||
ENABLE_SECURITY_HARDENING = 0
|
||||
GO = GO111MODULE=on go
|
||||
GO = go
|
||||
# Defines the absolute local directory of the open-match project
|
||||
REPOSITORY_ROOT := $(patsubst %/,%,$(dir $(abspath $(MAKEFILE_LIST))))
|
||||
BUILD_DIR = $(REPOSITORY_ROOT)/build
|
||||
@ -100,11 +100,10 @@ GCP_ZONE = us-west1-a
|
||||
GCP_LOCATION = $(GCP_ZONE)
|
||||
EXE_EXTENSION =
|
||||
GCP_LOCATION_FLAG = --zone $(GCP_ZONE)
|
||||
GO111MODULE = on
|
||||
GOLANG_TEST_COUNT = 1
|
||||
GOLANG_EXTRA_TEST_FLAGS =
|
||||
SWAGGERUI_PORT = 51500
|
||||
PROMETHEUS_PORT = 9090
|
||||
JAEGER_QUERY_PORT = 16686
|
||||
GRAFANA_PORT = 3000
|
||||
FRONTEND_PORT = 51504
|
||||
BACKEND_PORT = 51505
|
||||
@ -121,6 +120,7 @@ CERTGEN = $(TOOLCHAIN_BIN)/certgen$(EXE_EXTENSION)
|
||||
GOLANGCI = $(TOOLCHAIN_BIN)/golangci-lint$(EXE_EXTENSION)
|
||||
CHART_TESTING = $(TOOLCHAIN_BIN)/ct$(EXE_EXTENSION)
|
||||
GCLOUD = gcloud --quiet
|
||||
USE_GKE_GCLOUD_AUTH_PLUGIN = True
|
||||
OPEN_MATCH_HELM_NAME = open-match
|
||||
OPEN_MATCH_KUBERNETES_NAMESPACE = open-match
|
||||
OPEN_MATCH_SECRETS_DIR = $(REPOSITORY_ROOT)/install/helm/open-match/secrets
|
||||
@ -189,8 +189,10 @@ else
|
||||
endif
|
||||
|
||||
GOLANG_PROTOS = pkg/pb/backend.pb.go pkg/pb/frontend.pb.go pkg/pb/matchfunction.pb.go pkg/pb/query.pb.go pkg/pb/messages.pb.go pkg/pb/extensions.pb.go pkg/pb/evaluator.pb.go internal/ipb/synchronizer.pb.go internal/ipb/messages.pb.go pkg/pb/backend.pb.gw.go pkg/pb/frontend.pb.gw.go pkg/pb/matchfunction.pb.gw.go pkg/pb/query.pb.gw.go pkg/pb/evaluator.pb.gw.go
|
||||
golang-protos: $(GOLANG_PROTOS)
|
||||
|
||||
SWAGGER_JSON_DOCS = api/frontend.swagger.json api/backend.swagger.json api/query.swagger.json api/matchfunction.swagger.json api/evaluator.swagger.json
|
||||
swagger-json-docs: $(SWAGGER_JSON_DOCS)
|
||||
|
||||
ALL_PROTOS = $(GOLANG_PROTOS) $(SWAGGER_JSON_DOCS)
|
||||
|
||||
@ -317,10 +319,9 @@ build/chart/: build/chart/index.yaml build/chart/index.yaml.$(YEAR_MONTH_DAY)
|
||||
|
||||
install-chart-prerequisite: build/toolchain/bin/kubectl$(EXE_EXTENSION) update-chart-deps
|
||||
-$(KUBECTL) create namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE)
|
||||
$(KUBECTL) apply -f install/gke-metadata-server-workaround.yaml
|
||||
|
||||
# Used for Open Match development. Install om-configmap-override.yaml by default.
|
||||
HELM_UPGRADE_FLAGS = --cleanup-on-fail -i --no-hooks --debug --timeout=600s --namespace=$(OPEN_MATCH_KUBERNETES_NAMESPACE) --set global.gcpProjectId=$(GCP_PROJECT_ID) --set open-match-override.enabled=true --set redis.password=$(REDIS_DEV_PASSWORD) --set redis.usePassword=false --set redis.sentinel.usePassword=false
|
||||
HELM_UPGRADE_FLAGS = --cleanup-on-fail -i --no-hooks --debug --timeout=600s --namespace=$(OPEN_MATCH_KUBERNETES_NAMESPACE) --set global.gcpProjectId=$(GCP_PROJECT_ID) --set open-match-override.enabled=true --set redis.password=$(REDIS_DEV_PASSWORD) --set redis.auth.enabled=false --set redis.auth.sentinel=false
|
||||
# Used for generate static yamls. Install om-configmap-override.yaml as needed.
|
||||
HELM_TEMPLATE_FLAGS = --no-hooks --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) --set usingHelmTemplate=true
|
||||
HELM_IMAGE_FLAGS = --set global.image.registry=$(REGISTRY) --set global.image.tag=$(TAG)
|
||||
@ -339,7 +340,6 @@ install-large-chart: install-chart-prerequisite install-demo build/toolchain/bin
|
||||
--set open-match-customize.enabled=true \
|
||||
--set open-match-customize.evaluator.enabled=true \
|
||||
--set global.telemetry.grafana.enabled=true \
|
||||
--set global.telemetry.jaeger.enabled=true \
|
||||
--set global.telemetry.prometheus.enabled=true
|
||||
|
||||
# install-chart will install open-match-core, open-match-demo, with the demo evaluator and mmf.
|
||||
@ -357,7 +357,6 @@ install-scale-chart: install-chart-prerequisite build/toolchain/bin/helm$(EXE_EX
|
||||
--set open-match-customize.evaluator.enabled=true \
|
||||
--set open-match-customize.function.image=openmatch-scale-mmf \
|
||||
--set global.telemetry.grafana.enabled=true \
|
||||
--set global.telemetry.jaeger.enabled=false \
|
||||
--set global.telemetry.prometheus.enabled=true
|
||||
$(HELM) template $(OPEN_MATCH_HELM_NAME)-scale install/helm/open-match $(HELM_TEMPLATE_FLAGS) $(HELM_IMAGE_FLAGS) -f install/helm/open-match/values-production.yaml \
|
||||
--set open-match-core.enabled=false \
|
||||
@ -388,8 +387,8 @@ install-ci-chart: install-chart-prerequisite build/toolchain/bin/helm$(EXE_EXTEN
|
||||
delete-chart: build/toolchain/bin/helm$(EXE_EXTENSION) build/toolchain/bin/kubectl$(EXE_EXTENSION)
|
||||
-$(HELM) uninstall $(OPEN_MATCH_HELM_NAME)
|
||||
-$(HELM) uninstall $(OPEN_MATCH_HELM_NAME)-demo
|
||||
-$(KUBECTL) delete psp,clusterrole,clusterrolebinding --selector=release=open-match
|
||||
-$(KUBECTL) delete psp,clusterrole,clusterrolebinding --selector=release=open-match-demo
|
||||
-$(KUBECTL) delete clusterrole,clusterrolebinding --selector=release=open-match
|
||||
-$(KUBECTL) delete clusterrole,clusterrolebinding --selector=release=open-match-demo
|
||||
-$(KUBECTL) delete namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE)
|
||||
-$(KUBECTL) delete namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE)-demo
|
||||
|
||||
@ -397,14 +396,11 @@ ifneq ($(BASE_VERSION), 0.0.0-dev)
|
||||
install/yaml/: REGISTRY = gcr.io/$(OPEN_MATCH_PUBLIC_IMAGES_PROJECT_ID)
|
||||
install/yaml/: TAG = $(BASE_VERSION)
|
||||
endif
|
||||
install/yaml/: update-chart-deps install/yaml/install.yaml install/yaml/01-open-match-core.yaml install/yaml/02-open-match-demo.yaml install/yaml/03-prometheus-chart.yaml install/yaml/04-grafana-chart.yaml install/yaml/05-jaeger-chart.yaml install/yaml/06-open-match-override-configmap.yaml install/yaml/07-open-match-default-evaluator.yaml
|
||||
install/yaml/: update-chart-deps install/yaml/install.yaml install/yaml/01-open-match-core.yaml install/yaml/02-open-match-demo.yaml install/yaml/03-prometheus-chart.yaml install/yaml/04-grafana-chart.yaml install/yaml/06-open-match-override-configmap.yaml install/yaml/07-open-match-default-evaluator.yaml
|
||||
|
||||
# We have to hard-code the Jaeger endpoints as we are excluding Jaeger, so Helm cannot determine the endpoints from the Jaeger subchart
|
||||
install/yaml/01-open-match-core.yaml: build/toolchain/bin/helm$(EXE_EXTENSION)
|
||||
mkdir -p install/yaml/
|
||||
$(HELM) template $(OPEN_MATCH_HELM_NAME) $(HELM_TEMPLATE_FLAGS) $(HELM_IMAGE_FLAGS) \
|
||||
--set-string global.telemetry.jaeger.agentEndpoint="$(OPEN_MATCH_HELM_NAME)-jaeger-agent:6831" \
|
||||
--set-string global.telemetry.jaeger.collectorEndpoint="http://$(OPEN_MATCH_HELM_NAME)-jaeger-collector:14268/api/traces" \
|
||||
install/helm/open-match > install/yaml/01-open-match-core.yaml
|
||||
|
||||
install/yaml/02-open-match-demo.yaml: build/toolchain/bin/helm$(EXE_EXTENSION)
|
||||
@ -433,15 +429,6 @@ install/yaml/04-grafana-chart.yaml: build/toolchain/bin/helm$(EXE_EXTENSION)
|
||||
--set-string global.telemetry.grafana.prometheusServer="http://$(OPEN_MATCH_HELM_NAME)-prometheus-server.$(OPEN_MATCH_KUBERNETES_NAMESPACE).svc.cluster.local:80/" \
|
||||
install/helm/open-match > install/yaml/04-grafana-chart.yaml
|
||||
|
||||
install/yaml/05-jaeger-chart.yaml: build/toolchain/bin/helm$(EXE_EXTENSION)
|
||||
mkdir -p install/yaml/
|
||||
$(HELM) template $(OPEN_MATCH_HELM_NAME) $(HELM_TEMPLATE_FLAGS) $(HELM_IMAGE_FLAGS) \
|
||||
--set open-match-core.enabled=false \
|
||||
--set open-match-core.redis.enabled=false \
|
||||
--set open-match-telemetry.enabled=true \
|
||||
--set global.telemetry.jaeger.enabled=true \
|
||||
install/helm/open-match > install/yaml/05-jaeger-chart.yaml
|
||||
|
||||
install/yaml/06-open-match-override-configmap.yaml: build/toolchain/bin/helm$(EXE_EXTENSION)
|
||||
mkdir -p install/yaml/
|
||||
$(HELM) template $(OPEN_MATCH_HELM_NAME) $(HELM_TEMPLATE_FLAGS) $(HELM_IMAGE_FLAGS) \
|
||||
@ -466,7 +453,6 @@ install/yaml/install.yaml: build/toolchain/bin/helm$(EXE_EXTENSION)
|
||||
--set open-match-customize.enabled=true \
|
||||
--set open-match-customize.evaluator.enabled=true \
|
||||
--set open-match-telemetry.enabled=true \
|
||||
--set global.telemetry.jaeger.enabled=true \
|
||||
--set global.telemetry.grafana.enabled=true \
|
||||
--set global.telemetry.prometheus.enabled=true \
|
||||
install/helm/open-match > install/yaml/install.yaml
|
||||
@ -495,7 +481,7 @@ install-kubernetes-tools: build/toolchain/bin/kubectl$(EXE_EXTENSION) build/tool
|
||||
## # Install protoc tools
|
||||
## make install-protoc-tools
|
||||
##
|
||||
install-protoc-tools: build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-swagger$(EXE_EXTENSION)
|
||||
install-protoc-tools: build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go-grpc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-openapiv2$(EXE_EXTENSION)
|
||||
|
||||
## # Install OpenMatch tools
|
||||
## make install-openmatch-tools
|
||||
@ -564,18 +550,22 @@ build/toolchain/bin/protoc$(EXE_EXTENSION):
|
||||
|
||||
build/toolchain/bin/protoc-gen-doc$(EXE_EXTENSION):
|
||||
mkdir -p $(TOOLCHAIN_BIN)
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) build -i -pkgdir . github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) get github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc && $(GO) build -pkgdir . github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc
|
||||
|
||||
build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION):
|
||||
mkdir -p $(TOOLCHAIN_BIN)
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) build -i -pkgdir . github.com/golang/protobuf/protoc-gen-go
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) get google.golang.org/protobuf/cmd/protoc-gen-go && $(GO) build -pkgdir . google.golang.org/protobuf/cmd/protoc-gen-go
|
||||
|
||||
build/toolchain/bin/protoc-gen-go-grpc$(EXE_EXTENSION):
|
||||
mkdir -p $(TOOLCHAIN_BIN)
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) get google.golang.org/grpc/cmd/protoc-gen-go-grpc && $(GO) build -pkgdir . google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||
|
||||
build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION):
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) build -i -pkgdir . github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway && $(GO) build -pkgdir . github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
|
||||
|
||||
build/toolchain/bin/protoc-gen-swagger$(EXE_EXTENSION):
|
||||
build/toolchain/bin/protoc-gen-openapiv2$(EXE_EXTENSION):
|
||||
mkdir -p $(TOOLCHAIN_BIN)
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) build -i -pkgdir . github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
|
||||
cd $(TOOLCHAIN_BIN) && $(GO) get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 && $(GO) build -pkgdir . github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
|
||||
|
||||
build/toolchain/bin/certgen$(EXE_EXTENSION):
|
||||
mkdir -p $(TOOLCHAIN_BIN)
|
||||
@ -636,26 +626,23 @@ delete-kind-cluster: build/toolchain/bin/kind$(EXE_EXTENSION) build/toolchain/bi
|
||||
create-cluster-role-binding:
|
||||
$(KUBECTL) create clusterrolebinding myname-cluster-admin-binding --clusterrole=cluster-admin --user=$(GCLOUD_ACCOUNT_EMAIL)
|
||||
|
||||
create-gke-cluster: GKE_VERSION = 1.15.12-gke.20 # gcloud beta container get-server-config --zone us-west1-a
|
||||
create-gke-cluster: GKE_CLUSTER_SHAPE_FLAGS = --machine-type n1-standard-4 --enable-autoscaling --min-nodes 1 --num-nodes 2 --max-nodes 10 --disk-size 50
|
||||
create-gke-cluster: GKE_CLUSTER_SHAPE_FLAGS = --machine-type n1-standard-8 --enable-autoscaling --min-nodes 1 --num-nodes 6 --max-nodes 10 --disk-size 50
|
||||
create-gke-cluster: GKE_FUTURE_COMPAT_FLAGS = --no-enable-basic-auth --no-issue-client-certificate --enable-ip-alias --metadata disable-legacy-endpoints=true --enable-autoupgrade
|
||||
create-gke-cluster: build/toolchain/bin/kubectl$(EXE_EXTENSION) gcloud
|
||||
$(GCLOUD) beta $(GCP_PROJECT_FLAG) container clusters create $(GKE_CLUSTER_NAME) $(GCP_LOCATION_FLAG) $(GKE_CLUSTER_SHAPE_FLAGS) $(GKE_FUTURE_COMPAT_FLAGS) $(GKE_CLUSTER_FLAGS) \
|
||||
--enable-pod-security-policy \
|
||||
--cluster-version $(GKE_VERSION) \
|
||||
$(GCLOUD) $(GCP_PROJECT_FLAG) container clusters create $(GKE_CLUSTER_NAME) $(GCP_LOCATION_FLAG) $(GKE_CLUSTER_SHAPE_FLAGS) $(GKE_FUTURE_COMPAT_FLAGS) $(GKE_CLUSTER_FLAGS) \
|
||||
--cluster-version 1.27.3-gke.1700 \
|
||||
--image-type cos_containerd \
|
||||
--tags open-match
|
||||
$(MAKE) create-cluster-role-binding
|
||||
|
||||
--tags open-match \
|
||||
--workload-pool $(GCP_PROJECT_ID).svc.id.goog
|
||||
|
||||
delete-gke-cluster: gcloud
|
||||
-$(GCLOUD) $(GCP_PROJECT_FLAG) container clusters delete $(GKE_CLUSTER_NAME) $(GCP_LOCATION_FLAG) $(GCLOUD_EXTRA_FLAGS)
|
||||
|
||||
create-mini-cluster: build/toolchain/bin/minikube$(EXE_EXTENSION)
|
||||
$(MINIKUBE) start --memory 6144 --cpus 4 --disk-size 50g
|
||||
$(MINIKUBE) start -p openmatch --memory 6144 --cpus 4 --disk-size 50g --kubernetes-version=v1.27.3
|
||||
|
||||
delete-mini-cluster: build/toolchain/bin/minikube$(EXE_EXTENSION)
|
||||
-$(MINIKUBE) delete
|
||||
-$(MINIKUBE) delete -p openmatch
|
||||
|
||||
gcp-apply-binauthz-policy: build/policies/binauthz.yaml
|
||||
$(GCLOUD) beta $(GCP_PROJECT_FLAG) container binauthz policy import build/policies/binauthz.yaml
|
||||
@ -673,31 +660,33 @@ all-protos: $(ALL_PROTOS)
|
||||
# support methods for directing it to the correct location that's not the proto
|
||||
# file's location.
|
||||
# So, instead, put it in a tempororary directory, then move it out.
|
||||
pkg/pb/%.pb.go: api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION)
|
||||
pkg/pb/%.pb.go: api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go-grpc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION)
|
||||
mkdir -p $(REPOSITORY_ROOT)/build/prototmp $(REPOSITORY_ROOT)/pkg/pb
|
||||
$(PROTOC) $< \
|
||||
$(PROTOC) $< \
|
||||
-I $(REPOSITORY_ROOT) -I $(PROTOC_INCLUDES) \
|
||||
--go_out=plugins=grpc:$(REPOSITORY_ROOT)/build/prototmp
|
||||
mv $(REPOSITORY_ROOT)/build/prototmp/open-match.dev/open-match/$@ $@
|
||||
--go_out=$(REPOSITORY_ROOT)/build/prototmp \
|
||||
--go-grpc_out=require_unimplemented_servers=false:$(REPOSITORY_ROOT)/build/prototmp
|
||||
mv $(REPOSITORY_ROOT)/build/prototmp/open-match.dev/open-match/pkg/pb/* $(REPOSITORY_ROOT)/pkg/pb/
|
||||
|
||||
internal/ipb/%.pb.go: internal/api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION)
|
||||
internal/ipb/%.pb.go: internal/api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go-grpc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION)
|
||||
mkdir -p $(REPOSITORY_ROOT)/build/prototmp $(REPOSITORY_ROOT)/internal/ipb
|
||||
$(PROTOC) $< \
|
||||
$(PROTOC) $< \
|
||||
-I $(REPOSITORY_ROOT) -I $(PROTOC_INCLUDES) \
|
||||
--go_out=plugins=grpc:$(REPOSITORY_ROOT)/build/prototmp
|
||||
mv $(REPOSITORY_ROOT)/build/prototmp/open-match.dev/open-match/$@ $@
|
||||
--go_out=$(REPOSITORY_ROOT)/build/prototmp \
|
||||
--go-grpc_out=require_unimplemented_servers=false:$(REPOSITORY_ROOT)/build/prototmp
|
||||
mv $(REPOSITORY_ROOT)/build/prototmp/open-match.dev/open-match/internal/ipb/* $(REPOSITORY_ROOT)/internal/ipb/
|
||||
|
||||
pkg/pb/%.pb.gw.go: api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION)
|
||||
pkg/pb/%.pb.gw.go: api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-go-grpc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-grpc-gateway$(EXE_EXTENSION)
|
||||
mkdir -p $(REPOSITORY_ROOT)/build/prototmp $(REPOSITORY_ROOT)/pkg/pb
|
||||
$(PROTOC) $< \
|
||||
-I $(REPOSITORY_ROOT) -I $(PROTOC_INCLUDES) \
|
||||
--grpc-gateway_out=logtostderr=true,allow_delete_body=true:$(REPOSITORY_ROOT)/build/prototmp
|
||||
mv $(REPOSITORY_ROOT)/build/prototmp/open-match.dev/open-match/$@ $@
|
||||
mv $(REPOSITORY_ROOT)/build/prototmp/open-match.dev/open-match/pkg/pb/* $(REPOSITORY_ROOT)/pkg/pb/
|
||||
|
||||
api/%.swagger.json: api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-swagger$(EXE_EXTENSION)
|
||||
api/%.swagger.json: api/%.proto third_party/ build/toolchain/bin/protoc$(EXE_EXTENSION) build/toolchain/bin/protoc-gen-openapiv2$(EXE_EXTENSION)
|
||||
$(PROTOC) $< \
|
||||
-I $(REPOSITORY_ROOT) -I $(PROTOC_INCLUDES) \
|
||||
--swagger_out=logtostderr=true,allow_delete_body=true:$(REPOSITORY_ROOT)
|
||||
--openapiv2_out=json_names_for_fields=false,logtostderr=true,allow_delete_body=true:$(REPOSITORY_ROOT)
|
||||
|
||||
|
||||
## # Build API reference in markdown. Needs open-match-docs repo at the same level as this one.
|
||||
@ -736,8 +725,10 @@ build: assets
|
||||
define test_folder
|
||||
$(if $(wildcard $(1)/go.mod), \
|
||||
cd $(1) && \
|
||||
$(GO) test -cover -test.count $(GOLANG_TEST_COUNT) -race ./... && \
|
||||
$(GO) test -cover -test.count $(GOLANG_TEST_COUNT) -run IgnoreRace$$ ./... \
|
||||
$(GO) mod tidy && \
|
||||
$(GO) mod download -x && \
|
||||
CGO_ENABLED=1 $(GO) test $(GOLANG_EXTRA_TEST_FLAGS) -p 1 -cover -test.count $(GOLANG_TEST_COUNT) -race -vet=off ./... && \
|
||||
CGO_ENABLED=0 $(GO) test $(GOLANG_EXTRA_TEST_FLAGS) -p 1 -cover -test.count $(GOLANG_TEST_COUNT) -vet=off -run IgnoreRace$$ ./... \
|
||||
)
|
||||
$(foreach dir, $(wildcard $(1)/*/.), $(call test_folder, $(dir)))
|
||||
endef
|
||||
@ -763,7 +754,7 @@ fasttest: $(ALL_PROTOS) tls-certs third_party/
|
||||
$(call fast_test_folder,.)
|
||||
|
||||
test-e2e-cluster: all-protos tls-certs third_party/
|
||||
$(HELM) test --timeout 7m30s -v 0 --logs -n $(OPEN_MATCH_KUBERNETES_NAMESPACE) $(OPEN_MATCH_HELM_NAME)
|
||||
$(HELM) test --timeout 15m --debug -v 0 --logs -n $(OPEN_MATCH_KUBERNETES_NAMESPACE) $(OPEN_MATCH_HELM_NAME)
|
||||
|
||||
fmt:
|
||||
$(GO) fmt ./...
|
||||
@ -773,7 +764,7 @@ vet:
|
||||
$(GO) vet ./...
|
||||
|
||||
golangci: build/toolchain/bin/golangci-lint$(EXE_EXTENSION)
|
||||
GO111MODULE=on $(GOLANGCI) run --config=$(REPOSITORY_ROOT)/.golangci.yaml
|
||||
$(GOLANGCI) run --config=$(REPOSITORY_ROOT)/.golangci.yaml
|
||||
|
||||
## # Run linter on Go code, charts and terraform
|
||||
## make lint
|
||||
@ -792,7 +783,7 @@ $(foreach CMD,$(CMDS),build/cmd/$(CMD)): build/cmd/%: build/cmd/%/BUILD_PHONY bu
|
||||
|
||||
build/cmd/%/BUILD_PHONY:
|
||||
mkdir -p $(BUILD_DIR)/cmd/$*
|
||||
CGO_ENABLED=0 $(GO) build -a -installsuffix cgo -o $(BUILD_DIR)/cmd/$*/run open-match.dev/open-match/cmd/$*
|
||||
CGO_ENABLED=0 $(GO) build -v -installsuffix cgo -o $(BUILD_DIR)/cmd/$*/run open-match.dev/open-match/cmd/$*
|
||||
|
||||
# Default is that nothing needs to be copied into the direcotry
|
||||
build/cmd/%/COPY_PHONY:
|
||||
@ -863,7 +854,7 @@ ci-reap-namespaces: build/toolchain/bin/reaper$(EXE_EXTENSION)
|
||||
-$(TOOLCHAIN_BIN)/reaper -age=30m
|
||||
|
||||
# For presubmit we want to update the protobuf generated files and verify that tests are good.
|
||||
presubmit: GOLANG_TEST_COUNT = 5
|
||||
presubmit: GOLANG_TEST_COUNT = 3
|
||||
presubmit: clean third_party/ update-chart-deps assets update-deps lint build test md-test terraform-test
|
||||
|
||||
build/release/: presubmit clean-install-yaml install/yaml/
|
||||
@ -948,17 +939,13 @@ proxy-synchronizer: build/toolchain/bin/kubectl$(EXE_EXTENSION)
|
||||
@echo "Synchronizer Trace: http://localhost:$(SYNCHRONIZER_PORT)/debug/tracez"
|
||||
$(KUBECTL) port-forward --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) $(shell $(KUBECTL) get pod --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) --selector="app=open-match,component=synchronizer,release=$(OPEN_MATCH_HELM_NAME)" --output jsonpath='{.items[0].metadata.name}') $(SYNCHRONIZER_PORT):51506 $(PORT_FORWARD_ADDRESS_FLAG)
|
||||
|
||||
proxy-jaeger: build/toolchain/bin/kubectl$(EXE_EXTENSION)
|
||||
@echo "Jaeger Query Frontend: http://localhost:16686"
|
||||
$(KUBECTL) port-forward --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) $(shell $(KUBECTL) get pod --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) --selector="app.kubernetes.io/name=jaeger,app.kubernetes.io/component=query" --output jsonpath='{.items[0].metadata.name}') $(JAEGER_QUERY_PORT):16686 $(PORT_FORWARD_ADDRESS_FLAG)
|
||||
|
||||
proxy-grafana: build/toolchain/bin/kubectl$(EXE_EXTENSION)
|
||||
@echo "User: admin"
|
||||
@echo "Password: openmatch"
|
||||
$(KUBECTL) port-forward --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) $(shell $(KUBECTL) get pod --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) --selector="app=grafana,release=$(OPEN_MATCH_HELM_NAME)" --output jsonpath='{.items[0].metadata.name}') $(GRAFANA_PORT):3000 $(PORT_FORWARD_ADDRESS_FLAG)
|
||||
$(KUBECTL) port-forward --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) service/$(shell $(KUBECTL) get service --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) --selector="app.kubernetes.io/name=grafana" --output jsonpath='{.items[0].metadata.name}') $(GRAFANA_PORT):3000 $(PORT_FORWARD_ADDRESS_FLAG)
|
||||
|
||||
proxy-prometheus: build/toolchain/bin/kubectl$(EXE_EXTENSION)
|
||||
$(KUBECTL) port-forward --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) $(shell $(KUBECTL) get pod --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) --selector="app=prometheus,component=server,release=$(OPEN_MATCH_HELM_NAME)" --output jsonpath='{.items[0].metadata.name}') $(PROMETHEUS_PORT):9090 $(PORT_FORWARD_ADDRESS_FLAG)
|
||||
$(KUBECTL) port-forward --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) service/$(shell $(KUBECTL) get service --namespace $(OPEN_MATCH_KUBERNETES_NAMESPACE) --selector="app=prometheus,component=server,release=$(OPEN_MATCH_HELM_NAME)" --output jsonpath='{.items[0].metadata.name}') $(PROMETHEUS_PORT):80 $(PORT_FORWARD_ADDRESS_FLAG)
|
||||
|
||||
proxy-dashboard: build/toolchain/bin/kubectl$(EXE_EXTENSION)
|
||||
$(KUBECTL) port-forward --namespace kube-system $(shell $(KUBECTL) get pod --namespace kube-system --selector="app=kubernetes-dashboard" --output jsonpath='{.items[0].metadata.name}') $(DASHBOARD_PORT):9092 $(PORT_FORWARD_ADDRESS_FLAG)
|
||||
@ -973,7 +960,7 @@ proxy-demo: build/toolchain/bin/kubectl$(EXE_EXTENSION)
|
||||
|
||||
# Run `make proxy` instead to run everything at the same time.
|
||||
# If you run this directly it will just run each proxy sequentially.
|
||||
proxy-all: proxy-frontend proxy-backend proxy-query proxy-grafana proxy-prometheus proxy-jaeger proxy-synchronizer proxy-ui proxy-dashboard proxy-demo
|
||||
proxy-all: proxy-frontend proxy-backend proxy-query proxy-grafana proxy-prometheus proxy-synchronizer proxy-ui proxy-dashboard proxy-demo
|
||||
|
||||
proxy:
|
||||
# This is an exception case where we'll call recursive make.
|
||||
@ -982,8 +969,9 @@ proxy:
|
||||
|
||||
update-deps:
|
||||
$(GO) mod tidy
|
||||
$(MAKE) tutorial-deps
|
||||
|
||||
third_party/: third_party/google/api third_party/protoc-gen-swagger/options third_party/swaggerui/
|
||||
third_party/: third_party/google/api third_party/protoc-gen-openapiv2/options third_party/swaggerui/
|
||||
|
||||
third_party/google/api:
|
||||
mkdir -p $(TOOLCHAIN_DIR)/googleapis-temp/
|
||||
@ -995,12 +983,12 @@ third_party/google/api:
|
||||
cp -f $(TOOLCHAIN_DIR)/googleapis-temp/googleapis-$(GOOGLE_APIS_VERSION)/google/rpc/*.proto $(REPOSITORY_ROOT)/third_party/google/rpc/
|
||||
rm -rf $(TOOLCHAIN_DIR)/googleapis-temp
|
||||
|
||||
third_party/protoc-gen-swagger/options:
|
||||
third_party/protoc-gen-openapiv2/options:
|
||||
mkdir -p $(TOOLCHAIN_DIR)/grpc-gateway-temp/
|
||||
mkdir -p $(REPOSITORY_ROOT)/third_party/protoc-gen-swagger/options
|
||||
mkdir -p $(REPOSITORY_ROOT)/third_party/protoc-gen-openapiv2/options
|
||||
curl -o $(TOOLCHAIN_DIR)/grpc-gateway-temp/grpc-gateway.zip -L https://github.com/grpc-ecosystem/grpc-gateway/archive/v$(GRPC_GATEWAY_VERSION).zip
|
||||
(cd $(TOOLCHAIN_DIR)/grpc-gateway-temp/; unzip -q -o grpc-gateway.zip)
|
||||
cp -f $(TOOLCHAIN_DIR)/grpc-gateway-temp/grpc-gateway-$(GRPC_GATEWAY_VERSION)/protoc-gen-swagger/options/*.proto $(REPOSITORY_ROOT)/third_party/protoc-gen-swagger/options/
|
||||
cp -f $(TOOLCHAIN_DIR)/grpc-gateway-temp/grpc-gateway-$(GRPC_GATEWAY_VERSION)/protoc-gen-openapiv2/options/*.proto $(REPOSITORY_ROOT)/third_party/protoc-gen-openapiv2/options/
|
||||
rm -rf $(TOOLCHAIN_DIR)/grpc-gateway-temp
|
||||
|
||||
third_party/swaggerui/:
|
||||
@ -1017,9 +1005,25 @@ third_party/swaggerui/:
|
||||
$(SED_REPLACE) 's|0.0.0-dev|$(BASE_VERSION)|g' $(REPOSITORY_ROOT)/third_party/swaggerui/config.json
|
||||
rm -rf $(TOOLCHAIN_DIR)/swaggerui-temp
|
||||
|
||||
sync-deps:
|
||||
|
||||
clean-deps:
|
||||
$(GO) clean -modcache
|
||||
$(GO) mod download
|
||||
|
||||
sync-deps: clean-deps
|
||||
$(GO) mod tidy
|
||||
$(GO) mod download -x
|
||||
|
||||
define tutorial_folder
|
||||
$(if $(wildcard $(1)/go.mod), \
|
||||
cd $(1) && \
|
||||
$(GO) mod tidy
|
||||
)
|
||||
$(foreach dir, $(wildcard $(1)/*/.), $(call tutorial_folder, $(dir)))
|
||||
endef
|
||||
|
||||
tutorial-deps:
|
||||
$(call tutorial_folder,./tutorials)
|
||||
|
||||
|
||||
# Prevents users from running with sudo.
|
||||
# There's an exception for Google Cloud Build because it runs as root.
|
||||
|
@ -19,9 +19,9 @@ option csharp_namespace = "OpenMatch";
|
||||
|
||||
import "api/messages.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "protoc-gen-swagger/options/annotations.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Backend"
|
||||
version: "1.0"
|
||||
|
@ -13,6 +13,11 @@
|
||||
"url": "https://github.com/googleforgames/open-match/blob/master/LICENSE"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "BackendService"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
@ -38,7 +43,7 @@
|
||||
"$ref": "#/definitions/openmatchFetchMatchesResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of openmatchFetchMatchesResponse"
|
||||
@ -54,7 +59,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -94,7 +99,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -115,8 +120,7 @@
|
||||
},
|
||||
"/v1/backendservice/tickets:release": {
|
||||
"post": {
|
||||
"summary": "ReleaseTickets moves tickets from the pending state, to the active state.\nThis enables them to be returned by query, and find different matches.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "ReleaseTickets moves tickets from the pending state, to the active state.\nThis enables them to be returned by query, and find different matches.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "BackendService_ReleaseTickets",
|
||||
"responses": {
|
||||
"200": {
|
||||
@ -135,7 +139,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -156,8 +160,7 @@
|
||||
},
|
||||
"/v1/backendservice/tickets:releaseall": {
|
||||
"post": {
|
||||
"summary": "ReleaseAllTickets moves all tickets from the pending state, to the active\nstate. This enables them to be returned by query, and find different\nmatches.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "ReleaseAllTickets moves all tickets from the pending state, to the active\nstate. This enables them to be returned by query, and find different\nmatches.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "BackendService_ReleaseAllTickets",
|
||||
"responses": {
|
||||
"200": {
|
||||
@ -176,7 +179,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -222,6 +225,7 @@
|
||||
"assignments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchAssignmentGroup"
|
||||
},
|
||||
"description": "Assignments is a list of assignment groups that contain assignment and the Tickets to which they should be applied."
|
||||
@ -234,6 +238,7 @@
|
||||
"failures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchAssignmentFailure"
|
||||
},
|
||||
"description": "Failures is a list of all the Tickets that failed assignment along with the cause of failure."
|
||||
@ -302,7 +307,14 @@
|
||||
"additionalProperties": {
|
||||
"$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."
|
||||
"description": "Customized information not inspected by Open Match, to be used by\nthe Match Function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a backfill. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
@ -312,10 +324,10 @@
|
||||
"generation": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo not read or write to this field, it is for internal tracking and changing the value will cause bugs."
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo NOT read or write to this field, it is for internal tracking, and changing the value will cause bugs."
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.\nRepresents a backfill entity which is used to fill partially full matches."
|
||||
"description": "Represents a backfill entity which is used to fill partially full matches.\n\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal."
|
||||
},
|
||||
"openmatchDoubleRangeFilter": {
|
||||
"type": "object",
|
||||
@ -336,7 +348,7 @@
|
||||
},
|
||||
"exclude": {
|
||||
"$ref": "#/definitions/DoubleRangeFilterExclude",
|
||||
"description": "Which bounds would be excluded when comparing with a ticket's search_fields.double_args value.\n\nBETA FEATURE WARNING: This field and the associated values are\nnot finalized and still subject to possible change or removal."
|
||||
"description": "Defines the bounds to apply when filtering tickets by their search_fields.double_args value.\nBETA FEATURE WARNING: This field and the associated values are\nnot finalized and still subject to possible change or removal."
|
||||
}
|
||||
},
|
||||
"title": "Filters numerical values to only those within a range.\n double_arg: \"foo\"\n max: 10\n min: 5\nmatches:\n {\"foo\": 5}\n {\"foo\": 7.5}\n {\"foo\": 10}\ndoes not match:\n {\"foo\": 4}\n {\"foo\": 10.01}\n {\"foo\": \"7.5\"}\n {}"
|
||||
@ -405,6 +417,7 @@
|
||||
"tickets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTicket"
|
||||
},
|
||||
"description": "Tickets belonging to this match."
|
||||
@ -418,11 +431,11 @@
|
||||
},
|
||||
"backfill": {
|
||||
"$ref": "#/definitions/openmatchBackfill",
|
||||
"description": "Backfill request which contains additional information to the match\nand contains an association to a GameServer.\n\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
"description": "Backfill request which contains additional information to the match\nand contains an association to a GameServer.\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
},
|
||||
"allocate_gameserver": {
|
||||
"type": "boolean",
|
||||
"description": "AllocateGameServer signalise Director that Backfill is new and it should \nallocate a GameServer, this Backfill would be assigned.\n\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
"description": "AllocateGameServer signalise Director that Backfill is new and it should \nallocate a GameServer, this Backfill would be assigned.\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
}
|
||||
},
|
||||
"description": "A Match is used to represent a completed match object. It can be generated by\na MatchFunction as a proposal or can be returned by OpenMatch as a result in\nresponse to the FetchMatches call.\nWhen a match is returned by the FetchMatches call, it should contain at least\none ticket to be considered as valid."
|
||||
@ -437,6 +450,7 @@
|
||||
"pools": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchPool"
|
||||
},
|
||||
"description": "Set of pools to be queried when generating a match for this MatchProfile."
|
||||
@ -461,6 +475,7 @@
|
||||
"double_range_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchDoubleRangeFilter"
|
||||
},
|
||||
"description": "Set of Filters indicating the filtering criteria. Selected tickets must\nmatch every Filter."
|
||||
@ -468,12 +483,14 @@
|
||||
"string_equals_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchStringEqualsFilter"
|
||||
}
|
||||
},
|
||||
"tag_present_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTagPresentFilter"
|
||||
}
|
||||
},
|
||||
@ -583,6 +600,13 @@
|
||||
},
|
||||
"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."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a ticket. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
@ -594,63 +618,36 @@
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type_url": {
|
||||
"@type": {
|
||||
"type": "string",
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "Must be a valid serialized protocol buffer of the above specified type."
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
}
|
||||
},
|
||||
"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 }"
|
||||
"additionalProperties": {},
|
||||
"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 // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\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 := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(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\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 }"
|
||||
},
|
||||
"runtimeError": {
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int32",
|
||||
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]."
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "A developer-facing error message, which should be in English. Any\nuser-facing error message should be localized and sent in the\n[google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
},
|
||||
"description": "A list of messages that carry the error details. There is a common set of\nmessage types for APIs to use."
|
||||
}
|
||||
}
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"grpc_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"http_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"http_status": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "The `Status` type defines a logical error model that is suitable for\ndifferent programming environments, including REST APIs and RPC APIs. It is\nused by [gRPC](https://github.com/grpc). Each `Status` message contains\nthree pieces of data: error code, error message, and error details.\n\nYou can find out more about this error model and how to work with it in the\n[API Design Guide](https://cloud.google.com/apis/design/errors)."
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
|
@ -19,9 +19,9 @@ option csharp_namespace = "OpenMatch";
|
||||
|
||||
import "api/messages.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "protoc-gen-swagger/options/annotations.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Evaluator"
|
||||
version: "1.0"
|
||||
|
@ -13,6 +13,11 @@
|
||||
"url": "https://github.com/googleforgames/open-match/blob/master/LICENSE"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "Evaluator"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
@ -38,7 +43,7 @@
|
||||
"$ref": "#/definitions/openmatchEvaluateResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of openmatchEvaluateResponse"
|
||||
@ -54,7 +59,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -109,7 +114,14 @@
|
||||
"additionalProperties": {
|
||||
"$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."
|
||||
"description": "Customized information not inspected by Open Match, to be used by\nthe Match Function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a backfill. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
@ -119,10 +131,10 @@
|
||||
"generation": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo not read or write to this field, it is for internal tracking and changing the value will cause bugs."
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo NOT read or write to this field, it is for internal tracking, and changing the value will cause bugs."
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.\nRepresents a backfill entity which is used to fill partially full matches."
|
||||
"description": "Represents a backfill entity which is used to fill partially full matches.\n\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal."
|
||||
},
|
||||
"openmatchEvaluateRequest": {
|
||||
"type": "object",
|
||||
@ -160,6 +172,7 @@
|
||||
"tickets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTicket"
|
||||
},
|
||||
"description": "Tickets belonging to this match."
|
||||
@ -173,11 +186,11 @@
|
||||
},
|
||||
"backfill": {
|
||||
"$ref": "#/definitions/openmatchBackfill",
|
||||
"description": "Backfill request which contains additional information to the match\nand contains an association to a GameServer.\n\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
"description": "Backfill request which contains additional information to the match\nand contains an association to a GameServer.\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
},
|
||||
"allocate_gameserver": {
|
||||
"type": "boolean",
|
||||
"description": "AllocateGameServer signalise Director that Backfill is new and it should \nallocate a GameServer, this Backfill would be assigned.\n\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
"description": "AllocateGameServer signalise Director that Backfill is new and it should \nallocate a GameServer, this Backfill would be assigned.\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
}
|
||||
},
|
||||
"description": "A Match is used to represent a completed match object. It can be generated by\na MatchFunction as a proposal or can be returned by OpenMatch as a result in\nresponse to the FetchMatches call.\nWhen a match is returned by the FetchMatches call, it should contain at least\none ticket to be considered as valid."
|
||||
@ -232,6 +245,13 @@
|
||||
},
|
||||
"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."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a ticket. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
@ -243,63 +263,36 @@
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type_url": {
|
||||
"@type": {
|
||||
"type": "string",
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "Must be a valid serialized protocol buffer of the above specified type."
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
}
|
||||
},
|
||||
"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 }"
|
||||
"additionalProperties": {},
|
||||
"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 // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\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 := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(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\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 }"
|
||||
},
|
||||
"runtimeError": {
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int32",
|
||||
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]."
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "A developer-facing error message, which should be in English. Any\nuser-facing error message should be localized and sent in the\n[google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
},
|
||||
"description": "A list of messages that carry the error details. There is a common set of\nmessage types for APIs to use."
|
||||
}
|
||||
}
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"grpc_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"http_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"http_status": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "The `Status` type defines a logical error model that is suitable for\ndifferent programming environments, including REST APIs and RPC APIs. It is\nused by [gRPC](https://github.com/grpc). Each `Status` message contains\nthree pieces of data: error code, error message, and error details.\n\nYou can find out more about this error model and how to work with it in the\n[API Design Guide](https://cloud.google.com/apis/design/errors)."
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
|
@ -19,10 +19,10 @@ option csharp_namespace = "OpenMatch";
|
||||
|
||||
import "api/messages.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "protoc-gen-swagger/options/annotations.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Frontend"
|
||||
version: "1.0"
|
||||
@ -91,6 +91,16 @@ message AcknowledgeBackfillRequest {
|
||||
Assignment assignment = 2;
|
||||
}
|
||||
|
||||
// BETA FEATURE WARNING: This Request message is not finalized and still subject
|
||||
// to possible change or removal.
|
||||
message AcknowledgeBackfillResponse {
|
||||
// The Backfill that was acknowledged.
|
||||
Backfill backfill = 1;
|
||||
|
||||
// All of the Tickets that were successfully assigned
|
||||
repeated Ticket tickets = 2;
|
||||
}
|
||||
|
||||
// BETA FEATURE WARNING: This Request message is not finalized and still subject
|
||||
// to possible change or removal.
|
||||
message CreateBackfillRequest {
|
||||
@ -163,7 +173,7 @@ service FrontendService {
|
||||
// This triggers an assignment process.
|
||||
// BETA FEATURE WARNING: This call and the associated Request and Response
|
||||
// messages are not finalized and still subject to possible change or removal.
|
||||
rpc AcknowledgeBackfill(AcknowledgeBackfillRequest) returns (Backfill) {
|
||||
rpc AcknowledgeBackfill(AcknowledgeBackfillRequest) returns (AcknowledgeBackfillResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/frontendservice/backfills/{backfill_id}/acknowledge"
|
||||
body: "*"
|
||||
|
@ -13,6 +13,11 @@
|
||||
"url": "https://github.com/googleforgames/open-match/blob/master/LICENSE"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "FrontendService"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
@ -26,8 +31,7 @@
|
||||
"paths": {
|
||||
"/v1/frontendservice/backfills": {
|
||||
"post": {
|
||||
"summary": "CreateBackfill creates a new Backfill object.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "CreateBackfill creates a new Backfill object.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "FrontendService_CreateBackfill",
|
||||
"responses": {
|
||||
"200": {
|
||||
@ -46,13 +50,14 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"description": "BETA FEATURE WARNING: This Request message is not finalized and still subject\nto possible change or removal.",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
@ -65,8 +70,7 @@
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"summary": "UpdateBackfill updates search_fields and extensions for the backfill with the provided id.\nAny tickets waiting for this backfill will be returned to the active pool, no longer pending.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "UpdateBackfill updates search_fields and extensions for the backfill with the provided id.\nAny tickets waiting for this backfill will be returned to the active pool, no longer pending.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "FrontendService_UpdateBackfill",
|
||||
"responses": {
|
||||
"200": {
|
||||
@ -85,13 +89,14 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"description": "UpdateBackfillRequest - update searchFields, extensions and set assignment.\n\nBETA FEATURE WARNING: This Request message is not finalized and still subject\nto possible change or removal.",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
@ -106,8 +111,7 @@
|
||||
},
|
||||
"/v1/frontendservice/backfills/{backfill_id}": {
|
||||
"get": {
|
||||
"summary": "GetBackfill returns a backfill object by its ID.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "GetBackfill returns a backfill object by its ID.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "FrontendService_GetBackfill",
|
||||
"responses": {
|
||||
"200": {
|
||||
@ -126,13 +130,14 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "backfill_id",
|
||||
"description": "An existing ID of Backfill to retrieve.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
@ -143,13 +148,13 @@
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"summary": "DeleteBackfill receives a backfill ID and deletes its resource.\nAny tickets waiting for this backfill will be returned to the active pool, no longer pending.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "DeleteBackfill receives a backfill ID and deletes its resource.\nAny tickets waiting for this backfill will be returned to the active pool, no longer pending.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "FrontendService_DeleteBackfill",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
},
|
||||
@ -163,13 +168,14 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "backfill_id",
|
||||
"description": "An existing ID of Backfill to delete.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
@ -182,14 +188,13 @@
|
||||
},
|
||||
"/v1/frontendservice/backfills/{backfill_id}/acknowledge": {
|
||||
"post": {
|
||||
"summary": "AcknowledgeBackfill is used to notify OpenMatch about GameServer connection info\nThis triggers an assignment process.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "AcknowledgeBackfill is used to notify OpenMatch about GameServer connection info\nThis triggers an assignment process.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "FrontendService_AcknowledgeBackfill",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/openmatchBackfill"
|
||||
"$ref": "#/definitions/openmatchAcknowledgeBackfillResponse"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
@ -202,13 +207,14 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "backfill_id",
|
||||
"description": "An existing ID of Backfill to acknowledge.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
@ -218,7 +224,14 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/openmatchAcknowledgeBackfillRequest"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"assignment": {
|
||||
"$ref": "#/definitions/openmatchAssignment",
|
||||
"description": "An updated Assignment of the requested Backfill."
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This Request message is not finalized and still subject\nto possible change or removal."
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -248,7 +261,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -288,7 +301,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -312,6 +325,7 @@
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
},
|
||||
@ -325,7 +339,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -357,7 +371,7 @@
|
||||
"$ref": "#/definitions/openmatchWatchAssignmentsResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of openmatchWatchAssignmentsResponse"
|
||||
@ -373,7 +387,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -393,14 +407,20 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"openmatchAcknowledgeBackfillRequest": {
|
||||
"openmatchAcknowledgeBackfillResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backfill_id": {
|
||||
"type": "string"
|
||||
"backfill": {
|
||||
"$ref": "#/definitions/openmatchBackfill",
|
||||
"description": "The Backfill that was acknowledged."
|
||||
},
|
||||
"assignment": {
|
||||
"$ref": "#/definitions/openmatchAssignment"
|
||||
"tickets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTicket"
|
||||
},
|
||||
"title": "All of the Tickets that were successfully assigned"
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This Request message is not finalized and still subject\nto possible change or removal."
|
||||
@ -438,7 +458,14 @@
|
||||
"additionalProperties": {
|
||||
"$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."
|
||||
"description": "Customized information not inspected by Open Match, to be used by\nthe Match Function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a backfill. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
@ -448,16 +475,17 @@
|
||||
"generation": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo not read or write to this field, it is for internal tracking and changing the value will cause bugs."
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo NOT read or write to this field, it is for internal tracking, and changing the value will cause bugs."
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.\nRepresents a backfill entity which is used to fill partially full matches."
|
||||
"description": "Represents a backfill entity which is used to fill partially full matches.\n\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal."
|
||||
},
|
||||
"openmatchCreateBackfillRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backfill": {
|
||||
"$ref": "#/definitions/openmatchBackfill"
|
||||
"$ref": "#/definitions/openmatchBackfill",
|
||||
"description": "An empty Backfill object."
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This Request message is not finalized and still subject\nto possible change or removal."
|
||||
@ -521,6 +549,13 @@
|
||||
},
|
||||
"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."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a ticket. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
@ -533,7 +568,8 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backfill": {
|
||||
"$ref": "#/definitions/openmatchBackfill"
|
||||
"$ref": "#/definitions/openmatchBackfill",
|
||||
"description": "A Backfill object with ID set and fields to update."
|
||||
}
|
||||
},
|
||||
"description": "UpdateBackfillRequest - update searchFields, extensions and set assignment.\n\nBETA FEATURE WARNING: This Request message is not finalized and still subject\nto possible change or removal."
|
||||
@ -550,63 +586,36 @@
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type_url": {
|
||||
"@type": {
|
||||
"type": "string",
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "Must be a valid serialized protocol buffer of the above specified type."
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
}
|
||||
},
|
||||
"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 }"
|
||||
"additionalProperties": {},
|
||||
"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 // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\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 := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(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\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 }"
|
||||
},
|
||||
"runtimeError": {
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int32",
|
||||
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]."
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "A developer-facing error message, which should be in English. Any\nuser-facing error message should be localized and sent in the\n[google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
},
|
||||
"description": "A list of messages that carry the error details. There is a common set of\nmessage types for APIs to use."
|
||||
}
|
||||
}
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"grpc_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"http_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"http_status": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "The `Status` type defines a logical error model that is suitable for\ndifferent programming environments, including REST APIs and RPC APIs. It is\nused by [gRPC](https://github.com/grpc). Each `Status` message contains\nthree pieces of data: error code, error message, and error details.\n\nYou can find out more about this error model and how to work with it in the\n[API Design Guide](https://cloud.google.com/apis/design/errors)."
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
|
@ -19,9 +19,9 @@ option csharp_namespace = "OpenMatch";
|
||||
|
||||
import "api/messages.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "protoc-gen-swagger/options/annotations.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "Match Function"
|
||||
version: "1.0"
|
||||
|
@ -13,6 +13,11 @@
|
||||
"url": "https://github.com/googleforgames/open-match/blob/master/LICENSE"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "MatchFunction"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
@ -26,7 +31,7 @@
|
||||
"paths": {
|
||||
"/v1/matchfunction:run": {
|
||||
"post": {
|
||||
"summary": "DO NOT CALL THIS FUNCTION MANUALLY. USE backend.FetchMatches INSTEAD.\nRun pulls Tickets that satisfy Profile constraints from QueryService, runs matchmaking logics against them, then\nconstructs and streams back match candidates to the Backend service.",
|
||||
"summary": "DO NOT CALL THIS FUNCTION MANUALLY. USE backend.FetchMatches INSTEAD.\nRun pulls Tickets that satisfy Profile constraints from QueryService,\nruns matchmaking logic against them, then constructs and streams back\nmatch candidates to the Backend service.",
|
||||
"operationId": "MatchFunction_Run",
|
||||
"responses": {
|
||||
"200": {
|
||||
@ -38,7 +43,7 @@
|
||||
"$ref": "#/definitions/openmatchRunResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of openmatchRunResponse"
|
||||
@ -54,7 +59,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -119,7 +124,14 @@
|
||||
"additionalProperties": {
|
||||
"$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."
|
||||
"description": "Customized information not inspected by Open Match, to be used by\nthe Match Function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a backfill. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
@ -129,10 +141,10 @@
|
||||
"generation": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo not read or write to this field, it is for internal tracking and changing the value will cause bugs."
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo NOT read or write to this field, it is for internal tracking, and changing the value will cause bugs."
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.\nRepresents a backfill entity which is used to fill partially full matches."
|
||||
"description": "Represents a backfill entity which is used to fill partially full matches.\n\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal."
|
||||
},
|
||||
"openmatchDoubleRangeFilter": {
|
||||
"type": "object",
|
||||
@ -153,7 +165,7 @@
|
||||
},
|
||||
"exclude": {
|
||||
"$ref": "#/definitions/DoubleRangeFilterExclude",
|
||||
"description": "Which bounds would be excluded when comparing with a ticket's search_fields.double_args value.\n\nBETA FEATURE WARNING: This field and the associated values are\nnot finalized and still subject to possible change or removal."
|
||||
"description": "Defines the bounds to apply when filtering tickets by their search_fields.double_args value.\nBETA FEATURE WARNING: This field and the associated values are\nnot finalized and still subject to possible change or removal."
|
||||
}
|
||||
},
|
||||
"title": "Filters numerical values to only those within a range.\n double_arg: \"foo\"\n max: 10\n min: 5\nmatches:\n {\"foo\": 5}\n {\"foo\": 7.5}\n {\"foo\": 10}\ndoes not match:\n {\"foo\": 4}\n {\"foo\": 10.01}\n {\"foo\": \"7.5\"}\n {}"
|
||||
@ -176,6 +188,7 @@
|
||||
"tickets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTicket"
|
||||
},
|
||||
"description": "Tickets belonging to this match."
|
||||
@ -189,11 +202,11 @@
|
||||
},
|
||||
"backfill": {
|
||||
"$ref": "#/definitions/openmatchBackfill",
|
||||
"description": "Backfill request which contains additional information to the match\nand contains an association to a GameServer.\n\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
"description": "Backfill request which contains additional information to the match\nand contains an association to a GameServer.\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
},
|
||||
"allocate_gameserver": {
|
||||
"type": "boolean",
|
||||
"description": "AllocateGameServer signalise Director that Backfill is new and it should \nallocate a GameServer, this Backfill would be assigned.\n\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
"description": "AllocateGameServer signalise Director that Backfill is new and it should \nallocate a GameServer, this Backfill would be assigned.\nBETA FEATURE WARNING: This field is not finalized and still subject\nto possible change or removal."
|
||||
}
|
||||
},
|
||||
"description": "A Match is used to represent a completed match object. It can be generated by\na MatchFunction as a proposal or can be returned by OpenMatch as a result in\nresponse to the FetchMatches call.\nWhen a match is returned by the FetchMatches call, it should contain at least\none ticket to be considered as valid."
|
||||
@ -208,6 +221,7 @@
|
||||
"pools": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchPool"
|
||||
},
|
||||
"description": "Set of pools to be queried when generating a match for this MatchProfile."
|
||||
@ -232,6 +246,7 @@
|
||||
"double_range_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchDoubleRangeFilter"
|
||||
},
|
||||
"description": "Set of Filters indicating the filtering criteria. Selected tickets must\nmatch every Filter."
|
||||
@ -239,12 +254,14 @@
|
||||
"string_equals_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchStringEqualsFilter"
|
||||
}
|
||||
},
|
||||
"tag_present_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTagPresentFilter"
|
||||
}
|
||||
},
|
||||
@ -351,6 +368,13 @@
|
||||
},
|
||||
"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."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a ticket. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
@ -362,63 +386,36 @@
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type_url": {
|
||||
"@type": {
|
||||
"type": "string",
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "Must be a valid serialized protocol buffer of the above specified type."
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
}
|
||||
},
|
||||
"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 }"
|
||||
"additionalProperties": {},
|
||||
"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 // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\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 := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(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\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 }"
|
||||
},
|
||||
"runtimeError": {
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int32",
|
||||
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]."
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "A developer-facing error message, which should be in English. Any\nuser-facing error message should be localized and sent in the\n[google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
},
|
||||
"description": "A list of messages that carry the error details. There is a common set of\nmessage types for APIs to use."
|
||||
}
|
||||
}
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"grpc_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"http_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"http_status": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "The `Status` type defines a logical error model that is suitable for\ndifferent programming environments, including REST APIs and RPC APIs. It is\nused by [gRPC](https://github.com/grpc). Each `Status` message contains\nthree pieces of data: error code, error message, and error details.\n\nYou can find out more about this error model and how to work with it in the\n[API Design Guide](https://cloud.google.com/apis/design/errors)."
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
|
@ -45,9 +45,14 @@ message Ticket {
|
||||
// Optional, depending on the requirements of the connected systems.
|
||||
map<string, google.protobuf.Any> extensions = 5;
|
||||
|
||||
// Customized information not inspected by Open Match, to be kept persistent
|
||||
// throughout the life-cycle of a ticket.
|
||||
// Optional, depending on the requirements of the connected systems.
|
||||
map<string, google.protobuf.Any> persistent_field = 6;
|
||||
|
||||
// Create time is the time the Ticket was created. It is populated by Open
|
||||
// Match at the time of Ticket creation.
|
||||
google.protobuf.Timestamp create_time = 6;
|
||||
google.protobuf.Timestamp create_time = 7;
|
||||
|
||||
// Deprecated fields.
|
||||
reserved 2;
|
||||
@ -253,12 +258,17 @@ message Backfill {
|
||||
// Optional, depending on the requirements of the connected systems.
|
||||
map<string, google.protobuf.Any> extensions = 3;
|
||||
|
||||
// Customized information not inspected by Open Match, to be kept persistent
|
||||
// throughout the life-cycle of a backfill.
|
||||
// Optional, depending on the requirements of the connected systems.
|
||||
map<string, google.protobuf.Any> persistent_field = 4;
|
||||
|
||||
// Create time is the time the Ticket was created. It is populated by Open
|
||||
// Match at the time of Ticket creation.
|
||||
google.protobuf.Timestamp create_time = 4;
|
||||
google.protobuf.Timestamp create_time = 5;
|
||||
|
||||
// Generation gets incremented on GameServers update operations.
|
||||
// Prevents the MMF from overriding a newer version from the game server.
|
||||
// Do NOT read or write to this field, it is for internal tracking, and changing the value will cause bugs.
|
||||
int64 generation = 5;
|
||||
int64 generation = 6;
|
||||
}
|
@ -19,9 +19,9 @@ option csharp_namespace = "OpenMatch";
|
||||
|
||||
import "api/messages.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "protoc-gen-swagger/options/annotations.proto";
|
||||
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||
|
||||
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
info: {
|
||||
title: "MM Logic (Data Layer)"
|
||||
version: "1.0"
|
||||
|
@ -13,6 +13,11 @@
|
||||
"url": "https://github.com/googleforgames/open-match/blob/master/LICENSE"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "QueryService"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
@ -26,8 +31,7 @@
|
||||
"paths": {
|
||||
"/v1/queryservice/backfills:query": {
|
||||
"post": {
|
||||
"summary": "QueryBackfills gets a list of Backfills.",
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"summary": "QueryBackfills gets a list of Backfills.\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.",
|
||||
"operationId": "QueryService_QueryBackfills",
|
||||
"responses": {
|
||||
"200": {
|
||||
@ -39,7 +43,7 @@
|
||||
"$ref": "#/definitions/openmatchQueryBackfillsResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of openmatchQueryBackfillsResponse"
|
||||
@ -55,13 +59,14 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"description": "BETA FEATURE WARNING: This Request messages are not finalized and \nstill subject to possible change or removal.",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
@ -88,7 +93,7 @@
|
||||
"$ref": "#/definitions/openmatchQueryTicketIdsResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of openmatchQueryTicketIdsResponse"
|
||||
@ -104,7 +109,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -137,7 +142,7 @@
|
||||
"$ref": "#/definitions/openmatchQueryTicketsResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/runtimeStreamError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of openmatchQueryTicketsResponse"
|
||||
@ -153,7 +158,7 @@
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -218,7 +223,14 @@
|
||||
"additionalProperties": {
|
||||
"$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."
|
||||
"description": "Customized information not inspected by Open Match, to be used by\nthe Match Function, evaluator, and components making calls to Open Match.\nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a backfill. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
@ -228,10 +240,10 @@
|
||||
"generation": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo not read or write to this field, it is for internal tracking and changing the value will cause bugs."
|
||||
"description": "Generation gets incremented on GameServers update operations.\nPrevents the MMF from overriding a newer version from the game server.\nDo NOT read or write to this field, it is for internal tracking, and changing the value will cause bugs."
|
||||
}
|
||||
},
|
||||
"description": "BETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal.\nRepresents a backfill entity which is used to fill partially full matches."
|
||||
"description": "Represents a backfill entity which is used to fill partially full matches.\n\nBETA FEATURE WARNING: This call and the associated Request and Response\nmessages are not finalized and still subject to possible change or removal."
|
||||
},
|
||||
"openmatchDoubleRangeFilter": {
|
||||
"type": "object",
|
||||
@ -252,7 +264,7 @@
|
||||
},
|
||||
"exclude": {
|
||||
"$ref": "#/definitions/DoubleRangeFilterExclude",
|
||||
"description": "Which bounds would be excluded when comparing with a ticket's search_fields.double_args value.\n\nBETA FEATURE WARNING: This field and the associated values are\nnot finalized and still subject to possible change or removal."
|
||||
"description": "Defines the bounds to apply when filtering tickets by their search_fields.double_args value.\nBETA FEATURE WARNING: This field and the associated values are\nnot finalized and still subject to possible change or removal."
|
||||
}
|
||||
},
|
||||
"title": "Filters numerical values to only those within a range.\n double_arg: \"foo\"\n max: 10\n min: 5\nmatches:\n {\"foo\": 5}\n {\"foo\": 7.5}\n {\"foo\": 10}\ndoes not match:\n {\"foo\": 4}\n {\"foo\": 10.01}\n {\"foo\": \"7.5\"}\n {}"
|
||||
@ -267,6 +279,7 @@
|
||||
"double_range_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchDoubleRangeFilter"
|
||||
},
|
||||
"description": "Set of Filters indicating the filtering criteria. Selected tickets must\nmatch every Filter."
|
||||
@ -274,12 +287,14 @@
|
||||
"string_equals_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchStringEqualsFilter"
|
||||
}
|
||||
},
|
||||
"tag_present_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTagPresentFilter"
|
||||
}
|
||||
},
|
||||
@ -312,6 +327,7 @@
|
||||
"backfills": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchBackfill"
|
||||
},
|
||||
"description": "Backfills that meet all the filtering criteria requested by the pool."
|
||||
@ -355,6 +371,7 @@
|
||||
"tickets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/openmatchTicket"
|
||||
},
|
||||
"description": "Tickets that meet all the filtering criteria requested by the pool."
|
||||
@ -433,6 +450,13 @@
|
||||
},
|
||||
"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."
|
||||
},
|
||||
"persistent_field": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
},
|
||||
"description": "Customized information not inspected by Open Match, to be kept persistent \nthroughout the life-cycle of a ticket. \nOptional, depending on the requirements of the connected systems."
|
||||
},
|
||||
"create_time": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
@ -444,63 +468,36 @@
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type_url": {
|
||||
"@type": {
|
||||
"type": "string",
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "Must be a valid serialized protocol buffer of the above specified type."
|
||||
"description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics."
|
||||
}
|
||||
},
|
||||
"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 }"
|
||||
"additionalProperties": {},
|
||||
"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 // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\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 := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(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\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 }"
|
||||
},
|
||||
"runtimeError": {
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int32",
|
||||
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]."
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "A developer-facing error message, which should be in English. Any\nuser-facing error message should be localized and sent in the\n[google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
},
|
||||
"description": "A list of messages that carry the error details. There is a common set of\nmessage types for APIs to use."
|
||||
}
|
||||
}
|
||||
},
|
||||
"runtimeStreamError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"grpc_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"http_code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"http_status": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "The `Status` type defines a logical error model that is suitable for\ndifferent programming environments, including REST APIs and RPC APIs. It is\nused by [gRPC](https://github.com/grpc). Each `Status` message contains\nthree pieces of data: error code, error message, and error details.\n\nYou can find out more about this error model and how to work with it in the\n[API Design Guide](https://cloud.google.com/apis/design/errors)."
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
|
@ -16,15 +16,9 @@
|
||||
# Open Match Script for Google Cloud Build #
|
||||
################################################################################
|
||||
|
||||
# To run this locally:
|
||||
# cloud-build-local --config=cloudbuild.yaml --dryrun=false --substitutions=_OM_VERSION=DEV .
|
||||
# To run this remotely:
|
||||
# example command-line invocation:
|
||||
# gcloud builds submit --config=cloudbuild.yaml --substitutions=_OM_VERSION=DEV .
|
||||
|
||||
# Requires gcloud to be installed to work. (https://cloud.google.com/sdk/)
|
||||
# gcloud auth login
|
||||
# gcloud components install cloud-build-local
|
||||
|
||||
# This YAML contains all the build steps for building Open Match.
|
||||
# All PRs are verified against this script to prevent build breakages and regressions.
|
||||
|
||||
@ -38,8 +32,11 @@
|
||||
# Setup: Read-Write, similar to generate but steps that run before any other step.
|
||||
|
||||
# Some useful things to know about Cloud Build.
|
||||
# The root of this repository is always stored in /workspace.
|
||||
# Any modifications that occur within /workspace are persisted between builds anything else is forgotten.
|
||||
# When your build executes, Cloud Build copies the contents of your repository to /workspace, the default working directory for Cloud Build.
|
||||
# Learn more about working directories on the Build configuration overview page https://cloud.google.com/build/docs/build-config-file-schema
|
||||
# - Modifications that occur within /workspace are persisted between build steps.
|
||||
# - If you want to replicate the build process from this file locally, you'll need to
|
||||
# clone the open match github repo and set HEAD to the commit you're trying to build.
|
||||
# If a build step has intermediate files that need to be persisted for a future step then use volumes.
|
||||
# An example of this is the go-vol which is where the pkg/ data for go mod is stored.
|
||||
# More information here: https://cloud.google.com/cloud-build/docs/build-config#build_steps
|
||||
@ -48,23 +45,31 @@
|
||||
|
||||
steps:
|
||||
- id: 'Docker Image: open-match-build'
|
||||
name: gcr.io/cloud-builders/docker
|
||||
args: ['build', '-t', 'gcr.io/$PROJECT_ID/open-match-build', '-f', 'Dockerfile.ci', '.']
|
||||
name: gcr.io/kaniko-project/executor:latest
|
||||
args: [
|
||||
"--destination=gcr.io/$PROJECT_ID/open-match-build",
|
||||
"--dockerfile=Dockerfile.ci",
|
||||
"--cache=true",
|
||||
"--cache-ttl=3600h",
|
||||
]
|
||||
waitFor: ['-']
|
||||
#name: gcr.io/cloud-builders/docker
|
||||
#args: ['build', '-t', 'gcr.io/$PROJECT_ID/open-match-build', '-f', 'Dockerfile.ci', '.']
|
||||
#waitFor: ['-']
|
||||
|
||||
- id: 'Build: Clean'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'clean-third-party', 'clean-protos', 'clean-swagger-docs']
|
||||
waitFor: ['Docker Image: open-match-build']
|
||||
|
||||
# - id: 'Test: Markdown'
|
||||
# name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
# args: ['make', 'md-test']
|
||||
# waitFor: ['Build: Clean']
|
||||
|
||||
- id: 'Setup: Download Dependencies'
|
||||
- id: 'Test: Markdown'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'sync-deps']
|
||||
args: ['make', 'md-test']
|
||||
waitFor: ['Build: Clean']
|
||||
|
||||
- id: 'Setup: Clean Go Dependencies'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'clean-deps']
|
||||
volumes:
|
||||
- name: 'go-vol'
|
||||
path: '/go'
|
||||
@ -76,17 +81,33 @@ steps:
|
||||
volumes:
|
||||
- name: 'go-vol'
|
||||
path: '/go'
|
||||
waitFor: ['Setup: Download Dependencies']
|
||||
waitFor: ['Setup: Clean Go Dependencies']
|
||||
|
||||
- id: 'Test: Terraform Configuration'
|
||||
- id: 'Build: Compile Protos'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'terraform-test']
|
||||
args: ['make', 'golang-protos']
|
||||
volumes:
|
||||
- name: 'go-vol'
|
||||
path: '/go'
|
||||
waitFor: ['Build: Initialize Toolchain']
|
||||
|
||||
- id: 'Setup: Download Go Dependencies'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'sync-deps']
|
||||
volumes:
|
||||
- name: 'go-vol'
|
||||
path: '/go'
|
||||
waitFor: ['Build: Compile Protos']
|
||||
|
||||
- id: 'Build: Deployment Configs'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'SHORT_SHA=${SHORT_SHA}', 'update-chart-deps', 'install/yaml/']
|
||||
waitFor: ['Build: Initialize Toolchain']
|
||||
waitFor: ['Setup: Download Go Dependencies']
|
||||
|
||||
- id: 'Test: Terraform Configuration'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'terraform-test']
|
||||
waitFor: ['Setup: Download Go Dependencies']
|
||||
|
||||
- id: 'Build: Assets'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
@ -98,7 +119,7 @@ steps:
|
||||
|
||||
- id: 'Build: Binaries'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'GOPROXY=off', 'build', 'all', '-j12']
|
||||
args: ['make', '_CHARTS_BUCKET=${_CHARTS_BUCKET}', 'build', 'all', '-j12']
|
||||
volumes:
|
||||
- name: 'go-vol'
|
||||
path: '/go'
|
||||
@ -106,7 +127,9 @@ steps:
|
||||
|
||||
- id: 'Test: Services'
|
||||
name: 'gcr.io/$PROJECT_ID/open-match-build'
|
||||
args: ['make', 'GOPROXY=off', 'GOLANG_TEST_COUNT=10', 'test']
|
||||
args: ['make', 'GOLANG_TEST_COUNT=3', 'test']
|
||||
# When debugging failing tests, enable verbose 'go test' output, run additional passes
|
||||
#args: ['make', 'GOLANG_EXTRA_TEST_FLAGS=-v', 'GOLANG_TEST_COUNT=10', 'test']
|
||||
volumes:
|
||||
- name: 'go-vol'
|
||||
path: '/go'
|
||||
@ -153,21 +176,19 @@ steps:
|
||||
|
||||
artifacts:
|
||||
objects:
|
||||
location: '${_ARTIFACTS_BUCKET}'
|
||||
location: '${_ARTIFACTS_BUCKET}${_OM_VERSION}'
|
||||
paths:
|
||||
- install/yaml/install.yaml
|
||||
- install/yaml/01-open-match-core.yaml
|
||||
- install/yaml/02-open-match-demo.yaml
|
||||
- install/yaml/03-prometheus-chart.yaml
|
||||
- install/yaml/04-grafana-chart.yaml
|
||||
- install/yaml/05-jaeger-chart.yaml
|
||||
- install/yaml/06-open-match-override-configmap.yaml
|
||||
- install/yaml/*.yaml
|
||||
- pkg/pb/*.pb.go
|
||||
- pkg/pb/*.pb.gw.go
|
||||
- internal/ipb/*.pb.go
|
||||
- api/*.swagger.json
|
||||
|
||||
substitutions:
|
||||
_OM_VERSION: "0.0.0-dev"
|
||||
_OM_VERSION: "1.8.0-rc.1"
|
||||
_GCB_POST_SUBMIT: "0"
|
||||
_GCB_LATEST_VERSION: "undefined"
|
||||
_ARTIFACTS_BUCKET: "gs://open-match-build-artifacts/output/"
|
||||
_ARTIFACTS_BUCKET: "gs://open-match-build-artifacts/"
|
||||
_LOGS_BUCKET: "gs://open-match-build-logs/"
|
||||
_CHARTS_BUCKET: "gs://open-match-chart"
|
||||
logsBucket: '${_LOGS_BUCKET}'
|
||||
|
@ -46,7 +46,7 @@ make
|
||||
|
||||
*Typically for contributing you'll want to
|
||||
[create a fork](https://help.github.com/en/articles/fork-a-repo) and use that
|
||||
but for purpose of this guide we'll be using the upstream/master.*
|
||||
but for purpose of this guide we'll be using the upstream/main.*
|
||||
|
||||
## Building code and images
|
||||
|
||||
|
@ -37,7 +37,7 @@ func New() *ByteSub {
|
||||
}
|
||||
}
|
||||
|
||||
// AnnounceLatest writes b to all of the subscribers, with caviets listed in Subscribe.
|
||||
// AnnounceLatest writes b to all of the subscribers, with caveats listed in Subscribe.
|
||||
func (s *ByteSub) AnnounceLatest(b []byte) {
|
||||
s.r.Lock()
|
||||
defer s.r.Unlock()
|
||||
|
@ -37,7 +37,7 @@ type Updater struct {
|
||||
type SetFunc func(v interface{})
|
||||
|
||||
// New creates an Updater. Set is called when fields update, using the json
|
||||
// sererialized value of Updater's tree. All updates after ctx is canceled are
|
||||
// serialized value of Updater's tree. All updates after ctx is canceled are
|
||||
// ignored.
|
||||
func New(ctx context.Context, set func([]byte)) *Updater {
|
||||
f := func(v interface{}) {
|
||||
|
@ -24,10 +24,10 @@ import (
|
||||
|
||||
"log"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"open-match.dev/open-match/pkg/matchfunction"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
@ -243,7 +243,7 @@ func newBackfill(searchFields *pb.SearchFields, openSlots int) (*pb.Backfill, er
|
||||
b := pb.Backfill{
|
||||
SearchFields: searchFields,
|
||||
Generation: 0,
|
||||
CreateTime: ptypes.TimestampNow(),
|
||||
CreateTime: timestamppb.Now(),
|
||||
}
|
||||
|
||||
err := setOpenSlots(&b, int32(openSlots))
|
||||
@ -254,7 +254,7 @@ func newMatch(num int, profile string, tickets []*pb.Ticket, b *pb.Backfill) pb.
|
||||
t := time.Now().Format("2006-01-02T15:04:05.00")
|
||||
|
||||
return pb.Match{
|
||||
MatchId: fmt.Sprintf("profile-%s-time-%s-num-%d", matchName, t, num),
|
||||
MatchId: fmt.Sprintf("profile-%s-time-%s-num-%d", profile, t, num),
|
||||
MatchProfile: profile,
|
||||
MatchFunction: matchName,
|
||||
Tickets: tickets,
|
||||
@ -264,10 +264,10 @@ func newMatch(num int, profile string, tickets []*pb.Ticket, b *pb.Backfill) pb.
|
||||
|
||||
func setOpenSlots(b *pb.Backfill, val int32) error {
|
||||
if b.Extensions == nil {
|
||||
b.Extensions = make(map[string]*any.Any)
|
||||
b.Extensions = make(map[string]*anypb.Any)
|
||||
}
|
||||
|
||||
any, err := ptypes.MarshalAny(&wrappers.Int32Value{Value: val})
|
||||
any, err := anypb.New(&wrapperspb.Int32Value{Value: val})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -283,8 +283,8 @@ func getOpenSlots(b *pb.Backfill) (int32, error) {
|
||||
|
||||
if b.Extensions != nil {
|
||||
if any, ok := b.Extensions[openSlotsKey]; ok {
|
||||
var val wrappers.Int32Value
|
||||
err := ptypes.UnmarshalAny(any, &val)
|
||||
var val wrapperspb.Int32Value
|
||||
err := any.UnmarshalTo(&val)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@ -16,10 +16,9 @@ package mmf
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
@ -129,13 +128,13 @@ func TestMakeFullMatches(t *testing.T) {
|
||||
}
|
||||
|
||||
func withOpenSlots(openSlots int) *pb.Backfill {
|
||||
val, err := ptypes.MarshalAny(&wrappers.Int32Value{Value: int32(openSlots)})
|
||||
val, err := anypb.New(&wrapperspb.Int32Value{Value: int32(openSlots)})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &pb.Backfill{
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
openSlotsKey: val,
|
||||
},
|
||||
}
|
||||
|
@ -40,16 +40,16 @@ var (
|
||||
|
||||
activeScenario = scenarios.ActiveScenario
|
||||
|
||||
mIterations = telemetry.Counter("scale_backend_iterations", "fetch match iterations")
|
||||
mFetchMatchCalls = telemetry.Counter("scale_backend_fetch_match_calls", "fetch match calls")
|
||||
mFetchMatchSuccesses = telemetry.Counter("scale_backend_fetch_match_successes", "fetch match successes")
|
||||
mFetchMatchErrors = telemetry.Counter("scale_backend_fetch_match_errors", "fetch match errors")
|
||||
mMatchesReturned = telemetry.Counter("scale_backend_matches_returned", "matches returned")
|
||||
mSumTicketsReturned = telemetry.Counter("scale_backend_sum_tickets_returned", "tickets in matches returned")
|
||||
mMatchesAssigned = telemetry.Counter("scale_backend_matches_assigned", "matches assigned")
|
||||
mMatchAssignsFailed = telemetry.Counter("scale_backend_match_assigns_failed", "match assigns failed")
|
||||
mTicketsDeleted = telemetry.Counter("scale_backend_tickets_deleted", "tickets deleted")
|
||||
mTicketDeletesFailed = telemetry.Counter("scale_backend_ticket_deletes_failed", "ticket deletes failed")
|
||||
mIterations = telemetry.Counter("scale_backend_iterations", "fetch match iterations")
|
||||
mFetchMatchCalls = telemetry.Counter("scale_backend_fetch_match_calls", "fetch match calls")
|
||||
mFetchMatchSuccesses = telemetry.Counter("scale_backend_fetch_match_successes", "fetch match successes")
|
||||
mFetchMatchErrors = telemetry.Counter("scale_backend_fetch_match_errors", "fetch match errors")
|
||||
mMatchesReturned = telemetry.Counter("scale_backend_matches_returned", "matches returned")
|
||||
mSumTicketsReturned = telemetry.Counter("scale_backend_sum_tickets_returned", "tickets in matches returned")
|
||||
mMatchesAssigned = telemetry.Counter("scale_backend_matches_assigned", "matches assigned")
|
||||
mMatchAssignsFailed = telemetry.Counter("scale_backend_match_assigns_failed", "match assigns failed")
|
||||
mBackfillsDeleted = telemetry.Counter("scale_backend_backfills_deleted", "backfills deleted")
|
||||
mBackfillDeletesFailed = telemetry.Counter("scale_backend_backfill_deletes_failed", "backfill deletes failed")
|
||||
)
|
||||
|
||||
// Run triggers execution of functions that continuously fetch, assign and
|
||||
@ -79,12 +79,28 @@ func run(cfg config.View) {
|
||||
w := logger.Writer()
|
||||
defer w.Close()
|
||||
|
||||
matchesForAssignment := make(chan *pb.Match, 30000)
|
||||
ticketsForDeletion := make(chan string, 30000)
|
||||
matchesToAssign := make(chan *pb.Match, 30000)
|
||||
|
||||
for i := 0; i < 50; i++ {
|
||||
go runAssignments(be, matchesForAssignment, ticketsForDeletion)
|
||||
go runDeletions(fe, ticketsForDeletion)
|
||||
if activeScenario.BackendAssignsTickets {
|
||||
for i := 0; i < 100; i++ {
|
||||
go runAssignments(be, matchesToAssign)
|
||||
}
|
||||
}
|
||||
|
||||
backfillsToDelete := make(chan *pb.Backfill, 30000)
|
||||
|
||||
if activeScenario.BackendDeletesBackfills {
|
||||
for i := 0; i < 100; i++ {
|
||||
go runDeleteBackfills(fe, backfillsToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
matchesToAcknowledge := make(chan *pb.Match, 30000)
|
||||
|
||||
if activeScenario.BackendAcknowledgesBackfills {
|
||||
for i := 0; i < 100; i++ {
|
||||
go runAcknowledgeBackfills(fe, matchesToAcknowledge, backfillsToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
// Don't go faster than this, as it likely means that FetchMatches is throwing
|
||||
@ -98,7 +114,7 @@ func run(cfg config.View) {
|
||||
wg.Add(1)
|
||||
go func(wg *sync.WaitGroup, p *pb.MatchProfile) {
|
||||
defer wg.Done()
|
||||
runFetchMatches(be, p, matchesForAssignment)
|
||||
runFetchMatches(be, p, matchesToAssign, matchesToAcknowledge)
|
||||
}(&wg, p)
|
||||
}
|
||||
|
||||
@ -108,13 +124,13 @@ func run(cfg config.View) {
|
||||
}
|
||||
}
|
||||
|
||||
func runFetchMatches(be pb.BackendServiceClient, p *pb.MatchProfile, matchesForAssignment chan<- *pb.Match) {
|
||||
func runFetchMatches(be pb.BackendServiceClient, p *pb.MatchProfile, matchesToAssign chan<- *pb.Match, matchesToAcknowledge chan<- *pb.Match) {
|
||||
ctx, span := trace.StartSpan(context.Background(), "scale.backend/FetchMatches")
|
||||
defer span.End()
|
||||
|
||||
req := &pb.FetchMatchesRequest{
|
||||
Config: &pb.FunctionConfig{
|
||||
Host: "om-function",
|
||||
Host: "open-match-function",
|
||||
Port: 50502,
|
||||
Type: pb.FunctionConfig_GRPC,
|
||||
},
|
||||
@ -146,62 +162,90 @@ func runFetchMatches(be pb.BackendServiceClient, p *pb.MatchProfile, matchesForA
|
||||
telemetry.RecordNUnitMeasurement(ctx, mSumTicketsReturned, int64(len(resp.GetMatch().Tickets)))
|
||||
telemetry.RecordUnitMeasurement(ctx, mMatchesReturned)
|
||||
|
||||
matchesForAssignment <- resp.GetMatch()
|
||||
if activeScenario.BackendAssignsTickets {
|
||||
matchesToAssign <- resp.GetMatch()
|
||||
}
|
||||
|
||||
if activeScenario.BackendAcknowledgesBackfills {
|
||||
matchesToAcknowledge <- resp.GetMatch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runAssignments(be pb.BackendServiceClient, matchesForAssignment <-chan *pb.Match, ticketsForDeletion chan<- string) {
|
||||
func runDeleteBackfills(fe pb.FrontendServiceClient, backfillsToDelete <-chan *pb.Backfill) {
|
||||
for b := range backfillsToDelete {
|
||||
if !activeScenario.BackfillDeleteCond(b) {
|
||||
continue
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
_, err := fe.DeleteBackfill(ctx, &pb.DeleteBackfillRequest{BackfillId: b.Id})
|
||||
if err != nil {
|
||||
logger.WithError(err).Errorf("failed to delete backfill: %s", b.Id)
|
||||
telemetry.RecordUnitMeasurement(ctx, mBackfillDeletesFailed)
|
||||
} else {
|
||||
telemetry.RecordUnitMeasurement(ctx, mBackfillsDeleted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runAcknowledgeBackfills(fe pb.FrontendServiceClient, matchesToAcknowledge <-chan *pb.Match, backfillsToDelete chan<- *pb.Backfill) {
|
||||
for m := range matchesToAcknowledge {
|
||||
backfillId := m.Backfill.GetId()
|
||||
if backfillId == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
err := acknowledgeBackfill(fe, backfillId)
|
||||
if err != nil {
|
||||
logger.WithError(err).Errorf("failed to acknowledge backfill: %s", backfillId)
|
||||
continue
|
||||
}
|
||||
|
||||
if activeScenario.BackendDeletesBackfills {
|
||||
backfillsToDelete <- m.Backfill
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func acknowledgeBackfill(fe pb.FrontendServiceClient, backfillId string) error {
|
||||
ctx, span := trace.StartSpan(context.Background(), "scale.frontend/AcknowledgeBackfill")
|
||||
defer span.End()
|
||||
|
||||
_, err := fe.AcknowledgeBackfill(ctx, &pb.AcknowledgeBackfillRequest{
|
||||
BackfillId: backfillId,
|
||||
Assignment: &pb.Assignment{
|
||||
Connection: fmt.Sprintf("%d.%d.%d.%d:2222", rand.Intn(256), rand.Intn(256), rand.Intn(256), rand.Intn(256)),
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func runAssignments(be pb.BackendServiceClient, matchesToAssign <-chan *pb.Match) {
|
||||
ctx := context.Background()
|
||||
|
||||
for m := range matchesForAssignment {
|
||||
for m := range matchesToAssign {
|
||||
ids := []string{}
|
||||
for _, t := range m.Tickets {
|
||||
ids = append(ids, t.GetId())
|
||||
}
|
||||
|
||||
if activeScenario.BackendAssignsTickets {
|
||||
_, err := be.AssignTickets(context.Background(), &pb.AssignTicketsRequest{
|
||||
Assignments: []*pb.AssignmentGroup{
|
||||
{
|
||||
TicketIds: ids,
|
||||
Assignment: &pb.Assignment{
|
||||
Connection: fmt.Sprintf("%d.%d.%d.%d:2222", rand.Intn(256), rand.Intn(256), rand.Intn(256), rand.Intn(256)),
|
||||
},
|
||||
_, err := be.AssignTickets(context.Background(), &pb.AssignTicketsRequest{
|
||||
Assignments: []*pb.AssignmentGroup{
|
||||
{
|
||||
TicketIds: ids,
|
||||
Assignment: &pb.Assignment{
|
||||
Connection: fmt.Sprintf("%d.%d.%d.%d:2222", rand.Intn(256), rand.Intn(256), rand.Intn(256), rand.Intn(256)),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
telemetry.RecordUnitMeasurement(ctx, mMatchAssignsFailed)
|
||||
logger.WithError(err).Error("failed to assign tickets")
|
||||
continue
|
||||
}
|
||||
|
||||
telemetry.RecordUnitMeasurement(ctx, mMatchesAssigned)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
telemetry.RecordUnitMeasurement(ctx, mMatchAssignsFailed)
|
||||
logger.WithError(err).Error("failed to assign tickets")
|
||||
continue
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
ticketsForDeletion <- id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runDeletions(fe pb.FrontendServiceClient, ticketsForDeletion <-chan string) {
|
||||
ctx := context.Background()
|
||||
|
||||
for id := range ticketsForDeletion {
|
||||
if activeScenario.BackendDeletesTickets {
|
||||
req := &pb.DeleteTicketRequest{
|
||||
TicketId: id,
|
||||
}
|
||||
|
||||
_, err := fe.DeleteTicket(context.Background(), req)
|
||||
|
||||
if err == nil {
|
||||
telemetry.RecordUnitMeasurement(ctx, mTicketsDeleted)
|
||||
} else {
|
||||
telemetry.RecordUnitMeasurement(ctx, mTicketDeletesFailed)
|
||||
logger.WithError(err).Error("failed to delete tickets")
|
||||
}
|
||||
}
|
||||
telemetry.RecordUnitMeasurement(ctx, mMatchesAssigned)
|
||||
}
|
||||
}
|
||||
|
@ -38,12 +38,22 @@ var (
|
||||
})
|
||||
activeScenario = scenarios.ActiveScenario
|
||||
|
||||
mTicketsCreated = telemetry.Counter("scale_frontend_tickets_created", "tickets created")
|
||||
mTicketCreationsFailed = telemetry.Counter("scale_frontend_ticket_creations_failed", "tickets created")
|
||||
mRunnersWaiting = concurrentGauge(telemetry.Gauge("scale_frontend_runners_waiting", "runners waiting"))
|
||||
mRunnersCreating = concurrentGauge(telemetry.Gauge("scale_frontend_runners_creating", "runners creating"))
|
||||
mTicketsCreated = telemetry.Counter("scale_frontend_tickets_created", "tickets created")
|
||||
mTicketCreationsFailed = telemetry.Counter("scale_frontend_ticket_creations_failed", "tickets created")
|
||||
mRunnersWaiting = concurrentGauge(telemetry.Gauge("scale_frontend_runners_waiting", "runners waiting"))
|
||||
mRunnersCreating = concurrentGauge(telemetry.Gauge("scale_frontend_runners_creating", "runners creating"))
|
||||
mTicketsDeleted = telemetry.Counter("scale_frontend_tickets_deleted", "tickets deleted")
|
||||
mTicketDeletesFailed = telemetry.Counter("scale_frontend_ticket_deletes_failed", "ticket deletes failed")
|
||||
mBackfillsCreated = telemetry.Counter("scale_frontend_backfills_created", "backfills_created")
|
||||
mBackfillCreationsFailed = telemetry.Counter("scale_frontend_backfill_creations_failed", "backfill creations failed")
|
||||
mTicketsTimeToAssignment = telemetry.HistogramWithBounds("scale_frontend_tickets_time_to_assignment", "tickets time to assignment", stats.UnitMilliseconds, []float64{0.01, 0.05, 0.1, 0.3, 0.6, 0.8, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000})
|
||||
)
|
||||
|
||||
type ticketToWatch struct {
|
||||
id string
|
||||
createdAt time.Time
|
||||
}
|
||||
|
||||
// Run triggers execution of the scale frontend component that creates
|
||||
// tickets at scale in Open Match.
|
||||
func BindService(p *appmain.Params, b *appmain.Bindings) error {
|
||||
@ -61,9 +71,12 @@ func run(cfg config.View) {
|
||||
}
|
||||
fe := pb.NewFrontendServiceClient(conn)
|
||||
|
||||
if activeScenario.FrontendCreatesBackfillsOnStart {
|
||||
createBackfills(fe, activeScenario.FrontendTotalBackfillsToCreate)
|
||||
}
|
||||
|
||||
ticketQPS := int(activeScenario.FrontendTicketCreatedQPS)
|
||||
ticketTotal := activeScenario.FrontendTotalTicketsToCreate
|
||||
|
||||
totalCreated := 0
|
||||
|
||||
for range time.Tick(time.Second) {
|
||||
@ -89,13 +102,27 @@ func runner(fe pb.FrontendServiceClient) {
|
||||
time.Sleep(time.Duration(rand.Int63n(int64(time.Second))))
|
||||
|
||||
g.start(mRunnersCreating)
|
||||
createdAt := time.Now()
|
||||
id, err := createTicket(ctx, fe)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("failed to create a ticket")
|
||||
return
|
||||
}
|
||||
|
||||
_ = id
|
||||
err = watchAssignments(ctx, fe, ticketToWatch{id: id, createdAt: createdAt})
|
||||
if err != nil {
|
||||
logger.WithError(err).Errorf("failed to get ticket assignment: %s", id)
|
||||
} else {
|
||||
ms := time.Since(createdAt).Nanoseconds() / 1e6
|
||||
stats.Record(ctx, mTicketsTimeToAssignment.M(ms))
|
||||
}
|
||||
|
||||
if activeScenario.FrontendDeletesTickets {
|
||||
err = deleteTicket(ctx, fe, id)
|
||||
if err != nil {
|
||||
logger.WithError(err).Errorf("failed to delete ticket: %s", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createTicket(ctx context.Context, fe pb.FrontendServiceClient) (string, error) {
|
||||
@ -116,6 +143,68 @@ func createTicket(ctx context.Context, fe pb.FrontendServiceClient) (string, err
|
||||
return resp.Id, nil
|
||||
}
|
||||
|
||||
func watchAssignments(ctx context.Context, fe pb.FrontendServiceClient, ticket ticketToWatch) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
stream, err := fe.WatchAssignments(ctx, &pb.WatchAssignmentsRequest{TicketId: ticket.id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var a *pb.Assignment
|
||||
for a.GetConnection() == "" {
|
||||
resp, err := stream.Recv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a = resp.Assignment
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createBackfills(fe pb.FrontendServiceClient, numBackfillsToCreate int) error {
|
||||
for i := 0; i < numBackfillsToCreate; i++ {
|
||||
err := createBackfill(fe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createBackfill(fe pb.FrontendServiceClient) error {
|
||||
ctx, span := trace.StartSpan(context.Background(), "scale.frontend/CreateBackfill")
|
||||
defer span.End()
|
||||
|
||||
req := pb.CreateBackfillRequest{
|
||||
Backfill: activeScenario.Backfill(),
|
||||
}
|
||||
|
||||
_, err := fe.CreateBackfill(ctx, &req)
|
||||
if err != nil {
|
||||
telemetry.RecordUnitMeasurement(ctx, mBackfillCreationsFailed)
|
||||
logger.WithError(err).Error("failed to create backfill")
|
||||
return err
|
||||
}
|
||||
|
||||
telemetry.RecordUnitMeasurement(ctx, mBackfillsCreated)
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteTicket(ctx context.Context, fe pb.FrontendServiceClient, ticketId string) error {
|
||||
_, err := fe.DeleteTicket(ctx, &pb.DeleteTicketRequest{TicketId: ticketId})
|
||||
if err != nil {
|
||||
telemetry.RecordUnitMeasurement(ctx, mTicketDeletesFailed)
|
||||
} else {
|
||||
telemetry.RecordUnitMeasurement(ctx, mTicketsDeleted)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Allows concurrent moficiation of a gauge value by modifying the concurrent
|
||||
// value with a delta.
|
||||
func concurrentGauge(s *stats.Int64Measure) func(delta int64) {
|
||||
|
270
examples/scale/scenarios/backfill/backfill.go
Normal file
270
examples/scale/scenarios/backfill/backfill.go
Normal file
@ -0,0 +1,270 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package backfill
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
const (
|
||||
poolName = "all"
|
||||
openSlotsKey = "open-slots"
|
||||
)
|
||||
|
||||
func Scenario() *BackfillScenario {
|
||||
ticketsPerMatch := 4
|
||||
return &BackfillScenario{
|
||||
TicketsPerMatch: ticketsPerMatch,
|
||||
MaxTicketsPerNotFullMatch: 3,
|
||||
BackfillDeleteCond: func(b *pb.Backfill) bool {
|
||||
openSlots := getOpenSlots(b, ticketsPerMatch)
|
||||
return openSlots <= 0
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type BackfillScenario struct {
|
||||
TicketsPerMatch int
|
||||
MaxTicketsPerNotFullMatch int
|
||||
BackfillDeleteCond func(*pb.Backfill) bool
|
||||
}
|
||||
|
||||
func (s *BackfillScenario) Profiles() []*pb.MatchProfile {
|
||||
return []*pb.MatchProfile{
|
||||
{
|
||||
Name: "entirePool",
|
||||
Pools: []*pb.Pool{
|
||||
{
|
||||
Name: poolName,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BackfillScenario) Ticket() *pb.Ticket {
|
||||
return &pb.Ticket{}
|
||||
}
|
||||
|
||||
func (s *BackfillScenario) Backfill() *pb.Backfill {
|
||||
return &pb.Backfill{}
|
||||
}
|
||||
|
||||
func (s *BackfillScenario) MatchFunction(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
|
||||
return statefullMMF(p, poolBackfills, poolTickets, s.TicketsPerMatch, s.MaxTicketsPerNotFullMatch)
|
||||
}
|
||||
|
||||
// statefullMMF is a MMF implementation which is used in scenario when we want MMF to create not full match and fill it later.
|
||||
// 1. The first FetchMatches is called
|
||||
// 2. MMF grabs maxTicketsPerNotFullMatch tickets and makes a match and new backfill for it
|
||||
// 3. MMF sets backfill's open slots to ticketsPerMatch - maxTicketsPerNotFullMatch
|
||||
// 4. MMF returns the match as a result
|
||||
// 5. The second FetchMatches is called
|
||||
// 6. MMF gets previously created backfill
|
||||
// 7. MMF gets backfill's open slots value
|
||||
// 8. MMF grabs openSlots tickets and makes a match with previously created backfill
|
||||
// 9. MMF sets backfill's open slots to 0
|
||||
// 10. MMF returns the match as a result
|
||||
func statefullMMF(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket, ticketsPerMatch int, maxTicketsPerNotFullMatch int) ([]*pb.Match, error) {
|
||||
var matches []*pb.Match
|
||||
|
||||
for pool, backfills := range poolBackfills {
|
||||
tickets, ok := poolTickets[pool]
|
||||
|
||||
if !ok || len(tickets) == 0 {
|
||||
// no tickets in pool
|
||||
continue
|
||||
}
|
||||
|
||||
// process backfills first
|
||||
for _, b := range backfills {
|
||||
l := len(tickets)
|
||||
if l == 0 {
|
||||
// no tickets left
|
||||
break
|
||||
}
|
||||
|
||||
openSlots := getOpenSlots(b, ticketsPerMatch)
|
||||
if openSlots <= 0 {
|
||||
// no free open slots
|
||||
continue
|
||||
}
|
||||
|
||||
if l > openSlots {
|
||||
l = openSlots
|
||||
}
|
||||
|
||||
setOpenSlots(b, openSlots-l)
|
||||
matches = append(matches, &pb.Match{
|
||||
MatchId: fmt.Sprintf("profile-%v-time-%v-%v", p.GetName(), time.Now().Format("2006-01-02T15:04:05.00"), len(matches)),
|
||||
Tickets: tickets[0:l],
|
||||
MatchProfile: p.GetName(),
|
||||
MatchFunction: "backfill",
|
||||
Backfill: b,
|
||||
})
|
||||
tickets = tickets[l:]
|
||||
}
|
||||
|
||||
// create not full matches with backfill
|
||||
for {
|
||||
l := len(tickets)
|
||||
if l == 0 {
|
||||
// no tickets left
|
||||
break
|
||||
}
|
||||
|
||||
if l > maxTicketsPerNotFullMatch {
|
||||
l = maxTicketsPerNotFullMatch
|
||||
}
|
||||
b := pb.Backfill{}
|
||||
setOpenSlots(&b, ticketsPerMatch-l)
|
||||
matches = append(matches, &pb.Match{
|
||||
MatchId: fmt.Sprintf("profile-%v-time-%v-%v", p.GetName(), time.Now().Format("2006-01-02T15:04:05.00"), len(matches)),
|
||||
Tickets: tickets[0:l],
|
||||
MatchProfile: p.GetName(),
|
||||
MatchFunction: "backfill",
|
||||
Backfill: &b,
|
||||
AllocateGameserver: true,
|
||||
})
|
||||
tickets = tickets[l:]
|
||||
}
|
||||
}
|
||||
|
||||
return matches, nil
|
||||
}
|
||||
|
||||
func getOpenSlots(b *pb.Backfill, defaultVal int) int {
|
||||
if b.Extensions == nil {
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
any, ok := b.Extensions[openSlotsKey]
|
||||
if !ok {
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
var val wrapperspb.Int32Value
|
||||
err := any.UnmarshalTo(&val)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return int(val.Value)
|
||||
}
|
||||
|
||||
func setOpenSlots(b *pb.Backfill, val int) {
|
||||
if b.Extensions == nil {
|
||||
b.Extensions = make(map[string]*anypb.Any)
|
||||
}
|
||||
|
||||
any, err := anypb.New(&wrapperspb.Int32Value{Value: int32(val)})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
b.Extensions[openSlotsKey] = any
|
||||
}
|
||||
|
||||
// statelessMMF is a MMF implementation which is used in scenario when we want MMF to fill backfills created by a Gameserver. It doesn't create
|
||||
// or update any backfill.
|
||||
// 1. FetchMatches is called
|
||||
// 2. MMF gets a backfill
|
||||
// 3. MMF grabs ticketsPerMatch tickets and makes a match with the backfill
|
||||
// 4. MMF returns the match as a result
|
||||
func statelessMMF(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket, ticketsPerMatch int) ([]*pb.Match, error) {
|
||||
var matches []*pb.Match
|
||||
|
||||
for pool, backfills := range poolBackfills {
|
||||
tickets, ok := poolTickets[pool]
|
||||
|
||||
if !ok || len(tickets) == 0 {
|
||||
// no tickets in pool
|
||||
continue
|
||||
}
|
||||
|
||||
for _, b := range backfills {
|
||||
l := len(tickets)
|
||||
if l == 0 {
|
||||
// no tickets left
|
||||
break
|
||||
}
|
||||
|
||||
if l > ticketsPerMatch && ticketsPerMatch > 0 {
|
||||
l = ticketsPerMatch
|
||||
}
|
||||
|
||||
matches = append(matches, &pb.Match{
|
||||
MatchId: fmt.Sprintf("profile-%v-time-%v-%v", p.GetName(), time.Now().Format("2006-01-02T15:04:05.00"), len(matches)),
|
||||
Tickets: tickets[0:l],
|
||||
MatchProfile: p.GetName(),
|
||||
MatchFunction: "backfill",
|
||||
Backfill: b,
|
||||
})
|
||||
tickets = tickets[l:]
|
||||
}
|
||||
}
|
||||
|
||||
return matches, nil
|
||||
}
|
||||
|
||||
func (s *BackfillScenario) Evaluate(stream pb.Evaluator_EvaluateServer) error {
|
||||
tickets := map[string]struct{}{}
|
||||
backfills := map[string]struct{}{}
|
||||
matchIds := []string{}
|
||||
|
||||
outer:
|
||||
for {
|
||||
req, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read evaluator input stream: %w", err)
|
||||
}
|
||||
|
||||
m := req.GetMatch()
|
||||
|
||||
if _, ok := backfills[m.Backfill.Id]; ok {
|
||||
continue outer
|
||||
}
|
||||
|
||||
for _, t := range m.Tickets {
|
||||
if _, ok := tickets[t.Id]; ok {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
|
||||
for _, t := range m.Tickets {
|
||||
tickets[t.Id] = struct{}{}
|
||||
}
|
||||
|
||||
matchIds = append(matchIds, m.GetMatchId())
|
||||
}
|
||||
|
||||
for _, id := range matchIds {
|
||||
err := stream.Send(&pb.EvaluateResponse{MatchId: id})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to sending evaluator output stream: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -78,7 +78,11 @@ func (b *BattleRoyalScenario) Ticket() *pb.Ticket {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BattleRoyalScenario) MatchFunction(p *pb.MatchProfile, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
|
||||
func (b *BattleRoyalScenario) Backfill() *pb.Backfill {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BattleRoyalScenario) MatchFunction(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
|
||||
const playersInMatch = 100
|
||||
|
||||
tickets := poolTickets[poolName]
|
||||
|
@ -33,7 +33,7 @@ func Scenario() *FirstMatchScenario {
|
||||
type FirstMatchScenario struct {
|
||||
}
|
||||
|
||||
func (_ *FirstMatchScenario) Profiles() []*pb.MatchProfile {
|
||||
func (*FirstMatchScenario) Profiles() []*pb.MatchProfile {
|
||||
return []*pb.MatchProfile{
|
||||
{
|
||||
Name: "entirePool",
|
||||
@ -46,11 +46,15 @@ func (_ *FirstMatchScenario) Profiles() []*pb.MatchProfile {
|
||||
}
|
||||
}
|
||||
|
||||
func (_ *FirstMatchScenario) Ticket() *pb.Ticket {
|
||||
func (*FirstMatchScenario) Ticket() *pb.Ticket {
|
||||
return &pb.Ticket{}
|
||||
}
|
||||
|
||||
func (_ *FirstMatchScenario) MatchFunction(p *pb.MatchProfile, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
|
||||
func (*FirstMatchScenario) Backfill() *pb.Backfill {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*FirstMatchScenario) MatchFunction(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
|
||||
tickets := poolTickets[poolName]
|
||||
var matches []*pb.Match
|
||||
|
||||
@ -68,7 +72,7 @@ func (_ *FirstMatchScenario) MatchFunction(p *pb.MatchProfile, poolTickets map[s
|
||||
|
||||
// fifoEvaluate accepts all matches which don't contain the same ticket as in a
|
||||
// previously accepted match. Essentially first to claim the ticket wins.
|
||||
func (_ *FirstMatchScenario) Evaluate(stream pb.Evaluator_EvaluateServer) error {
|
||||
func (*FirstMatchScenario) Evaluate(stream pb.Evaluator_EvaluateServer) error {
|
||||
used := map[string]struct{}{}
|
||||
|
||||
// TODO: once the evaluator client supports sending and receiving at the
|
||||
|
@ -19,9 +19,8 @@ import (
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"open-match.dev/open-match/examples/scale/scenarios/battleroyal"
|
||||
"open-match.dev/open-match/examples/scale/scenarios/backfill"
|
||||
"open-match.dev/open-match/examples/scale/scenarios/firstmatch"
|
||||
"open-match.dev/open-match/examples/scale/scenarios/teamshooter"
|
||||
"open-match.dev/open-match/internal/util/testing"
|
||||
"open-match.dev/open-match/pkg/matchfunction"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
@ -40,11 +39,14 @@ type GameScenario interface {
|
||||
// Ticket creates a new ticket, with randomized parameters.
|
||||
Ticket() *pb.Ticket
|
||||
|
||||
// Backfill creates a new backfill, with randomized parameters.
|
||||
Backfill() *pb.Backfill
|
||||
|
||||
// Profiles lists all of the profiles that should run.
|
||||
Profiles() []*pb.MatchProfile
|
||||
|
||||
// MatchFunction is the custom logic implementation of the match function.
|
||||
MatchFunction(p *pb.MatchProfile, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error)
|
||||
MatchFunction(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error)
|
||||
|
||||
// Evaluate is the custom logic implementation of the evaluator.
|
||||
Evaluate(stream pb.Evaluator_EvaluateServer) error
|
||||
@ -56,18 +58,26 @@ var ActiveScenario = func() *Scenario {
|
||||
|
||||
// TODO: Select which scenario to use based on some configuration or choice,
|
||||
// so it's easier to run different scenarios without changing code.
|
||||
gs = battleroyal.Scenario()
|
||||
gs = teamshooter.Scenario()
|
||||
//gs = battleroyal.Scenario()
|
||||
//gs = teamshooter.Scenario()
|
||||
s := backfill.Scenario()
|
||||
gs = s
|
||||
|
||||
return &Scenario{
|
||||
FrontendTotalTicketsToCreate: -1,
|
||||
FrontendTicketCreatedQPS: 100,
|
||||
FrontendTotalTicketsToCreate: -1,
|
||||
FrontendTicketCreatedQPS: 100,
|
||||
FrontendCreatesBackfillsOnStart: true,
|
||||
FrontendTotalBackfillsToCreate: 1000,
|
||||
FrontendDeletesTickets: true,
|
||||
|
||||
BackendAssignsTickets: true,
|
||||
BackendDeletesTickets: true,
|
||||
BackendAssignsTickets: false,
|
||||
BackendAcknowledgesBackfills: true,
|
||||
BackendDeletesBackfills: true,
|
||||
|
||||
Ticket: gs.Ticket,
|
||||
Profiles: gs.Profiles,
|
||||
Ticket: gs.Ticket,
|
||||
Backfill: gs.Backfill,
|
||||
BackfillDeleteCond: s.BackfillDeleteCond,
|
||||
Profiles: gs.Profiles,
|
||||
|
||||
MMF: queryPoolsWrapper(gs.MatchFunction),
|
||||
Evaluator: gs.Evaluate,
|
||||
@ -87,17 +97,23 @@ type Scenario struct {
|
||||
// TicketExtensionSize int
|
||||
// PendingTicketNumber int
|
||||
// MatchExtensionSize int
|
||||
FrontendTotalTicketsToCreate int // TotalTicketsToCreate = -1 let scale-frontend create tickets forever
|
||||
FrontendTicketCreatedQPS uint32
|
||||
FrontendTicketCreatedQPS uint32
|
||||
FrontendTotalTicketsToCreate int // TotalTicketsToCreate = -1 let scale-frontend create tickets forever
|
||||
FrontendTotalBackfillsToCreate int
|
||||
FrontendCreatesBackfillsOnStart bool
|
||||
FrontendDeletesTickets bool
|
||||
|
||||
// GameBackend Configs
|
||||
// ProfileNumber int
|
||||
// FilterNumber int
|
||||
BackendAssignsTickets bool
|
||||
BackendDeletesTickets bool
|
||||
BackendAssignsTickets bool
|
||||
BackendAcknowledgesBackfills bool
|
||||
BackendDeletesBackfills bool
|
||||
|
||||
Ticket func() *pb.Ticket
|
||||
Profiles func() []*pb.MatchProfile
|
||||
Ticket func() *pb.Ticket
|
||||
Backfill func() *pb.Backfill
|
||||
BackfillDeleteCond func(*pb.Backfill) bool
|
||||
Profiles func() []*pb.MatchProfile
|
||||
|
||||
MMF matchFunction
|
||||
Evaluator evaluatorFunction
|
||||
@ -122,7 +138,7 @@ func getQueryServiceGRPCClient() pb.QueryServiceClient {
|
||||
return pb.NewQueryServiceClient(conn)
|
||||
}
|
||||
|
||||
func queryPoolsWrapper(mmf func(req *pb.MatchProfile, pools map[string][]*pb.Ticket) ([]*pb.Match, error)) matchFunction {
|
||||
func queryPoolsWrapper(mmf func(req *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error)) matchFunction {
|
||||
var q pb.QueryServiceClient
|
||||
var startQ sync.Once
|
||||
|
||||
@ -136,7 +152,12 @@ func queryPoolsWrapper(mmf func(req *pb.MatchProfile, pools map[string][]*pb.Tic
|
||||
return err
|
||||
}
|
||||
|
||||
proposals, err := mmf(req.GetProfile(), poolTickets)
|
||||
poolBackfills, err := matchfunction.QueryBackfillPools(stream.Context(), q, req.GetProfile().GetPools())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
proposals, err := mmf(req.GetProfile(), poolBackfills, poolTickets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -18,10 +18,13 @@
|
||||
// arguments used:
|
||||
// mode: The game mode the players wants to play in. mode is a hard partition.
|
||||
// regions: Players may have good latency to one or more regions. A player will
|
||||
// search for matches in all eligible regions.
|
||||
//
|
||||
// search for matches in all eligible regions.
|
||||
//
|
||||
// skill: Players have a random skill based on a normal distribution. Players
|
||||
// will only be matched with other players who have a close skill value. The
|
||||
// match functions have overlapping partitions of the skill brackets.
|
||||
//
|
||||
// will only be matched with other players who have a close skill value. The
|
||||
// match functions have overlapping partitions of the skill brackets.
|
||||
package teamshooter
|
||||
|
||||
import (
|
||||
@ -32,9 +35,8 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
@ -154,9 +156,13 @@ func (t *TeamShooterScenario) Ticket() *pb.Ticket {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TeamShooterScenario) Backfill() *pb.Backfill {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MatchFunction puts tickets into matches based on their skill, finding the
|
||||
// required number of tickets for a game within the maximum skill difference.
|
||||
func (t *TeamShooterScenario) MatchFunction(p *pb.MatchProfile, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
|
||||
func (t *TeamShooterScenario) MatchFunction(p *pb.MatchProfile, poolBackfills map[string][]*pb.Backfill, poolTickets map[string][]*pb.Ticket) ([]*pb.Match, error) {
|
||||
skill := func(t *pb.Ticket) float64 {
|
||||
return t.SearchFields.DoubleArgs[skillArg]
|
||||
}
|
||||
@ -261,9 +267,9 @@ type matchExt struct {
|
||||
}
|
||||
|
||||
func unpackMatch(m *pb.Match) (*matchExt, error) {
|
||||
v := &wrappers.DoubleValue{}
|
||||
v := &wrapperspb.DoubleValue{}
|
||||
|
||||
err := ptypes.UnmarshalAny(m.Extensions["quality"], v)
|
||||
err := m.Extensions["quality"].UnmarshalTo(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error unpacking match quality: %w", err)
|
||||
}
|
||||
@ -278,9 +284,9 @@ func unpackMatch(m *pb.Match) (*matchExt, error) {
|
||||
}
|
||||
|
||||
func (m *matchExt) pack() (*pb.Match, error) {
|
||||
v := &wrappers.DoubleValue{Value: m.quality}
|
||||
v := &wrapperspb.DoubleValue{Value: m.quality}
|
||||
|
||||
a, err := ptypes.MarshalAny(v)
|
||||
a, err := anypb.New(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error packing match quality: %w", err)
|
||||
}
|
||||
@ -290,7 +296,7 @@ func (m *matchExt) pack() (*pb.Match, error) {
|
||||
Tickets: m.tickets,
|
||||
MatchProfile: m.matchProfile,
|
||||
MatchFunction: m.matchFunction,
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"quality": a,
|
||||
},
|
||||
}, nil
|
||||
|
146
go.mod
146
go.mod
@ -15,52 +15,124 @@ module open-match.dev/open-match
|
||||
// limitations under the License.
|
||||
|
||||
// When updating Go version, update Dockerfile.ci, Dockerfile.base-build, and go.mod
|
||||
go 1.14
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
contrib.go.opencensus.io/exporter/jaeger v0.2.1
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.7.0
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.2.0
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.4
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.4.2
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.14
|
||||
github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb
|
||||
github.com/TV4/logrus-stackdriver-formatter v0.1.0
|
||||
github.com/alicebob/miniredis/v2 v2.14.1
|
||||
github.com/aws/aws-sdk-go v1.35.26 // indirect
|
||||
github.com/alicebob/miniredis/v2 v2.30.5
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/go-redsync/redsync/v4 v4.0.3
|
||||
github.com/gogo/protobuf v1.3.1 // indirect
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/go-redsync/redsync/v4 v4.8.1
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/gomodule/redigo v2.0.1-0.20191111085604-09d84710e01a+incompatible
|
||||
github.com/googleapis/gnostic v0.3.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
github.com/pelletier/go-toml v1.8.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.8.0
|
||||
github.com/rs/xid v1.2.1
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/spf13/afero v1.4.1 // indirect
|
||||
github.com/prometheus/client_golang v1.16.0
|
||||
github.com/rs/xid v1.5.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.opencensus.io v0.24.0
|
||||
golang.org/x/net v0.14.0
|
||||
golang.org/x/sync v0.3.0
|
||||
google.golang.org/genproto v0.0.0-20230815205213-6bfd019c3878 // indirect
|
||||
google.golang.org/grpc v1.57.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
k8s.io/api v0.28.0 // kubernetes-1.14.10
|
||||
k8s.io/apimachinery v0.28.0
|
||||
k8s.io/client-go v0.28.0
|
||||
)
|
||||
|
||||
require (
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230815205213-6bfd019c3878
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.23.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/monitoring v1.15.1 // indirect
|
||||
cloud.google.com/go/trace v1.10.1 // indirect
|
||||
github.com/Masterminds/semver v1.4.2 // indirect
|
||||
github.com/Masterminds/sprig v2.15.0+incompatible // indirect
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect
|
||||
github.com/aokoli/goutils v1.0.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.324 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/s2a-go v0.1.5 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
github.com/prometheus/prometheus v0.46.0 // indirect
|
||||
github.com/prometheus/statsd_exporter v0.24.0 // indirect
|
||||
github.com/pseudomuto/protoc-gen-doc v1.5.1 // indirect
|
||||
github.com/pseudomuto/protokit v0.2.0 // indirect
|
||||
github.com/spf13/afero v1.9.5 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/stretchr/testify v1.6.1
|
||||
go.opencensus.io v0.22.5
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
||||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd // indirect
|
||||
golang.org/x/text v0.3.4 // indirect
|
||||
google.golang.org/api v0.35.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20201112120144-2985b7af83de
|
||||
google.golang.org/grpc v1.33.2
|
||||
google.golang.org/protobuf v1.25.0
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/yuin/gopher-lua v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.12.0 // indirect
|
||||
golang.org/x/oauth2 v0.11.0 // indirect
|
||||
golang.org/x/sys v0.11.0 // indirect
|
||||
golang.org/x/term v0.11.0 // indirect
|
||||
golang.org/x/text v0.12.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
google.golang.org/api v0.137.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/api v0.0.0-20191004102349-159aefb8556b // kubernetes-1.14.10
|
||||
k8s.io/apimachinery v0.0.0-20191004074956-c5d2f014d689 // kubernetes-1.14.10
|
||||
k8s.io/client-go v11.0.1-0.20191029005444-8e4128053008+incompatible // kubernetes-1.14.10
|
||||
k8s.io/klog v1.0.0 // indirect
|
||||
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 // indirect
|
||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/klog/v2 v2.100.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230811205723-7ac0aad8c58d // indirect
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
@ -5,7 +5,7 @@ Templates under the `templates/` directory are for the core components in Open M
|
||||
|
||||
Open Match also provides templates for optional components that are disabled by default under the `subcharts/` directory.
|
||||
1. `open-match-customize` contains flexible templates to deploy your own matchfunction and evaluator.
|
||||
2. `open-match-telemetry` contains monitoring supports for Open Match, you may choose to enable/disable [jaeger](https://www.jaegertracing.io/ "jaeger"), [prometheus](http://prometheus.io "prometheus"), [stackdriver](https://cloud.google.com/stackdriver/ "stackdriver"), and [grafana](https://grafana.com/ "grafana") by overriding the config values in the provided templates.
|
||||
2. `open-match-telemetry` contains monitoring supports for Open Match, you may choose to enable/disable [prometheus](http://prometheus.io "prometheus"), [stackdriver](https://cloud.google.com/stackdriver/ "stackdriver"), and [grafana](https://grafana.com/ "grafana") by overriding the config values in the provided templates.
|
||||
|
||||
You may control the behavior of Open Match by overriding the configs in `install/helm/open-match/values.yaml` file. Here are a few examples:
|
||||
|
||||
@ -26,7 +26,7 @@ swaggerui:
|
||||
global:
|
||||
kubernetes:
|
||||
service:
|
||||
- portType: ClusterIP
|
||||
- portType: ClusterIP
|
||||
+ portType: LoadBalancer
|
||||
|
||||
# Enables grafana support in Open Match
|
||||
|
@ -13,12 +13,12 @@
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: v2
|
||||
appVersion: "0.0.0-dev"
|
||||
version: 0.0.0-dev
|
||||
appVersion: "1.8.0-rc.1"
|
||||
version: 1.8.0-rc.1
|
||||
name: open-match
|
||||
dependencies:
|
||||
- name: redis
|
||||
version: 12.3.3
|
||||
version: 17.15.4
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
condition: open-match-core.redis.enabled
|
||||
- name: open-match-telemetry
|
||||
|
@ -54,7 +54,7 @@ spec:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "openmatch.evaluator.hostName" . }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.spec.common" . | nindent 2 }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.evaluator.spec.common" . | nindent 2 }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
@ -54,7 +54,7 @@ spec:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "openmatchcustomize.function.hostName" . }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.spec.common" . | nindent 2 }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.matchfunction.spec.common" . | nindent 2 }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
@ -18,13 +18,15 @@
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 16,
|
||||
"id": 28,
|
||||
"panels": [],
|
||||
"title": "Iterations",
|
||||
"type": "row"
|
||||
},
|
||||
@ -130,11 +132,317 @@
|
||||
"x": 0,
|
||||
"y": 9
|
||||
},
|
||||
"id": 16,
|
||||
"panels": [],
|
||||
"title": "Backfills",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"fill": 1,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 10
|
||||
},
|
||||
"id": 30,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(scale_backend_backfills_deleted[5m]))",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Backfilld Deleted per second",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(scale_backend_backfill_deletes_failed[5m]))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Backfill Deletions Failed per second",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Backfill Deletion",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": "0",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 18
|
||||
},
|
||||
"id": 14,
|
||||
"panels": [],
|
||||
"title": "Tickets",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"fill": 0,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 19
|
||||
},
|
||||
"id": 26,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": true,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": true
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(scale_frontend_tickets_time_to_assignment_bucket[5m])) by (le))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "99%-ile",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(scale_frontend_tickets_time_to_assignment_bucket[5m])) by (le))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "95%-ile",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.90, sum(rate(scale_frontend_tickets_time_to_assignment_bucket[5m])) by (le))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "90%-ile",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(scale_frontend_tickets_time_to_assignment_bucket[5m])) by (le))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "50%-ile",
|
||||
"refId": "D"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.10, sum(rate(scale_frontend_tickets_time_to_assignment_bucket[5m])) by (le))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "10%-ile",
|
||||
"refId": "E"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Ticket Time to Assignment",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "ms",
|
||||
"label": null,
|
||||
"logBase": 2,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"fill": 1,
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 19
|
||||
},
|
||||
"id": 12,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(scale_backend_sum_tickets_returned[5m]))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Backend Tickets in Matches pers second",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Tickets In Matches",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": "0",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
@ -146,7 +454,7 @@
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 10
|
||||
"y": 27
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
@ -242,12 +550,12 @@
|
||||
"dashes": false,
|
||||
"fill": 1,
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 10
|
||||
"y": 28
|
||||
},
|
||||
"id": 12,
|
||||
"id": 22,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
@ -272,18 +580,26 @@
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(scale_backend_sum_tickets_returned[5m]))",
|
||||
"expr": "sum(rate(scale_frontend_tickets_deleted[5m]))",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Backend Tickets Deleted per second",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(scale_frontend_ticket_deletes_failed[5m]))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Backend Tickets in Matches pers second",
|
||||
"refId": "A"
|
||||
"legendFormat": "Backend Ticket Deletions Failed per second",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Tickets In Matches",
|
||||
"title": "Ticket Deletion",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
@ -331,7 +647,7 @@
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 19
|
||||
"y": 36
|
||||
},
|
||||
"id": 24,
|
||||
"legend": {
|
||||
@ -414,106 +730,13 @@
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"fill": 1,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 19
|
||||
},
|
||||
"id": 22,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"options": {},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(scale_backend_tickets_deleted[5m]))",
|
||||
"format": "time_series",
|
||||
"interval": "",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Backend Tickets Deleted per second",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "sum(rate(scale_backend_ticket_deletes_failed[5m]))",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "Backend Ticket Deletions Failed per second",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Ticket Deletion",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": "0",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 27
|
||||
"y": 44
|
||||
},
|
||||
"id": 18,
|
||||
"panels": [],
|
||||
@ -530,7 +753,7 @@
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 28
|
||||
"y": 45
|
||||
},
|
||||
"id": 6,
|
||||
"legend": {
|
||||
@ -616,7 +839,7 @@
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 28
|
||||
"y": 45
|
||||
},
|
||||
"id": 19,
|
||||
"legend": {
|
||||
@ -705,7 +928,7 @@
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 36
|
||||
"y": 53
|
||||
},
|
||||
"id": 21,
|
||||
"panels": [],
|
||||
@ -722,7 +945,7 @@
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 37
|
||||
"y": 54
|
||||
},
|
||||
"id": 8,
|
||||
"legend": {
|
||||
@ -807,7 +1030,7 @@
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 37
|
||||
"y": 54
|
||||
},
|
||||
"id": 10,
|
||||
"legend": {
|
||||
@ -890,7 +1113,7 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
"refresh": "10s",
|
||||
"schemaVersion": 18,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
|
@ -31,7 +31,7 @@ spec:
|
||||
protocol: TCP
|
||||
port: {{ .Values.scaleFrontend.httpPort }}
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "openmatchscale.scaleFrontend.hostName" . }}
|
||||
|
@ -19,15 +19,10 @@ name: open-match-telemetry
|
||||
version: 0.0.0-dev
|
||||
dependencies:
|
||||
- name: prometheus
|
||||
version: 9.2.0
|
||||
repository: https://charts.helm.sh/stable
|
||||
version: 15.8.7
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
condition: global.telemetry.prometheus.enabled,prometheus.enabled
|
||||
- name: grafana
|
||||
version: 4.0.1
|
||||
repository: https://charts.helm.sh/stable
|
||||
version: 6.29.3
|
||||
repository: https://grafana.github.io/helm-charts
|
||||
condition: global.telemetry.grafana.enabled,grafana.enabled
|
||||
- name: jaeger
|
||||
version: 0.13.3
|
||||
repository: https://charts.helm.sh/stable
|
||||
condition: global.telemetry.jaeger.enabled,jaeger.enabled
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -13,12 +13,20 @@
|
||||
# limitations under the License.
|
||||
|
||||
{{- if .Values.global.telemetry.grafana.enabled }}
|
||||
{{- $om := (include "openmatch.fullname" .) }}
|
||||
{{ $c := 1 | int }}
|
||||
{{- range $path, $bytes := .Files.Glob "dashboards/*.json" }}
|
||||
{{- $ext := ext $path }}
|
||||
{{- $file := base $path }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "openmatch.fullname" . }}-dashboards
|
||||
name: {{ printf "%s-%s-dashboard" $om ((printf "%s" $file) | replace $ext "") }}
|
||||
labels:
|
||||
grafana_dashboard: "1"
|
||||
grafana_dashboard: {{ printf "d-%d" $c }}
|
||||
data:
|
||||
{{- (.Files.Glob "dashboards/*.json").AsConfig | nindent 2 }}
|
||||
{{- ($.Files.Glob (printf "dashboards/%s" $file)).AsConfig | nindent 2 }}
|
||||
---
|
||||
{{ $c = add1 $c }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
@ -146,23 +146,3 @@ grafana:
|
||||
datasources:
|
||||
enabled: true
|
||||
plugins: grafana-piechart-panel
|
||||
|
||||
jaeger:
|
||||
enabled: true
|
||||
# Configs for the cassandra schema job
|
||||
schema:
|
||||
pullPolicy: Always
|
||||
mode: prod
|
||||
activeDeadlineSeconds: 200
|
||||
cassandra:
|
||||
image:
|
||||
tag: latest
|
||||
config:
|
||||
cluster_size: 2
|
||||
resources:
|
||||
requests:
|
||||
memory: 4Gi
|
||||
cpu: 2
|
||||
limits:
|
||||
memory: 4Gi
|
||||
cpu: 2
|
||||
|
@ -102,17 +102,17 @@ resources:
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.volumemounts.withredis" -}}
|
||||
{{- if .Values.redis.usePassword }}
|
||||
{{- if .Values.redis.auth.enabled }}
|
||||
- name: redis-password
|
||||
mountPath: {{ .Values.redis.secretMountPath }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.volumes.withredis" -}}
|
||||
{{- if .Values.redis.usePassword }}
|
||||
{{- if .Values.redis.auth.enabled }}
|
||||
- name: redis-password
|
||||
secret:
|
||||
secretName: {{ include "call-nested" (list . "redis" "redis.fullname") }}
|
||||
secretName: {{ include "call-nested" (list . "redis" "common.names.fullname") }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
@ -150,16 +150,46 @@ readinessProbe:
|
||||
failureThreshold: 2
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.HorizontalPodAutoscaler.spec.common" -}}
|
||||
minReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.minReplicas }}
|
||||
maxReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.maxReplicas }}
|
||||
targetCPUUtilizationPercentage: {{ .Values.global.kubernetes.horizontalPodAutoScaler.targetCPUUtilizationPercentage }}
|
||||
{{- define "openmatch.HorizontalPodAutoscaler.frontend.spec.common" -}}
|
||||
minReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.frontend.minReplicas }}
|
||||
maxReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.frontend.maxReplicas }}
|
||||
targetCPUUtilizationPercentage: {{ .Values.global.kubernetes.horizontalPodAutoScaler.frontend.targetCPUUtilizationPercentage }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.HorizontalPodAutoscaler.backend.spec.common" -}}
|
||||
minReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.backend.minReplicas }}
|
||||
maxReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.backend.maxReplicas }}
|
||||
targetCPUUtilizationPercentage: {{ .Values.global.kubernetes.horizontalPodAutoScaler.backend.targetCPUUtilizationPercentage }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.HorizontalPodAutoscaler.query.spec.common" -}}
|
||||
minReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.query.minReplicas }}
|
||||
maxReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.query.maxReplicas }}
|
||||
targetCPUUtilizationPercentage: {{ .Values.global.kubernetes.horizontalPodAutoScaler.query.targetCPUUtilizationPercentage }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.HorizontalPodAutoscaler.evaluator.spec.common" -}}
|
||||
minReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.evaluator.minReplicas }}
|
||||
maxReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.evaluator.maxReplicas }}
|
||||
targetCPUUtilizationPercentage: {{ .Values.global.kubernetes.horizontalPodAutoScaler.evaluator.targetCPUUtilizationPercentage }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.HorizontalPodAutoscaler.matchfunction.spec.common" -}}
|
||||
minReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.matchfunction.minReplicas }}
|
||||
maxReplicas: {{ .Values.global.kubernetes.horizontalPodAutoScaler.matchfunction.maxReplicas }}
|
||||
targetCPUUtilizationPercentage: {{ .Values.global.kubernetes.horizontalPodAutoScaler.matchfunction.targetCPUUtilizationPercentage }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.serviceAccount.name" -}}
|
||||
{{- .Values.global.kubernetes.serviceAccount | default (printf "%s-unprivileged-service" (include "openmatch.fullname" . ) ) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.serviceAccountAnnotations" -}}
|
||||
{{- if .Values.global.kubernetes.serviceAccountAnnotations -}}
|
||||
{{- toYaml (.Values.global.kubernetes.serviceAccountAnnotations) | nindent 4 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.swaggerui.hostName" -}}
|
||||
{{- .Values.swaggerui.hostName | default (printf "%s-swaggerui" (include "openmatch.fullname" . ) ) -}}
|
||||
{{- end -}}
|
||||
@ -192,25 +222,9 @@ targetCPUUtilizationPercentage: {{ .Values.global.kubernetes.horizontalPodAutoSc
|
||||
{{- printf "%s-configmap-override" (include "openmatch.fullname" . ) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.jaeger.agent" -}}
|
||||
{{- if index .Values "open-match-telemetry" "enabled" -}}
|
||||
{{- if index .Values "open-match-telemetry" "jaeger" "enabled" -}}
|
||||
{{ include "call-nested" (list . "open-match-telemetry.jaeger" "jaeger.agent.name") }}:6831
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "openmatch.jaeger.collector" -}}
|
||||
{{- if index .Values "open-match-telemetry" "enabled" -}}
|
||||
{{- if index .Values "open-match-telemetry" "jaeger" "enabled" -}}
|
||||
http://{{ include "call-nested" (list . "open-match-telemetry.jaeger" "jaeger.collector.name") }}:14268/api/traces
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Call templates from sub-charts in a synthesized context, workaround for https://github.com/helm/helm/issues/3920
|
||||
Mainly useful for things like `{{ include "call-nested" (list . "redis" "redis.fullname") }}`
|
||||
Mainly useful for things like `{{ include "call-nested" (list . "redis" "common.names.fullname") }}`
|
||||
https://github.com/helm/helm/issues/4535#issuecomment-416022809
|
||||
https://github.com/helm/helm/issues/4535#issuecomment-477778391
|
||||
*/}}
|
||||
@ -223,4 +237,4 @@ https://github.com/helm/helm/issues/4535#issuecomment-477778391
|
||||
{{- $values = index $values . }}
|
||||
{{- end }}
|
||||
{{- include $template (dict "Chart" (dict "Name" (last $subchart)) "Values" $values "Release" $dot.Release "Capabilities" $dot.Capabilities) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
@ -51,7 +51,7 @@ spec:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "openmatch.backend.hostName" . }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.spec.common" . | nindent 2 }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.backend.spec.common" . | nindent 2 }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
@ -51,7 +51,7 @@ spec:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "openmatch.frontend.hostName" . }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.spec.common" . | nindent 2 }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.frontend.spec.common" . | nindent 2 }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
@ -26,7 +26,11 @@ metadata:
|
||||
data:
|
||||
matchmaker_config_default.yaml: |-
|
||||
logging:
|
||||
{{- if .Values.global.logging.level }}
|
||||
level: {{ .Values.global.logging.level }}
|
||||
{{- else }}
|
||||
level: debug
|
||||
{{- end }}
|
||||
{{- if .Values.global.telemetry.stackdriverMetrics.enabled }}
|
||||
format: stackdriver
|
||||
{{- else }}
|
||||
@ -90,13 +94,25 @@ data:
|
||||
{{- if index .Values "redis" "sentinel" "enabled"}}
|
||||
sentinelPort: {{ .Values.redis.sentinel.port }}
|
||||
sentinelMaster: {{ .Values.redis.sentinel.masterSet }}
|
||||
sentinelHostname: {{ include "call-nested" (list . "redis" "redis.fullname") }}
|
||||
sentinelHostname: {{ include "call-nested" (list . "redis" "common.names.fullname") }}
|
||||
sentinelUsePassword: {{ .Values.redis.sentinel.usePassword }}
|
||||
{{- else}}
|
||||
# Open Match's default Redis setups
|
||||
hostname: {{ include "call-nested" (list . "redis" "redis.fullname") }}-master.{{ .Release.Namespace }}.svc.cluster.local
|
||||
hostname: {{ include "call-nested" (list . "redis" "common.names.fullname") }}-master.{{ .Release.Namespace }}.svc.cluster.local
|
||||
{{- if .Values.redis.redisPort }}
|
||||
# source value: redis.redisPort = {{ .Values.redis.redisPort }}
|
||||
port: {{ .Values.redis.redisPort }}
|
||||
{{- else if index .Values "open-match-core" "redis" "port" }}
|
||||
# source value: open-match-core.redis.port = {{ index .Values "open-match-core" "redis" "port"}}
|
||||
port: {{ index .Values "open-match-core" "redis" "port" }}
|
||||
{{- end }}
|
||||
{{- if .Values.redis.user }}
|
||||
# source value: redis.user = {{ .Values.redis.user }}
|
||||
user: {{ .Values.redis.user }}
|
||||
{{- else if index .Values "open-match-core" "redis" "user" }}
|
||||
# source value: open-match-core.redis.user = {{ index .Values "open-match-core" "redis" "user"}}
|
||||
user: {{ index .Values "open-match-core" "redis" "user"}}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
{{- else }}
|
||||
# BYO Redis setups
|
||||
@ -104,7 +120,7 @@ data:
|
||||
port: {{ index .Values "open-match-core" "redis" "port" }}
|
||||
user: {{ index .Values "open-match-core" "redis" "user" }}
|
||||
{{- end }}
|
||||
usePassword: {{ .Values.redis.usePassword }}
|
||||
usePassword: {{ .Values.redis.auth.enabled }}
|
||||
passwordPath: {{ .Values.redis.secretMountPath }}/redis-password
|
||||
pool:
|
||||
maxIdle: {{ index .Values "open-match-core" "redis" "pool" "maxIdle" }}
|
||||
@ -117,15 +133,6 @@ data:
|
||||
traceSamplingFraction: "{{ .Values.global.telemetry.traceSamplingFraction }}"
|
||||
zpages:
|
||||
enable: "{{ .Values.global.telemetry.zpages.enabled }}"
|
||||
jaeger:
|
||||
enable: "{{ .Values.global.telemetry.jaeger.enabled }}"
|
||||
{{- if .Values.global.telemetry.jaeger.enabled }}
|
||||
agentEndpoint: "{{ tpl .Values.global.telemetry.jaeger.agentEndpoint . }}"
|
||||
collectorEndpoint: "{{ tpl .Values.global.telemetry.jaeger.collectorEndpoint . }}"
|
||||
{{- else }}
|
||||
agentEndpoint: ""
|
||||
collectorEndpoint: ""
|
||||
{{- end }}
|
||||
prometheus:
|
||||
enable: "{{ .Values.global.telemetry.prometheus.enabled }}"
|
||||
endpoint: "{{ .Values.global.telemetry.prometheus.endpoint }}"
|
||||
|
@ -12,7 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
{{- if index .Values "open-match-override" }}
|
||||
{{- if index .Values "open-match-override" "enabled" }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
|
@ -1,140 +0,0 @@
|
||||
# Copyright 2019 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
{{- if index .Values "open-match-core" "enabled" }}
|
||||
{{- if empty .Values.ci }}
|
||||
# This is the least restricted PSP used to create privileged pods to disable THP in host kernel.
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: {{ include "openmatch.fullname" . }}-redis-podsecuritypolicy
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations:
|
||||
{{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
privileged: true
|
||||
allowPrivilegeEscalation: true
|
||||
allowedCapabilities:
|
||||
- '*'
|
||||
volumes:
|
||||
- '*'
|
||||
hostNetwork: true
|
||||
hostPorts:
|
||||
# Redis
|
||||
- min: 6379
|
||||
max: 6379
|
||||
- min: 9121
|
||||
max: 9121
|
||||
hostIPC: true
|
||||
hostPID: true
|
||||
runAsUser:
|
||||
rule: 'RunAsAny'
|
||||
seLinux:
|
||||
rule: 'RunAsAny'
|
||||
supplementalGroups:
|
||||
rule: 'RunAsAny'
|
||||
fsGroup:
|
||||
rule: 'RunAsAny'
|
||||
---
|
||||
# This does not allow creating privileged pods and restrict binded pods to use the specified port ranges.
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: {{ include "openmatch.fullname" . }}-core-podsecuritypolicy
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations: {{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
allowPrivilegeEscalation: false
|
||||
defaultAllowPrivilegeEscalation: false
|
||||
forbiddenSysctls:
|
||||
- "*"
|
||||
fsGroup:
|
||||
rule: "MustRunAs"
|
||||
ranges:
|
||||
- min: 1
|
||||
max: 65535
|
||||
hostIPC: false
|
||||
hostNetwork: false
|
||||
hostPID: false
|
||||
hostPorts:
|
||||
# Open Match Services
|
||||
- min: 50500
|
||||
max: 50510
|
||||
- min: 51500
|
||||
max: 51510
|
||||
# Cassandra
|
||||
- min: 7000
|
||||
max: 7001
|
||||
- min: 7199
|
||||
max: 7199
|
||||
- min: 9042
|
||||
max: 9042
|
||||
- min: 9160
|
||||
max: 9160
|
||||
# Grafana
|
||||
- min: 3000
|
||||
max: 3000
|
||||
# Jaeger
|
||||
- min: 5775
|
||||
max: 5778
|
||||
- min: 6831
|
||||
max: 6832
|
||||
- min: 14267
|
||||
max: 14268
|
||||
- min: 9411
|
||||
max: 9411
|
||||
- min: 16686
|
||||
max: 16686
|
||||
# Prometheus
|
||||
- min: 9090
|
||||
max: 9093
|
||||
- min: 9100
|
||||
max: 9100
|
||||
- min: 8080
|
||||
max: 8080
|
||||
privileged: false # Prevents creation of privileged Pods
|
||||
readOnlyRootFilesystem: false
|
||||
# Capabilities Reference: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
|
||||
# TODO: Open Match itself doesn't need any capabilties but its dependencies do. We should split out the service accounts later.
|
||||
allowedCapabilities:
|
||||
- CHOWN
|
||||
#requiredDropCapabilities:
|
||||
#- ALL
|
||||
runAsUser:
|
||||
rule: "RunAsAny"
|
||||
# Blocked on isolating the open match services from dependencies (Redis, Prometheus, etc.)
|
||||
# Require the container to run without root privileges.
|
||||
#rule: 'MustRunAsNonRoot'
|
||||
seLinux:
|
||||
# This policy assumes the nodes are using AppArmor rather than SELinux.
|
||||
rule: 'RunAsAny'
|
||||
supplementalGroups:
|
||||
rule: RunAsAny
|
||||
volumes:
|
||||
- 'configMap'
|
||||
- 'emptyDir'
|
||||
- 'projected'
|
||||
- 'secret'
|
||||
- 'downwardAPI'
|
||||
# Assume that persistentVolumes set up by the cluster admin are safe to use.
|
||||
- 'persistentVolumeClaim'
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -51,7 +51,7 @@ spec:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "openmatch.query.hostName" . }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.spec.common" . | nindent 2 }}
|
||||
{{- include "openmatch.HorizontalPodAutoscaler.query.spec.common" . | nindent 2 }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
|
@ -23,6 +23,8 @@ metadata:
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
pod-security.kubernetes.io/enforce: baseline
|
||||
pod-security.kubernetes.io/warn: baseline
|
||||
{{- end }}
|
||||
---
|
||||
# Create a universal service account for open-match-core services.
|
||||
@ -31,85 +33,12 @@ kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "openmatch.serviceAccount.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations: {{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
{{- include "openmatch.serviceAccountAnnotations" . }}
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
automountServiceAccountToken: true
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "openmatch.fullname" . }}-service-role
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations: {{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
- {{ include "openmatch.fullname" . }}-core-podsecuritypolicy
|
||||
verbs:
|
||||
- use
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "openmatch.fullname" . }}-service-role-binding
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations: {{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
subjects:
|
||||
- kind: Group
|
||||
name: system:authenticated # All authenticated users
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: {{ include "openmatch.fullname" . }}-service-role
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
{{- if index .Values "open-match-core" "redis" "enabled" }}
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "openmatch.fullname" . }}-redis-role
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations: {{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
- {{ include "openmatch.fullname" . }}-redis-podsecuritypolicy
|
||||
verbs:
|
||||
- use
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "openmatch.fullname" . }}-redis-role-binding
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations: {{- include "openmatch.chartmeta" . | nindent 4 }}
|
||||
labels:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "call-nested" (list . "redis" "redis.serviceAccountName") }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: {{ include "openmatch.fullname" . }}-redis-role
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
@ -24,14 +24,6 @@ metadata:
|
||||
app: {{ template "openmatch.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
- {{ include "openmatch.fullname" . }}-core-podsecuritypolicy
|
||||
verbs:
|
||||
- use
|
||||
# Grant this role get & list permission for k8s endpoints and pods resources
|
||||
# Required for e2e in-cluster testing.
|
||||
- apiGroups:
|
||||
|
@ -91,7 +91,7 @@ spec:
|
||||
command: ["go"]
|
||||
args:
|
||||
- "test"
|
||||
- "./internal/testing/e2e"
|
||||
- "./testing/e2e"
|
||||
- "-v"
|
||||
- "-timeout"
|
||||
- "150s"
|
||||
|
@ -106,17 +106,12 @@ configs:
|
||||
# https://hub.helm.sh/charts/stable/redis
|
||||
# https://github.com/helm/charts/tree/master/stable/redis
|
||||
redis:
|
||||
redisPort: 6379
|
||||
usePassword: false
|
||||
usePasswordFile: false
|
||||
secretMountPath: /opt/bitnami/redis/secrets
|
||||
architecture: standalone
|
||||
auth:
|
||||
enabled: false
|
||||
configmap: |
|
||||
maxclients 100000
|
||||
maxmemory 500000000
|
||||
sentinel:
|
||||
enabled: true
|
||||
masterSet: om-redis-master
|
||||
port: 26379
|
||||
master:
|
||||
disableCommands: [] # don't disable 'FLUSH-' commands
|
||||
resources:
|
||||
@ -130,20 +125,6 @@ redis:
|
||||
enabled: false
|
||||
metrics:
|
||||
enabled: true
|
||||
cluster:
|
||||
slaveCount: 3
|
||||
serviceAccount:
|
||||
create: true
|
||||
slave:
|
||||
persistence:
|
||||
enabled: false
|
||||
resources:
|
||||
requests:
|
||||
memory: 1Gi
|
||||
cpu: 1
|
||||
limits:
|
||||
memory: 2Gi
|
||||
cpu: 2
|
||||
sysctlImage:
|
||||
# Enable this setting in production if you are running Open Match under Linux environment
|
||||
enabled: true
|
||||
@ -228,6 +209,10 @@ open-match-customize:
|
||||
# function:
|
||||
# image: [YOUR_MMF_IMAGE]
|
||||
|
||||
# Controls if users need to install open-match-override ConfigMap.
|
||||
open-match-override:
|
||||
enabled: false
|
||||
|
||||
# Global configurations that are visible to all subcharts
|
||||
global:
|
||||
kubernetes:
|
||||
@ -238,9 +223,26 @@ global:
|
||||
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
affinity: {}
|
||||
horizontalPodAutoScaler:
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 60
|
||||
frontend:
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 60
|
||||
backend:
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 60
|
||||
query:
|
||||
minReplicas: 5
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 60
|
||||
evaluator:
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 60
|
||||
matchfunction:
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 60
|
||||
resources:
|
||||
requests:
|
||||
memory: 1.5Gi
|
||||
@ -250,6 +252,8 @@ global:
|
||||
cpu: 2
|
||||
# Overrides the name of the service account which provides an identity for processes that run in a Pod in Open Match.
|
||||
serviceAccount:
|
||||
# Adds custom annotations to the Open Match service account.
|
||||
serviceAccountAnnotations: {}
|
||||
# Use this field if you need to override the port type for all services defined in this chart
|
||||
service:
|
||||
portType:
|
||||
@ -282,10 +286,6 @@ global:
|
||||
traceSamplingFraction: 0.005 # What fraction of traces to sample.
|
||||
zpages:
|
||||
enabled: true
|
||||
jaeger:
|
||||
enabled: false
|
||||
agentEndpoint: '{{ include "openmatch.jaeger.agent" . }}'
|
||||
collectorEndpoint: '{{ include "openmatch.jaeger.collector" . }}'
|
||||
prometheus:
|
||||
enabled: false
|
||||
endpoint: "/metrics"
|
||||
|
@ -103,39 +103,38 @@ configs:
|
||||
configName: '{{ include "openmatch.configmap.override" . }}'
|
||||
|
||||
# Override Redis settings
|
||||
# https://hub.helm.sh/charts/stable/redis
|
||||
# https://github.com/helm/charts/tree/master/stable/redis
|
||||
# https://github.com/bitnami/charts/tree/ba40e46ec6831e039f5bf213ab10e9748603ce6c/bitnami/redis
|
||||
redis:
|
||||
redisPort: 6379
|
||||
usePassword: false
|
||||
usePasswordFile: false
|
||||
secretMountPath: /opt/bitnami/redis/secrets
|
||||
configmap: |
|
||||
architecture: standalone
|
||||
auth:
|
||||
enabled: false
|
||||
commonConfiguration: |
|
||||
maxclients 100000
|
||||
maxmemory 300000000
|
||||
sentinel:
|
||||
enabled: true
|
||||
masterSet: om-redis-master
|
||||
port: 26379
|
||||
master:
|
||||
disableCommands: [] # don't disable 'FLUSH-' commands
|
||||
persistence:
|
||||
enabled: false
|
||||
resources:
|
||||
requests:
|
||||
memory: 300Mi
|
||||
cpu: 0.5
|
||||
replica:
|
||||
disableCommands: [] # don't disable 'FLUSH-' commands
|
||||
replicaCount: 3
|
||||
resources:
|
||||
requests:
|
||||
memory: 300Mi
|
||||
cpu: 0.5
|
||||
metrics:
|
||||
enabled: true
|
||||
cluster:
|
||||
slaveCount: 2
|
||||
serviceAccount:
|
||||
create: true
|
||||
sysctlImage:
|
||||
# Enable this setting in production if you are running Open Match under Linux environment
|
||||
enabled: false
|
||||
# Disable this setting in production if you are not running Redis in Linux
|
||||
enabled: true
|
||||
mountHostSys: true
|
||||
# Redis may require some changes in the kernel of the host machine to work as expected,
|
||||
# in particular increasing the somaxconn value and disabling transparent huge pages.
|
||||
# https://github.com/helm/charts/tree/master/stable/redis#host-kernel-settings
|
||||
# https://docs.bitnami.com/kubernetes/infrastructure/redis/administration/configure-kernel-settings/
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
@ -213,6 +212,10 @@ open-match-customize:
|
||||
# function:
|
||||
# image: [YOUR_MMF_IMAGE]
|
||||
|
||||
# Controls if users need to install open-match-override ConfigMap.
|
||||
open-match-override:
|
||||
enabled: false
|
||||
|
||||
# Global configurations that are visible to all subcharts
|
||||
global:
|
||||
kubernetes:
|
||||
@ -223,9 +226,26 @@ global:
|
||||
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
affinity: {}
|
||||
horizontalPodAutoScaler:
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
frontend:
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
backend:
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
query:
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
evaluator:
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
matchfunction:
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 80
|
||||
resources:
|
||||
requests:
|
||||
memory: 100Mi
|
||||
@ -235,6 +255,8 @@ global:
|
||||
cpu: 100m
|
||||
# Overrides the name of the service account which provides an identity for processes that run in a Pod in Open Match.
|
||||
serviceAccount:
|
||||
# Adds custom annotations to the Open Match service account.
|
||||
serviceAccountAnnotations: {}
|
||||
# Use this field if you need to override the port type for all services defined in this chart
|
||||
service:
|
||||
portType:
|
||||
@ -256,7 +278,7 @@ global:
|
||||
# Use this field if you need to override the image registry and image tag for all services defined in this chart
|
||||
image:
|
||||
registry: gcr.io/open-match-public-images
|
||||
tag: 0.0.0-dev
|
||||
tag: 1.8.0-rc.1
|
||||
pullPolicy: Always
|
||||
|
||||
# Expose the telemetry configurations to all subcharts because prometheus, for example,
|
||||
@ -267,10 +289,6 @@ global:
|
||||
traceSamplingFraction: 0.01 # What fraction of traces to sample.
|
||||
zpages:
|
||||
enabled: true
|
||||
jaeger:
|
||||
enabled: false
|
||||
agentEndpoint: '{{ include "openmatch.jaeger.agent" . }}'
|
||||
collectorEndpoint: '{{ include "openmatch.jaeger.collector" . }}'
|
||||
prometheus:
|
||||
enabled: false
|
||||
endpoint: "/metrics"
|
||||
|
@ -27,7 +27,6 @@ admissionWhitelistPatterns:
|
||||
- namePattern: docker.io/bitnami/redis:*
|
||||
- namePattern: docker.io/oliver006/redis_exporter:*
|
||||
- namePattern: registry.hub.docker.com/grafana/*
|
||||
- namePattern: registry.hub.docker.com/jaegertracing/*
|
||||
- namePattern: registry.hub.docker.com/jimmidyson/configmap-reload:*
|
||||
- namePattern: registry.hub.docker.com/kiwigrid/k8s-sidecar:*
|
||||
- namePattern: registry.hub.docker.com/prom/*
|
||||
|
@ -96,11 +96,6 @@ resource "google_container_cluster" "ci_cluster" {
|
||||
identity_namespace = "${var.gcp_project_id}.svc.id.goog"
|
||||
}
|
||||
|
||||
# Enable PodSecurityPolicy
|
||||
pod_security_policy_config {
|
||||
enabled = "true"
|
||||
}
|
||||
|
||||
node_config {
|
||||
oauth_scopes = [
|
||||
"https://www.googleapis.com/auth/devstorage.read_only",
|
||||
|
@ -27,8 +27,6 @@ import (
|
||||
"go.opencensus.io/stats"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/xid"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -36,6 +34,8 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"open-match.dev/open-match/internal/appmain/contextcause"
|
||||
"open-match.dev/open-match/internal/ipb"
|
||||
"open-match.dev/open-match/internal/rpc"
|
||||
@ -279,6 +279,8 @@ func callHTTPMmf(ctx context.Context, cc *rpc.ClientCache, profile *pb.MatchProf
|
||||
if err != nil {
|
||||
return status.Errorf(codes.FailedPrecondition, "failed to create mmf http request for profile %s: %s", profile.GetName(), err.Error())
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Transfer-Encoding", "chunked")
|
||||
|
||||
resp, err := client.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
@ -369,7 +371,7 @@ func (s *backendService) AssignTickets(ctx context.Context, req *pb.AssignTicket
|
||||
func createOrUpdateBackfill(ctx context.Context, backfill *pb.Backfill, ticketIds []string, store statestore.Service) error {
|
||||
if backfill.Id == "" {
|
||||
backfill.Id = xid.New().String()
|
||||
backfill.CreateTime = ptypes.TimestampNow()
|
||||
backfill.CreateTime = timestamppb.Now()
|
||||
backfill.Generation = 1
|
||||
err := store.CreateBackfill(ctx, backfill, ticketIds)
|
||||
if err != nil {
|
||||
@ -386,7 +388,7 @@ func createOrUpdateBackfill(ctx context.Context, backfill *pb.Backfill, ticketId
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_, unlockErr := m.Unlock(ctx)
|
||||
_, unlockErr := m.Unlock(context.Background())
|
||||
if unlockErr != nil {
|
||||
logger.WithFields(logrus.Fields{"backfill_id": backfill.Id}).WithError(unlockErr).Error("failed to make unlock")
|
||||
}
|
||||
@ -459,10 +461,7 @@ func recordTimeToAssignment(ctx context.Context, ticket *pb.Ticket) error {
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
created, err := ptypes.Timestamp(ticket.CreateTime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
created := ticket.CreateTime.AsTime()
|
||||
|
||||
stats.Record(ctx, ticketsTimeToAssignment.M(now.Sub(created).Milliseconds()))
|
||||
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"go.opencensus.io/stats"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/stats/view"
|
||||
"open-match.dev/open-match/internal/app/evaluator"
|
||||
@ -73,7 +72,7 @@ func evaluate(ctx context.Context, in <-chan *pb.Match, out chan<- string) error
|
||||
}
|
||||
|
||||
if a, ok := m.Extensions["evaluation_input"]; ok {
|
||||
err := ptypes.UnmarshalAny(a, inp)
|
||||
err := a.UnmarshalTo(inp)
|
||||
if err != nil {
|
||||
logger.WithFields(logrus.Fields{
|
||||
"match_id": m.MatchId,
|
||||
|
@ -18,15 +18,14 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
func mustAny(m proto.Message) *any.Any {
|
||||
result, err := ptypes.MarshalAny(m)
|
||||
func mustAny(m proto.Message) *anypb.Any {
|
||||
result, err := anypb.New(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -44,7 +43,7 @@ func TestEvaluate(t *testing.T) {
|
||||
ticket12Score1 := &pb.Match{
|
||||
MatchId: "ticket12Score1",
|
||||
Tickets: []*pb.Ticket{ticket1, ticket2},
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 1,
|
||||
}),
|
||||
@ -54,7 +53,7 @@ func TestEvaluate(t *testing.T) {
|
||||
ticket12Score10 := &pb.Match{
|
||||
MatchId: "ticket12Score10",
|
||||
Tickets: []*pb.Ticket{ticket2, ticket1},
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 10,
|
||||
}),
|
||||
@ -64,7 +63,7 @@ func TestEvaluate(t *testing.T) {
|
||||
ticket123Score5 := &pb.Match{
|
||||
MatchId: "ticket123Score5",
|
||||
Tickets: []*pb.Ticket{ticket1, ticket2, ticket3},
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 5,
|
||||
}),
|
||||
@ -74,7 +73,7 @@ func TestEvaluate(t *testing.T) {
|
||||
ticket3Score50 := &pb.Match{
|
||||
MatchId: "ticket3Score50",
|
||||
Tickets: []*pb.Ticket{ticket3},
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 50,
|
||||
}),
|
||||
@ -85,7 +84,7 @@ func TestEvaluate(t *testing.T) {
|
||||
MatchId: "ticket1Backfill0Score1",
|
||||
Tickets: []*pb.Ticket{ticket1},
|
||||
Backfill: backfill0,
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 1,
|
||||
}),
|
||||
@ -96,7 +95,7 @@ func TestEvaluate(t *testing.T) {
|
||||
MatchId: "ticket2Backfill0Score1",
|
||||
Tickets: []*pb.Ticket{ticket2},
|
||||
Backfill: backfill0,
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 1,
|
||||
}),
|
||||
@ -107,7 +106,7 @@ func TestEvaluate(t *testing.T) {
|
||||
MatchId: "ticket12Bacfill1Score1",
|
||||
Tickets: []*pb.Ticket{ticket1, ticket2},
|
||||
Backfill: backfill1,
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 1,
|
||||
}),
|
||||
@ -118,7 +117,7 @@ func TestEvaluate(t *testing.T) {
|
||||
MatchId: "ticket12Bacfill1Score1",
|
||||
Tickets: []*pb.Ticket{ticket1, ticket2},
|
||||
Backfill: backfill1,
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 10,
|
||||
}),
|
||||
@ -129,7 +128,7 @@ func TestEvaluate(t *testing.T) {
|
||||
MatchId: "ticket12Backfill2Score5",
|
||||
Tickets: []*pb.Ticket{ticket1, ticket2},
|
||||
Backfill: backfill2,
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"evaluation_input": mustAny(&pb.DefaultEvaluationCriteria{
|
||||
Score: 5,
|
||||
}),
|
||||
|
@ -46,7 +46,7 @@ var (
|
||||
func BindServiceFor(eval Evaluator) appmain.Bind {
|
||||
return func(p *appmain.Params, b *appmain.Bindings) error {
|
||||
b.AddHandleFunc(func(s *grpc.Server) {
|
||||
pb.RegisterEvaluatorServer(s, &evaluatorService{eval})
|
||||
pb.RegisterEvaluatorServer(s, &evaluatorService{evaluate: eval})
|
||||
}, pb.RegisterEvaluatorHandlerFromEndpoint)
|
||||
b.RegisterViews(
|
||||
matchesPerEvaluateRequestView,
|
||||
|
@ -17,15 +17,15 @@ package frontend
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/rs/xid"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
"open-match.dev/open-match/internal/statestore"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
@ -72,7 +72,7 @@ func doCreateTicket(ctx context.Context, req *pb.CreateTicketRequest, store stat
|
||||
}
|
||||
|
||||
ticket.Id = xid.New().String()
|
||||
ticket.CreateTime = ptypes.TimestampNow()
|
||||
ticket.CreateTime = timestamppb.Now()
|
||||
|
||||
sfCount := 0
|
||||
sfCount += len(ticket.GetSearchFields().GetDoubleArgs())
|
||||
@ -122,7 +122,7 @@ func doCreateBackfill(ctx context.Context, req *pb.CreateBackfillRequest, store
|
||||
}
|
||||
|
||||
backfill.Id = xid.New().String()
|
||||
backfill.CreateTime = ptypes.TimestampNow()
|
||||
backfill.CreateTime = timestamppb.Now()
|
||||
backfill.Generation = 1
|
||||
|
||||
sfCount := 0
|
||||
@ -171,7 +171,7 @@ func (s *frontendService) UpdateBackfill(ctx context.Context, req *pb.UpdateBack
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if _, err = m.Unlock(ctx); err != nil {
|
||||
if _, err = m.Unlock(context.Background()); err != nil {
|
||||
logger.WithError(err).Error("error on mutex unlock")
|
||||
}
|
||||
}()
|
||||
@ -183,6 +183,7 @@ func (s *frontendService) UpdateBackfill(ctx context.Context, req *pb.UpdateBack
|
||||
// Update generation here, because Frontend is used by GameServer only
|
||||
bfStored.SearchFields = backfill.SearchFields
|
||||
bfStored.Extensions = backfill.Extensions
|
||||
bfStored.PersistentField = backfill.PersistentField
|
||||
// Autoincrement generation, input backfill generation validation is performed
|
||||
// on Backend only (after MMF round)
|
||||
bfStored.Generation++
|
||||
@ -208,7 +209,7 @@ func (s *frontendService) UpdateBackfill(ctx context.Context, req *pb.UpdateBack
|
||||
}
|
||||
|
||||
// DeleteBackfill deletes a Backfill by its ID.
|
||||
func (s *frontendService) DeleteBackfill(ctx context.Context, req *pb.DeleteBackfillRequest) (*empty.Empty, error) {
|
||||
func (s *frontendService) DeleteBackfill(ctx context.Context, req *pb.DeleteBackfillRequest) (*emptypb.Empty, error) {
|
||||
bfID := req.GetBackfillId()
|
||||
if bfID == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, ".BackfillId is required")
|
||||
@ -221,19 +222,20 @@ func (s *frontendService) DeleteBackfill(ctx context.Context, req *pb.DeleteBack
|
||||
"error": err.Error(),
|
||||
}).Error("error on DeleteBackfill")
|
||||
}
|
||||
return &empty.Empty{}, nil
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// DeleteTicket immediately stops Open Match from using the Ticket for matchmaking and removes the Ticket from state storage.
|
||||
// The client must delete the Ticket when finished matchmaking with it.
|
||||
// - If SearchFields exist in a Ticket, DeleteTicket will deindex the fields lazily.
|
||||
//
|
||||
// Users may still be able to assign/get a ticket after calling DeleteTicket on it.
|
||||
func (s *frontendService) DeleteTicket(ctx context.Context, req *pb.DeleteTicketRequest) (*empty.Empty, error) {
|
||||
func (s *frontendService) DeleteTicket(ctx context.Context, req *pb.DeleteTicketRequest) (*emptypb.Empty, error) {
|
||||
err := doDeleteTicket(ctx, req.GetTicketId(), s.store)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &empty.Empty{}, nil
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func doDeleteTicket(ctx context.Context, id string, store statestore.Service) error {
|
||||
@ -277,35 +279,37 @@ func (s *frontendService) GetTicket(ctx context.Context, req *pb.GetTicketReques
|
||||
// - If the Assignment is not updated, GetAssignment will retry using the configured backoff strategy.
|
||||
func (s *frontendService) WatchAssignments(req *pb.WatchAssignmentsRequest, stream pb.FrontendService_WatchAssignmentsServer) error {
|
||||
ctx := stream.Context()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
sender := func(assignment *pb.Assignment) error {
|
||||
return stream.Send(&pb.WatchAssignmentsResponse{Assignment: assignment})
|
||||
}
|
||||
return doWatchAssignments(ctx, req.GetTicketId(), sender, s.store)
|
||||
}
|
||||
sender := func(assignment *pb.Assignment) error {
|
||||
return stream.Send(&pb.WatchAssignmentsResponse{Assignment: assignment})
|
||||
}
|
||||
return doWatchAssignments(ctx, req.GetTicketId(), sender, s.store)
|
||||
}
|
||||
|
||||
func doWatchAssignments(ctx context.Context, id string, sender func(*pb.Assignment) error, store statestore.Service) error {
|
||||
var currAssignment *pb.Assignment
|
||||
var ok bool
|
||||
callback := func(assignment *pb.Assignment) error {
|
||||
if (currAssignment == nil && assignment != nil) || !proto.Equal(currAssignment, assignment) {
|
||||
currAssignment, ok = proto.Clone(assignment).(*pb.Assignment)
|
||||
if !ok {
|
||||
return status.Error(codes.Internal, "failed to cast the assignment object")
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return status.Errorf(codes.Aborted, ctx.Err().Error())
|
||||
default:
|
||||
if ctx.Err() != nil {
|
||||
return status.Errorf(codes.Aborted, ctx.Err().Error())
|
||||
}
|
||||
|
||||
err := sender(currAssignment)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Aborted, err.Error())
|
||||
if (currAssignment == nil && assignment != nil) || !proto.Equal(currAssignment, assignment) {
|
||||
currAssignment, ok = proto.Clone(assignment).(*pb.Assignment)
|
||||
if !ok {
|
||||
return status.Error(codes.Internal, "failed to cast the assignment object")
|
||||
}
|
||||
|
||||
err := sender(currAssignment)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Aborted, err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return store.GetAssignments(ctx, id, callback)
|
||||
@ -313,7 +317,7 @@ func doWatchAssignments(ctx context.Context, id string, sender func(*pb.Assignme
|
||||
|
||||
// AcknowledgeBackfill is used to notify OpenMatch about GameServer connection info.
|
||||
// This triggers an assignment process.
|
||||
func (s *frontendService) AcknowledgeBackfill(ctx context.Context, req *pb.AcknowledgeBackfillRequest) (*pb.Backfill, error) {
|
||||
func (s *frontendService) AcknowledgeBackfill(ctx context.Context, req *pb.AcknowledgeBackfillRequest) (*pb.AcknowledgeBackfillResponse, error) {
|
||||
if req.GetBackfillId() == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, ".BackfillId is required")
|
||||
}
|
||||
@ -328,7 +332,7 @@ func (s *frontendService) AcknowledgeBackfill(ctx context.Context, req *pb.Ackno
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if _, err = m.Unlock(ctx); err != nil {
|
||||
if _, err = m.Unlock(context.Background()); err != nil {
|
||||
logger.WithError(err).Error("error on mutex unlock")
|
||||
}
|
||||
}()
|
||||
@ -343,16 +347,23 @@ func (s *frontendService) AcknowledgeBackfill(ctx context.Context, req *pb.Ackno
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &pb.AcknowledgeBackfillResponse{
|
||||
Backfill: bf,
|
||||
Tickets: make([]*pb.Ticket, 0),
|
||||
}
|
||||
|
||||
if len(associatedTickets) != 0 {
|
||||
resp, _, err := s.store.UpdateAssignments(ctx, &pb.AssignTicketsRequest{
|
||||
setResp, tickets, err := s.store.UpdateAssignments(ctx, &pb.AssignTicketsRequest{
|
||||
Assignments: []*pb.AssignmentGroup{{TicketIds: associatedTickets, Assignment: req.GetAssignment()}},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Tickets = tickets
|
||||
|
||||
// log errors returned from UpdateAssignments to track tickets with NotFound errors
|
||||
for _, f := range resp.Failures {
|
||||
for _, f := range setResp.Failures {
|
||||
logger.Errorf("failed to assign ticket %s, cause %d", f.TicketId, f.Cause)
|
||||
}
|
||||
for _, id := range associatedTickets {
|
||||
@ -370,7 +381,7 @@ func (s *frontendService) AcknowledgeBackfill(ctx context.Context, req *pb.Ackno
|
||||
}
|
||||
}
|
||||
|
||||
return bf, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetBackfill fetches a Backfill object by its ID.
|
||||
|
@ -22,11 +22,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"open-match.dev/open-match/internal/statestore"
|
||||
statestoreTesting "open-match.dev/open-match/internal/statestore/testing"
|
||||
utilTesting "open-match.dev/open-match/internal/util/testing"
|
||||
@ -94,7 +94,7 @@ func TestCreateBackfill(t *testing.T) {
|
||||
store, closer := statestoreTesting.NewStoreServiceForTesting(t, cfg)
|
||||
defer closer()
|
||||
ctx := utilTesting.NewContext(t)
|
||||
fs := frontendService{cfg, store}
|
||||
fs := frontendService{cfg: cfg, store: store}
|
||||
var testCases = []struct {
|
||||
description string
|
||||
request *pb.CreateBackfillRequest
|
||||
@ -116,7 +116,7 @@ func TestCreateBackfill(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "createTime should not exist in input",
|
||||
request: &pb.CreateBackfillRequest{Backfill: &pb.Backfill{CreateTime: ptypes.TimestampNow()}},
|
||||
request: &pb.CreateBackfillRequest{Backfill: &pb.Backfill{CreateTime: timestamppb.Now()}},
|
||||
expectedCode: codes.InvalidArgument,
|
||||
expectedMessage: "backfills cannot be created with create time set",
|
||||
},
|
||||
@ -157,7 +157,7 @@ func TestCreateBackfill(t *testing.T) {
|
||||
// expect error with canceled context
|
||||
store, closer = statestoreTesting.NewStoreServiceForTesting(t, cfg)
|
||||
defer closer()
|
||||
fs = frontendService{cfg, store}
|
||||
fs = frontendService{cfg: cfg, store: store}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
@ -178,7 +178,7 @@ func TestUpdateBackfill(t *testing.T) {
|
||||
store, closer := statestoreTesting.NewStoreServiceForTesting(t, cfg)
|
||||
defer closer()
|
||||
ctx := utilTesting.NewContext(t)
|
||||
fs := frontendService{cfg, store}
|
||||
fs := frontendService{cfg: cfg, store: store}
|
||||
res, err := fs.CreateBackfill(ctx, &pb.CreateBackfillRequest{
|
||||
Backfill: &pb.Backfill{
|
||||
SearchFields: &pb.SearchFields{
|
||||
@ -248,7 +248,7 @@ func TestUpdateBackfill(t *testing.T) {
|
||||
|
||||
// expect error with canceled context
|
||||
store, closer = statestoreTesting.NewStoreServiceForTesting(t, cfg)
|
||||
fs = frontendService{cfg, store}
|
||||
fs = frontendService{cfg: cfg, store: store}
|
||||
defer closer()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
@ -370,7 +370,7 @@ func TestAcknowledgeBackfillValidation(t *testing.T) {
|
||||
|
||||
store, closer := statestoreTesting.NewStoreServiceForTesting(t, cfg)
|
||||
defer closer()
|
||||
fs := frontendService{cfg, store}
|
||||
fs := frontendService{cfg: cfg, store: store}
|
||||
bf, err := fs.AcknowledgeBackfill(ctx, test.request)
|
||||
require.Equal(t, codes.InvalidArgument.String(), status.Convert(err).Code().String())
|
||||
require.Equal(t, test.expectedMessage, status.Convert(err).Message())
|
||||
@ -399,16 +399,18 @@ func TestAcknowledgeBackfill(t *testing.T) {
|
||||
}
|
||||
err := store.CreateBackfill(ctx, fakeBackfill, []string{})
|
||||
require.NoError(t, err)
|
||||
fs := frontendService{cfg, store}
|
||||
fs := frontendService{cfg: cfg, store: store}
|
||||
|
||||
bf, err := fs.AcknowledgeBackfill(ctx, &pb.AcknowledgeBackfillRequest{BackfillId: fakeBackfill.Id, Assignment: &pb.Assignment{Connection: "10.0.0.1"}})
|
||||
resp, err := fs.AcknowledgeBackfill(ctx, &pb.AcknowledgeBackfillRequest{BackfillId: fakeBackfill.Id, Assignment: &pb.Assignment{Connection: "10.0.0.1"}})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, bf)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Backfill)
|
||||
require.NotNil(t, resp.Tickets)
|
||||
|
||||
// Use wrong BackfillID, error is returned
|
||||
bf, err = fs.AcknowledgeBackfill(ctx, &pb.AcknowledgeBackfillRequest{BackfillId: "42", Assignment: &pb.Assignment{Connection: "10.0.0.1"}})
|
||||
resp, err = fs.AcknowledgeBackfill(ctx, &pb.AcknowledgeBackfillRequest{BackfillId: "42", Assignment: &pb.Assignment{Connection: "10.0.0.1"}})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, bf)
|
||||
require.Nil(t, resp)
|
||||
require.Equal(t, "Backfill id: 42 not found", status.Convert(err).Message())
|
||||
|
||||
time.Sleep(cfg.GetDuration("pendingReleaseTimeout"))
|
||||
@ -416,8 +418,8 @@ func TestAcknowledgeBackfill(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, ids, 1)
|
||||
|
||||
bf, err = fs.AcknowledgeBackfill(ctx, &pb.AcknowledgeBackfillRequest{BackfillId: fakeBackfill.Id, Assignment: &pb.Assignment{Connection: "10.0.0.1"}})
|
||||
require.Nil(t, bf)
|
||||
resp, err = fs.AcknowledgeBackfill(ctx, &pb.AcknowledgeBackfillRequest{BackfillId: fakeBackfill.Id, Assignment: &pb.Assignment{Connection: "10.0.0.1"}})
|
||||
require.Nil(t, resp)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, codes.Unavailable.String(), status.Convert(err).Code().String())
|
||||
require.Contains(t, status.Convert(err).Message(), "can not acknowledge an expired backfill, id: 1")
|
||||
@ -578,7 +580,7 @@ func TestGetBackfill(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(utilTesting.NewContext(t))
|
||||
store, closer := statestoreTesting.NewStoreServiceForTesting(t, viper.New())
|
||||
defer closer()
|
||||
fs := frontendService{cfg, store}
|
||||
fs := frontendService{cfg: cfg, store: store}
|
||||
|
||||
test.preAction(ctx, cancel, store)
|
||||
|
||||
@ -611,7 +613,7 @@ func TestDoDeleteBackfill(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := viper.New()
|
||||
fs := frontendService{cfg, store}
|
||||
fs := frontendService{cfg: cfg, store: store}
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
|
@ -177,8 +177,10 @@ func updateTicketCache(store statestore.Service, value interface{}) error {
|
||||
}
|
||||
|
||||
stats.Record(context.Background(), cacheTotalItems.M(int64(previousCount)))
|
||||
stats.Record(context.Background(), totalActiveTickets.M(int64(len(currentAll))))
|
||||
stats.Record(context.Background(), cacheFetchedItems.M(int64(len(toFetch))))
|
||||
stats.Record(context.Background(), cacheUpdateLatency.M(float64(time.Since(t))/float64(time.Millisecond)))
|
||||
stats.Record(context.Background(), totalPendingTickets.M(int64(len(toFetch))))
|
||||
|
||||
logger.Debugf("Ticket Cache update: Previous %d, Deleted %d, Fetched %d, Current %d", previousCount, deletedCount, len(toFetch), len(tickets))
|
||||
return nil
|
||||
@ -242,6 +244,7 @@ func updateBackfillCache(store statestore.Service, value interface{}) error {
|
||||
}
|
||||
|
||||
stats.Record(context.Background(), cacheTotalItems.M(int64(previousCount)))
|
||||
stats.Record(context.Background(), totalBackfillsTickets.M(int64(len(backfills))))
|
||||
stats.Record(context.Background(), cacheFetchedItems.M(int64(len(toFetch))))
|
||||
stats.Record(context.Background(), cacheUpdateLatency.M(float64(time.Since(t))/float64(time.Millisecond)))
|
||||
|
||||
|
@ -25,12 +25,15 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ticketsPerQuery = stats.Int64("open-match.dev/query/tickets_per_query", "Number of tickets per query", stats.UnitDimensionless)
|
||||
backfillsPerQuery = stats.Int64("open-match.dev/query/backfills_per_query", "Number of backfills per query", stats.UnitDimensionless)
|
||||
cacheTotalItems = stats.Int64("open-match.dev/query/total_cache_items", "Total number of items query service cached", stats.UnitDimensionless)
|
||||
cacheFetchedItems = stats.Int64("open-match.dev/query/fetched_items", "Number of fetched items in total", stats.UnitDimensionless)
|
||||
cacheWaitingQueries = stats.Int64("open-match.dev/query/waiting_queries", "Number of waiting queries in the last update", stats.UnitDimensionless)
|
||||
cacheUpdateLatency = stats.Float64("open-match.dev/query/update_latency", "Time elapsed of each query cache update", stats.UnitMilliseconds)
|
||||
ticketsPerQuery = stats.Int64("open-match.dev/query/tickets_per_query", "Number of tickets per query", stats.UnitDimensionless)
|
||||
totalActiveTickets = stats.Int64("open-match.dev/query/total_active_tickets", "Number of tickets", stats.UnitDimensionless)
|
||||
backfillsPerQuery = stats.Int64("open-match.dev/query/backfills_per_query", "Number of backfills per query", stats.UnitDimensionless)
|
||||
totalBackfillsTickets = stats.Int64("open-match.dev/query/total_backfill_tickets", "Number of current backfills", stats.UnitDimensionless)
|
||||
totalPendingTickets = stats.Int64("open-match.dev/query/tickets_pending_release", "Number of tickets per query", stats.UnitDimensionless)
|
||||
cacheTotalItems = stats.Int64("open-match.dev/query/total_cache_items", "Total number of items query service cached", stats.UnitDimensionless)
|
||||
cacheFetchedItems = stats.Int64("open-match.dev/query/fetched_items", "Number of fetched items in total", stats.UnitDimensionless)
|
||||
cacheWaitingQueries = stats.Int64("open-match.dev/query/waiting_queries", "Number of waiting queries in the last update", stats.UnitDimensionless)
|
||||
cacheUpdateLatency = stats.Float64("open-match.dev/query/update_latency", "Time elapsed of each query cache update", stats.UnitMilliseconds)
|
||||
|
||||
ticketsPerQueryView = &view.View{
|
||||
Measure: ticketsPerQuery,
|
||||
@ -38,12 +41,30 @@ var (
|
||||
Description: "Tickets per query",
|
||||
Aggregation: telemetry.DefaultCountDistribution,
|
||||
}
|
||||
ticketsActiveTotalView = &view.View{
|
||||
Measure: totalActiveTickets,
|
||||
Name: "open-match.dev/query/total_active_tickets",
|
||||
Description: "Total tickets",
|
||||
Aggregation: view.LastValue(),
|
||||
}
|
||||
backfillsPerQueryView = &view.View{
|
||||
Measure: ticketsPerQuery,
|
||||
Name: "open-match.dev/query/backfills_per_query",
|
||||
Description: "Backfills per query",
|
||||
Aggregation: telemetry.DefaultCountDistribution,
|
||||
}
|
||||
backfillTotalTicketsView = &view.View{
|
||||
Measure: totalBackfillsTickets,
|
||||
Name: "open-match.dev/query/total_backfill_tickets",
|
||||
Description: "Total number of backfill tickets",
|
||||
Aggregation: view.LastValue(),
|
||||
}
|
||||
pendingTotalTicketsView = &view.View{
|
||||
Measure: totalPendingTickets,
|
||||
Name: "open-match.dev/query/total_pending_tickets",
|
||||
Description: "Total number of pending tickets",
|
||||
Aggregation: view.LastValue(),
|
||||
}
|
||||
cacheTotalItemsView = &view.View{
|
||||
Measure: cacheTotalItems,
|
||||
Name: "open-match.dev/query/total_cached_items",
|
||||
@ -90,7 +111,10 @@ func BindService(p *appmain.Params, b *appmain.Bindings) error {
|
||||
}, pb.RegisterQueryServiceHandlerFromEndpoint)
|
||||
b.RegisterViews(
|
||||
ticketsPerQueryView,
|
||||
ticketsActiveTotalView,
|
||||
backfillsPerQueryView,
|
||||
backfillTotalTicketsView,
|
||||
pendingTotalTicketsView,
|
||||
cacheTotalItemsView,
|
||||
cacheUpdateView,
|
||||
cacheFetchedItemsView,
|
||||
|
@ -133,7 +133,7 @@ var getTests = []struct {
|
||||
},
|
||||
}
|
||||
|
||||
//nolint: gocritic, staticcheck
|
||||
// nolint: gocritic, staticcheck
|
||||
func Test_Get(t *testing.T) {
|
||||
for _, tt := range getTests {
|
||||
tt := tt
|
||||
|
@ -58,6 +58,30 @@ func Read() (*viper.Viper, error) {
|
||||
return nil, fmt.Errorf("fatal error reading override config file, desc: %s", err.Error())
|
||||
}
|
||||
|
||||
if !cfg.IsSet("registrationInterval") {
|
||||
log.Printf("config: registrationInterval is not set in matchmaker_config_override.yaml")
|
||||
}
|
||||
|
||||
if !cfg.IsSet("proposalCollectionInterval") {
|
||||
log.Printf("config: proposalCollectionInterval is not set in matchmaker_config_override.yaml")
|
||||
}
|
||||
|
||||
if !cfg.IsSet("pendingReleaseTimeout") {
|
||||
log.Printf("config: pendingReleaseTimeout is not set in matchmaker_config_override.yaml")
|
||||
}
|
||||
|
||||
if !cfg.IsSet("assignedDeleteTimeout") {
|
||||
log.Printf("config: assignedDeleteTimeout is not set in matchmaker_config_override.yaml")
|
||||
}
|
||||
|
||||
if !cfg.IsSet("queryPageSize") {
|
||||
log.Printf("config: queryPageSize is not set in matchmaker_config_override.yaml")
|
||||
}
|
||||
|
||||
if !cfg.IsSet("backfillLockTimeout") {
|
||||
log.Printf("config: backfillLockTimeout is not set in matchmaker_config_override.yaml")
|
||||
}
|
||||
|
||||
// Look for updates to the config; in Kubernetes, this is implemented using
|
||||
// a ConfigMap that is written to the matchmaker_config_override.yaml file, which is
|
||||
// what the Open Match components using Viper monitor for changes.
|
||||
|
@ -1,3 +1,4 @@
|
||||
//go:build !race
|
||||
// +build !race
|
||||
|
||||
// Copyright 2019 Google LLC
|
||||
|
@ -20,11 +20,10 @@ package filter
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
@ -53,15 +52,17 @@ func NewPoolFilter(pool *pb.Pool) (*PoolFilter, error) {
|
||||
var err error
|
||||
|
||||
if pool.GetCreatedBefore() != nil {
|
||||
if cb, err = ptypes.Timestamp(pool.GetCreatedBefore()); err != nil {
|
||||
if err = pool.GetCreatedBefore().CheckValid(); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, ".invalid created_before value")
|
||||
}
|
||||
cb = pool.GetCreatedBefore().AsTime()
|
||||
}
|
||||
|
||||
if pool.GetCreatedAfter() != nil {
|
||||
if ca, err = ptypes.Timestamp(pool.GetCreatedAfter()); err != nil {
|
||||
if err = pool.GetCreatedAfter().CheckValid(); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, ".invalid created_after value")
|
||||
}
|
||||
ca = pool.GetCreatedAfter().AsTime()
|
||||
}
|
||||
|
||||
return &PoolFilter{
|
||||
@ -76,7 +77,7 @@ func NewPoolFilter(pool *pb.Pool) (*PoolFilter, error) {
|
||||
type filteredEntity interface {
|
||||
GetId() string
|
||||
GetSearchFields() *pb.SearchFields
|
||||
GetCreateTime() *timestamp.Timestamp
|
||||
GetCreateTime() *timestamppb.Timestamp
|
||||
}
|
||||
|
||||
// In returns true if the Ticket meets all the criteria for this PoolFilter.
|
||||
@ -89,7 +90,8 @@ func (pf *PoolFilter) In(entity filteredEntity) bool {
|
||||
|
||||
if !pf.CreatedAfter.IsZero() || !pf.CreatedBefore.IsZero() {
|
||||
// CreateTime is only populated by Open Match and hence expected to be valid.
|
||||
if ct, err := ptypes.Timestamp(entity.GetCreateTime()); err == nil {
|
||||
if err := entity.GetCreateTime().CheckValid(); err == nil {
|
||||
ct := entity.GetCreateTime().AsTime()
|
||||
if !pf.CreatedAfter.IsZero() {
|
||||
if !ct.After(pf.CreatedAfter) {
|
||||
return false
|
||||
|
@ -17,11 +17,10 @@ package filter
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"open-match.dev/open-match/internal/filter/testcases"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
@ -43,11 +42,11 @@ func TestMeetsCriteria(t *testing.T) {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
testInclusion(t, tc.Pool, &pb.Ticket{
|
||||
SearchFields: tc.SearchFields,
|
||||
CreateTime: ptypes.TimestampNow(),
|
||||
CreateTime: timestamppb.Now(),
|
||||
})
|
||||
testInclusion(t, tc.Pool, &pb.Backfill{
|
||||
SearchFields: tc.SearchFields,
|
||||
CreateTime: ptypes.TimestampNow(),
|
||||
CreateTime: timestamppb.Now(),
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -68,11 +67,11 @@ func TestMeetsCriteria(t *testing.T) {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
testExclusion(t, tc.Pool, &pb.Ticket{
|
||||
SearchFields: tc.SearchFields,
|
||||
CreateTime: ptypes.TimestampNow(),
|
||||
CreateTime: timestamppb.Now(),
|
||||
})
|
||||
testExclusion(t, tc.Pool, &pb.Backfill{
|
||||
SearchFields: tc.SearchFields,
|
||||
CreateTime: ptypes.TimestampNow(),
|
||||
CreateTime: timestamppb.Now(),
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -88,7 +87,7 @@ func TestValidPoolFilter(t *testing.T) {
|
||||
{
|
||||
"invalid create before",
|
||||
&pb.Pool{
|
||||
CreatedBefore: ×tamp.Timestamp{Nanos: -1},
|
||||
CreatedBefore: ×tamppb.Timestamp{Nanos: -1},
|
||||
},
|
||||
codes.InvalidArgument,
|
||||
".invalid created_before value",
|
||||
@ -96,7 +95,7 @@ func TestValidPoolFilter(t *testing.T) {
|
||||
{
|
||||
"invalid create after",
|
||||
&pb.Pool{
|
||||
CreatedAfter: ×tamp.Timestamp{Nanos: -1},
|
||||
CreatedAfter: ×tamppb.Timestamp{Nanos: -1},
|
||||
},
|
||||
codes.InvalidArgument,
|
||||
".invalid created_after value",
|
||||
|
@ -20,8 +20,7 @@ import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
tspb "github.com/golang/protobuf/ptypes/timestamp"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
@ -447,9 +446,9 @@ func multipleFilters(doubleRange, stringEquals, tagPresent bool) TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
func timestamp(t time.Time) *tspb.Timestamp {
|
||||
tsp, err := ptypes.TimestampProto(t)
|
||||
if err != nil {
|
||||
func timestamp(t time.Time) *timestamppb.Timestamp {
|
||||
tsp := timestamppb.New(t)
|
||||
if err := tsp.CheckValid(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
@ -14,14 +14,13 @@
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc v3.10.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.24.0
|
||||
// source: internal/api/messages.proto
|
||||
|
||||
package ipb
|
||||
|
||||
import (
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
pb "open-match.dev/open-match/pkg/pb"
|
||||
@ -36,10 +35,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type BackfillInternal struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
@ -14,18 +14,13 @@
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc v3.10.1
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.24.0
|
||||
// source: internal/api/synchronizer.proto
|
||||
|
||||
package ipb
|
||||
|
||||
import (
|
||||
context "context"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
pb "open-match.dev/open-match/pkg/pb"
|
||||
@ -40,10 +35,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type SynchronizeRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -271,119 +262,3 @@ func file_internal_api_synchronizer_proto_init() {
|
||||
file_internal_api_synchronizer_proto_goTypes = nil
|
||||
file_internal_api_synchronizer_proto_depIdxs = nil
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConnInterface
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion6
|
||||
|
||||
// SynchronizerClient is the client API for Synchronizer service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type SynchronizerClient interface {
|
||||
// Synchronize signals the caller when it is safe to run mmfs, collects the
|
||||
// mmfs' proposals, and returns the evaluated matches.
|
||||
Synchronize(ctx context.Context, opts ...grpc.CallOption) (Synchronizer_SynchronizeClient, error)
|
||||
}
|
||||
|
||||
type synchronizerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewSynchronizerClient(cc grpc.ClientConnInterface) SynchronizerClient {
|
||||
return &synchronizerClient{cc}
|
||||
}
|
||||
|
||||
func (c *synchronizerClient) Synchronize(ctx context.Context, opts ...grpc.CallOption) (Synchronizer_SynchronizeClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_Synchronizer_serviceDesc.Streams[0], "/openmatch.internal.Synchronizer/Synchronize", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &synchronizerSynchronizeClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Synchronizer_SynchronizeClient interface {
|
||||
Send(*SynchronizeRequest) error
|
||||
Recv() (*SynchronizeResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type synchronizerSynchronizeClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeClient) Send(m *SynchronizeRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeClient) Recv() (*SynchronizeResponse, error) {
|
||||
m := new(SynchronizeResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// SynchronizerServer is the server API for Synchronizer service.
|
||||
type SynchronizerServer interface {
|
||||
// Synchronize signals the caller when it is safe to run mmfs, collects the
|
||||
// mmfs' proposals, and returns the evaluated matches.
|
||||
Synchronize(Synchronizer_SynchronizeServer) error
|
||||
}
|
||||
|
||||
// UnimplementedSynchronizerServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedSynchronizerServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedSynchronizerServer) Synchronize(Synchronizer_SynchronizeServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Synchronize not implemented")
|
||||
}
|
||||
|
||||
func RegisterSynchronizerServer(s *grpc.Server, srv SynchronizerServer) {
|
||||
s.RegisterService(&_Synchronizer_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Synchronizer_Synchronize_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(SynchronizerServer).Synchronize(&synchronizerSynchronizeServer{stream})
|
||||
}
|
||||
|
||||
type Synchronizer_SynchronizeServer interface {
|
||||
Send(*SynchronizeResponse) error
|
||||
Recv() (*SynchronizeRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type synchronizerSynchronizeServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeServer) Send(m *SynchronizeResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeServer) Recv() (*SynchronizeRequest, error) {
|
||||
m := new(SynchronizeRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var _Synchronizer_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "openmatch.internal.Synchronizer",
|
||||
HandlerType: (*SynchronizerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Synchronize",
|
||||
Handler: _Synchronizer_Synchronize_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "internal/api/synchronizer.proto",
|
||||
}
|
||||
|
157
internal/ipb/synchronizer_grpc.pb.go
Normal file
157
internal/ipb/synchronizer_grpc.pb.go
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.24.0
|
||||
// source: internal/api/synchronizer.proto
|
||||
|
||||
package ipb
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
Synchronizer_Synchronize_FullMethodName = "/openmatch.internal.Synchronizer/Synchronize"
|
||||
)
|
||||
|
||||
// SynchronizerClient is the client API for Synchronizer service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type SynchronizerClient interface {
|
||||
// Synchronize signals the caller when it is safe to run mmfs, collects the
|
||||
// mmfs' proposals, and returns the evaluated matches.
|
||||
Synchronize(ctx context.Context, opts ...grpc.CallOption) (Synchronizer_SynchronizeClient, error)
|
||||
}
|
||||
|
||||
type synchronizerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewSynchronizerClient(cc grpc.ClientConnInterface) SynchronizerClient {
|
||||
return &synchronizerClient{cc}
|
||||
}
|
||||
|
||||
func (c *synchronizerClient) Synchronize(ctx context.Context, opts ...grpc.CallOption) (Synchronizer_SynchronizeClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Synchronizer_ServiceDesc.Streams[0], Synchronizer_Synchronize_FullMethodName, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &synchronizerSynchronizeClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Synchronizer_SynchronizeClient interface {
|
||||
Send(*SynchronizeRequest) error
|
||||
Recv() (*SynchronizeResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type synchronizerSynchronizeClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeClient) Send(m *SynchronizeRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeClient) Recv() (*SynchronizeResponse, error) {
|
||||
m := new(SynchronizeResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// SynchronizerServer is the server API for Synchronizer service.
|
||||
// All implementations should embed UnimplementedSynchronizerServer
|
||||
// for forward compatibility
|
||||
type SynchronizerServer interface {
|
||||
// Synchronize signals the caller when it is safe to run mmfs, collects the
|
||||
// mmfs' proposals, and returns the evaluated matches.
|
||||
Synchronize(Synchronizer_SynchronizeServer) error
|
||||
}
|
||||
|
||||
// UnimplementedSynchronizerServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedSynchronizerServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedSynchronizerServer) Synchronize(Synchronizer_SynchronizeServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Synchronize not implemented")
|
||||
}
|
||||
|
||||
// UnsafeSynchronizerServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to SynchronizerServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeSynchronizerServer interface {
|
||||
mustEmbedUnimplementedSynchronizerServer()
|
||||
}
|
||||
|
||||
func RegisterSynchronizerServer(s grpc.ServiceRegistrar, srv SynchronizerServer) {
|
||||
s.RegisterService(&Synchronizer_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Synchronizer_Synchronize_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(SynchronizerServer).Synchronize(&synchronizerSynchronizeServer{stream})
|
||||
}
|
||||
|
||||
type Synchronizer_SynchronizeServer interface {
|
||||
Send(*SynchronizeResponse) error
|
||||
Recv() (*SynchronizeRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type synchronizerSynchronizeServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeServer) Send(m *SynchronizeResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *synchronizerSynchronizeServer) Recv() (*SynchronizeRequest, error) {
|
||||
m := new(SynchronizeRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Synchronizer_ServiceDesc is the grpc.ServiceDesc for Synchronizer service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Synchronizer_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "openmatch.internal.Synchronizer",
|
||||
HandlerType: (*SynchronizerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Synchronize",
|
||||
Handler: _Synchronizer_Synchronize_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "internal/api/synchronizer.proto",
|
||||
}
|
@ -24,8 +24,8 @@ import (
|
||||
)
|
||||
|
||||
// ConfigureLogging sets up open match logrus instance using the logging section of the matchmaker_config.json
|
||||
// - log line format (text[default] or json)
|
||||
// - min log level to include (debug, info [default], warn, error, fatal, panic)
|
||||
// - log line format (text[default] or json)
|
||||
// - min log level to include (debug, info [default], warn, error, fatal, panic)
|
||||
func ConfigureLogging(cfg config.View) {
|
||||
logrus.SetFormatter(newFormatter(cfg.GetString("logging.format")))
|
||||
level := toLevel(cfg.GetString("logging.level"))
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
"go.opencensus.io/plugin/ochttp"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
@ -134,7 +135,7 @@ func GRPCClientFromEndpoint(cfg config.View, address string) (*grpc.ClientConn,
|
||||
|
||||
grpcOptions = append(grpcOptions, grpc.WithTransportCredentials(tc))
|
||||
} else {
|
||||
grpcOptions = append(grpcOptions, grpc.WithInsecure())
|
||||
grpcOptions = append(grpcOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
}
|
||||
|
||||
return grpc.Dial(address, grpcOptions...)
|
||||
@ -152,7 +153,7 @@ func GRPCClientFromParams(params *ClientParams) (*grpc.ClientConn, error) {
|
||||
}
|
||||
grpcOptions = append(grpcOptions, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(trustedCertPool, "")))
|
||||
} else {
|
||||
grpcOptions = append(grpcOptions, grpc.WithInsecure())
|
||||
grpcOptions = append(grpcOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
}
|
||||
|
||||
return grpc.Dial(params.Address, grpcOptions...)
|
||||
|
@ -30,9 +30,9 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
"open-match.dev/open-match/internal/telemetry"
|
||||
shellTesting "open-match.dev/open-match/internal/testing"
|
||||
utilTesting "open-match.dev/open-match/internal/util/testing"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
shellTesting "open-match.dev/open-match/testing"
|
||||
certgenTesting "open-match.dev/open-match/tools/certgen/testing"
|
||||
)
|
||||
|
||||
|
@ -19,9 +19,11 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"open-match.dev/open-match/internal/telemetry"
|
||||
)
|
||||
|
||||
@ -37,7 +39,19 @@ type insecureServer struct {
|
||||
|
||||
func (s *insecureServer) start(params *ServerParams) error {
|
||||
s.httpMux = params.ServeMux
|
||||
s.proxyMux = runtime.NewServeMux()
|
||||
s.proxyMux = runtime.NewServeMux(
|
||||
runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
|
||||
Marshaler: &runtime.JSONPb{
|
||||
MarshalOptions: protojson.MarshalOptions{
|
||||
UseProtoNames: true,
|
||||
EmitUnpopulated: false,
|
||||
},
|
||||
UnmarshalOptions: protojson.UnmarshalOptions{
|
||||
DiscardUnknown: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
// Configure the gRPC server.
|
||||
s.grpcServer = grpc.NewServer(newGRPCServerOptions(params)...)
|
||||
@ -60,7 +74,7 @@ func (s *insecureServer) start(params *ServerParams) error {
|
||||
|
||||
for _, handlerFunc := range params.handlersForGrpcProxy {
|
||||
dialOpts := newGRPCDialOptions(params.enableMetrics, params.enableRPCLogging, params.enableRPCPayloadLogging)
|
||||
dialOpts = append(dialOpts, grpc.WithInsecure())
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err := handlerFunc(ctx, s.proxyMux, s.grpcListener.Addr().String(), dialOpts); err != nil {
|
||||
cancel()
|
||||
return errors.WithStack(err)
|
||||
|
@ -24,7 +24,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
shellTesting "open-match.dev/open-match/internal/testing"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
shellTesting "open-match.dev/open-match/testing"
|
||||
)
|
||||
|
||||
func TestInsecureStartStop(t *testing.T) {
|
||||
@ -42,7 +43,7 @@ func TestInsecureStartStop(t *testing.T) {
|
||||
err := s.start(params)
|
||||
require.Nil(err)
|
||||
|
||||
conn, err := grpc.Dial(fmt.Sprintf(":%s", MustGetPortNumber(grpcL)), grpc.WithInsecure())
|
||||
conn, err := grpc.Dial(fmt.Sprintf(":%s", MustGetPortNumber(grpcL)), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
require.Nil(err)
|
||||
defer conn.Close()
|
||||
|
||||
|
@ -28,7 +28,7 @@ import (
|
||||
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
|
||||
grpc_tracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
|
||||
grpc_validator "github.com/grpc-ecosystem/go-grpc-middleware/validator"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/plugin/ocgrpc"
|
||||
|
@ -24,10 +24,11 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"open-match.dev/open-match/internal/telemetry"
|
||||
shellTesting "open-match.dev/open-match/internal/testing"
|
||||
utilTesting "open-match.dev/open-match/internal/util/testing"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
shellTesting "open-match.dev/open-match/testing"
|
||||
)
|
||||
|
||||
func TestStartStopServer(t *testing.T) {
|
||||
@ -46,7 +47,7 @@ func TestStartStopServer(t *testing.T) {
|
||||
err := s.Start(params)
|
||||
require.Nil(err)
|
||||
|
||||
conn, err := grpc.Dial(fmt.Sprintf(":%s", MustGetPortNumber(grpcL)), grpc.WithInsecure())
|
||||
conn, err := grpc.Dial(fmt.Sprintf(":%s", MustGetPortNumber(grpcL)), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
require.Nil(err)
|
||||
|
||||
endpoint := fmt.Sprintf("http://localhost:%s", MustGetPortNumber(httpL))
|
||||
|
@ -21,10 +21,11 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"open-match.dev/open-match/internal/telemetry"
|
||||
)
|
||||
|
||||
@ -45,7 +46,19 @@ type tlsServer struct {
|
||||
|
||||
func (s *tlsServer) start(params *ServerParams) error {
|
||||
s.httpMux = params.ServeMux
|
||||
s.proxyMux = runtime.NewServeMux()
|
||||
s.proxyMux = runtime.NewServeMux(
|
||||
runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
|
||||
Marshaler: &runtime.JSONPb{
|
||||
MarshalOptions: protojson.MarshalOptions{
|
||||
UseProtoNames: true,
|
||||
EmitUnpopulated: false,
|
||||
},
|
||||
UnmarshalOptions: protojson.UnmarshalOptions{
|
||||
DiscardUnknown: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
_, grpcPort, err := net.SplitHostPort(s.grpcListener.Addr().String())
|
||||
if err != nil {
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
shellTesting "open-match.dev/open-match/internal/testing"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
shellTesting "open-match.dev/open-match/testing"
|
||||
certgenTesting "open-match.dev/open-match/tools/certgen/testing"
|
||||
)
|
||||
|
||||
|
@ -20,12 +20,12 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
"open-match.dev/open-match/internal/ipb"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
@ -164,7 +164,7 @@ func (rb *redisBackend) GetBackfills(ctx context.Context, ids []string) ([]*pb.B
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DeleteBackfill removes the Backfill with the specified id from state storage. This method succeeds if the Backfill does not exist.
|
||||
// DeleteBackfill removes the Backfill with the specified id from state storage.
|
||||
func (rb *redisBackend) DeleteBackfill(ctx context.Context, id string) error {
|
||||
redisConn, err := rb.redisPool.GetContext(ctx)
|
||||
if err != nil {
|
||||
@ -172,12 +172,16 @@ func (rb *redisBackend) DeleteBackfill(ctx context.Context, id string) error {
|
||||
}
|
||||
defer handleConnectionClose(&redisConn)
|
||||
|
||||
_, err = redisConn.Do("DEL", id)
|
||||
value, err := redis.Int(redisConn.Do("DEL", id))
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to delete the backfill from state storage, id: %s", id)
|
||||
return status.Errorf(codes.Internal, "%v", err)
|
||||
}
|
||||
|
||||
if value == 0 {
|
||||
return status.Errorf(codes.NotFound, "Backfill id: %s not found", id)
|
||||
}
|
||||
|
||||
return rb.deleteExpiredBackfillID(redisConn, id)
|
||||
}
|
||||
|
||||
@ -189,7 +193,7 @@ func (rb *redisBackend) UpdateBackfill(ctx context.Context, backfill *pb.Backfil
|
||||
}
|
||||
defer handleConnectionClose(&redisConn)
|
||||
|
||||
expired, err := isBackfillExpired(redisConn, backfill.Id, getBackfillReleaseTimeout(rb.cfg))
|
||||
expired, err := isBackfillExpired(redisConn, backfill.Id, getBackfillReleaseTimeoutFraction(rb.cfg))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -238,7 +242,7 @@ func (rb *redisBackend) DeleteBackfillCompletely(ctx context.Context, id string)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if _, err = m.Unlock(ctx); err != nil {
|
||||
if _, err = m.Unlock(context.Background()); err != nil {
|
||||
logger.WithError(err).Error("error on mutex unlock")
|
||||
}
|
||||
}()
|
||||
@ -328,7 +332,7 @@ func (rb *redisBackend) UpdateAcknowledgmentTimestamp(ctx context.Context, id st
|
||||
}
|
||||
defer handleConnectionClose(&redisConn)
|
||||
|
||||
expired, err := isBackfillExpired(redisConn, id, getBackfillReleaseTimeout(rb.cfg))
|
||||
expired, err := isBackfillExpired(redisConn, id, getBackfillReleaseTimeoutFraction(rb.cfg))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -360,7 +364,7 @@ func (rb *redisBackend) GetExpiredBackfillIDs(ctx context.Context) ([]string, er
|
||||
}
|
||||
defer handleConnectionClose(&redisConn)
|
||||
|
||||
ttl := getBackfillReleaseTimeout(rb.cfg)
|
||||
ttl := getBackfillReleaseTimeoutFraction(rb.cfg)
|
||||
curTime := time.Now()
|
||||
endTimeInt := curTime.Add(-ttl).UnixNano()
|
||||
startTimeInt := 0
|
||||
@ -427,7 +431,7 @@ func (rb *redisBackend) GetIndexedBackfills(ctx context.Context) (map[string]int
|
||||
}
|
||||
defer handleConnectionClose(&redisConn)
|
||||
|
||||
ttl := getBackfillReleaseTimeout(rb.cfg)
|
||||
ttl := getBackfillReleaseTimeoutFraction(rb.cfg)
|
||||
curTime := time.Now()
|
||||
endTimeInt := curTime.Add(time.Hour).UnixNano()
|
||||
startTimeInt := curTime.Add(-ttl).UnixNano()
|
||||
@ -459,7 +463,22 @@ func (rb *redisBackend) GetIndexedBackfills(ctx context.Context) (map[string]int
|
||||
}
|
||||
|
||||
func getBackfillReleaseTimeout(cfg config.View) time.Duration {
|
||||
const (
|
||||
name = "pendingReleaseTimeout"
|
||||
// Default timeout to release backfill. This value
|
||||
// will be used if pendingReleaseTimeout is not configured.
|
||||
defaultpendingReleaseTimeout time.Duration = 1 * time.Minute
|
||||
)
|
||||
|
||||
if !cfg.IsSet(name) {
|
||||
return defaultpendingReleaseTimeout
|
||||
}
|
||||
|
||||
return cfg.GetDuration(name)
|
||||
}
|
||||
|
||||
func getBackfillReleaseTimeoutFraction(cfg config.View) time.Duration {
|
||||
// Use a fraction 80% of pendingRelease Tickets TTL
|
||||
ttl := cfg.GetDuration("pendingReleaseTimeout") / 5 * 4
|
||||
ttl := getBackfillReleaseTimeout(cfg) / 5 * 4
|
||||
return ttl
|
||||
}
|
||||
|
@ -21,14 +21,13 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
utilTesting "open-match.dev/open-match/internal/util/testing"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
@ -127,8 +126,8 @@ func TestUpdateExistingBackfillNoError(t *testing.T) {
|
||||
ctx := utilTesting.NewContext(t)
|
||||
|
||||
// ARRANGE
|
||||
v := &wrappers.DoubleValue{Value: 123}
|
||||
a, err := ptypes.MarshalAny(v)
|
||||
v := &wrapperspb.DoubleValue{Value: 123}
|
||||
a, err := anypb.New(v)
|
||||
require.NoError(t, err)
|
||||
|
||||
existingBF := pb.Backfill{
|
||||
@ -137,7 +136,7 @@ func TestUpdateExistingBackfillNoError(t *testing.T) {
|
||||
SearchFields: &pb.SearchFields{
|
||||
Tags: []string{"123"},
|
||||
},
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"qwe": a,
|
||||
},
|
||||
}
|
||||
@ -151,7 +150,7 @@ func TestUpdateExistingBackfillNoError(t *testing.T) {
|
||||
SearchFields: &pb.SearchFields{
|
||||
Tags: []string{"456"},
|
||||
},
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"xyz": a,
|
||||
},
|
||||
}
|
||||
@ -172,8 +171,8 @@ func TestUpdateExistingBackfillNoError(t *testing.T) {
|
||||
require.NotNil(t, backfillActual.SearchFields)
|
||||
require.Equal(t, updateBF.SearchFields.Tags, backfillActual.SearchFields.Tags)
|
||||
|
||||
res := &wrappers.DoubleValue{}
|
||||
err = ptypes.UnmarshalAny(backfillActual.Extensions["xyz"], res)
|
||||
res := &wrapperspb.DoubleValue{}
|
||||
err = backfillActual.Extensions["xyz"].UnmarshalTo(res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, v.Value, res.Value)
|
||||
}
|
||||
@ -186,8 +185,8 @@ func TestUpdateBackfillDoNotExistCanNotUpdate(t *testing.T) {
|
||||
defer service.Close()
|
||||
ctx := utilTesting.NewContext(t)
|
||||
|
||||
v := &wrappers.DoubleValue{Value: 123}
|
||||
a, err := ptypes.MarshalAny(v)
|
||||
v := &wrapperspb.DoubleValue{Value: 123}
|
||||
a, err := anypb.New(v)
|
||||
require.NoError(t, err)
|
||||
|
||||
updateBF := pb.Backfill{
|
||||
@ -196,7 +195,7 @@ func TestUpdateBackfillDoNotExistCanNotUpdate(t *testing.T) {
|
||||
SearchFields: &pb.SearchFields{
|
||||
Tags: []string{"456"},
|
||||
},
|
||||
Extensions: map[string]*any.Any{
|
||||
Extensions: map[string]*anypb.Any{
|
||||
"xyz": a,
|
||||
},
|
||||
}
|
||||
@ -377,10 +376,16 @@ func TestDeleteBackfill(t *testing.T) {
|
||||
expectedMessage: "",
|
||||
},
|
||||
{
|
||||
description: "empty id passed, no err expected",
|
||||
description: "empty id passed, err expected",
|
||||
backfillID: "",
|
||||
expectedCode: codes.OK,
|
||||
expectedMessage: "",
|
||||
expectedCode: codes.NotFound,
|
||||
expectedMessage: "Backfill id: not found",
|
||||
},
|
||||
{
|
||||
description: "wrong id passed, err expected",
|
||||
backfillID: "123456",
|
||||
expectedCode: codes.NotFound,
|
||||
expectedMessage: "Backfill id: 123456 not found",
|
||||
},
|
||||
}
|
||||
|
||||
@ -388,9 +393,9 @@ func TestDeleteBackfill(t *testing.T) {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
errActual := service.DeleteBackfill(ctx, tc.backfillID)
|
||||
require.NoError(t, errActual)
|
||||
if tc.expectedCode == codes.OK {
|
||||
require.NoError(t, errActual)
|
||||
|
||||
if tc.backfillID != "" {
|
||||
_, errGetTicket := service.GetTicket(ctx, tc.backfillID)
|
||||
require.Error(t, errGetTicket)
|
||||
require.Equal(t, codes.NotFound.String(), status.Convert(errGetTicket).Code().String())
|
||||
@ -398,6 +403,10 @@ func TestDeleteBackfill(t *testing.T) {
|
||||
_, err = redis.Int64(conn.Do("ZSCORE", backfillLastAckTime, tc.backfillID))
|
||||
require.Error(t, err)
|
||||
require.Equal(t, err.Error(), "redigo: nil returned")
|
||||
} else {
|
||||
require.Error(t, errActual)
|
||||
require.Equal(t, tc.expectedCode.String(), status.Convert(errActual).Code().String())
|
||||
require.Contains(t, status.Convert(errActual).Message(), tc.expectedMessage)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ type Service interface {
|
||||
|
||||
// GetBackfill gets the Backfill with the specified id from state storage.
|
||||
// This method fails if the Backfill does not exist.
|
||||
// Returns the Backfill and asossiated ticketIDs if they exist.
|
||||
// Returns the Backfill and associated ticketIDs if they exist.
|
||||
GetBackfill(ctx context.Context, id string) (*pb.Backfill, []string, error)
|
||||
|
||||
// GetBackfills returns multiple backfills from storage
|
||||
|
@ -41,11 +41,11 @@ var (
|
||||
|
||||
// NewMutex returns a new distributed mutex with given name
|
||||
func (rb *redisBackend) NewMutex(key string) RedisLocker {
|
||||
m := redsync.NewMutex(fmt.Sprintf("lock/%s", key), rs.WithExpiry(rb.cfg.GetDuration("backfillLockTimeout")))
|
||||
m := redsync.NewMutex(fmt.Sprintf("lock/%s", key), rs.WithExpiry(getBackfillLockTimeout(rb.cfg)))
|
||||
return redisBackend{mutex: m}
|
||||
}
|
||||
|
||||
//Lock locks r. In case it returns an error on failure, you may retry to acquire the lock by calling this method again.
|
||||
// Lock locks r. In case it returns an error on failure, you may retry to acquire the lock by calling this method again.
|
||||
func (rb redisBackend) Lock(ctx context.Context) error {
|
||||
return rb.mutex.LockContext(ctx)
|
||||
}
|
||||
@ -246,3 +246,18 @@ func handleConnectionClose(conn *redis.Conn) {
|
||||
}).Debug("failed to close redis client connection.")
|
||||
}
|
||||
}
|
||||
|
||||
func getBackfillLockTimeout(cfg config.View) time.Duration {
|
||||
const (
|
||||
name = "backfillLockTimeout"
|
||||
// Default timeout to lock backfill. This value
|
||||
// will be used if backfillLockTimeout is not configured.
|
||||
defaultBackfillLockTimeout time.Duration = 1 * time.Minute
|
||||
)
|
||||
|
||||
if !cfg.IsSet(name) {
|
||||
return defaultBackfillLockTimeout
|
||||
}
|
||||
|
||||
return cfg.GetDuration(name)
|
||||
}
|
||||
|
@ -20,11 +20,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"open-match.dev/open-match/internal/config"
|
||||
"open-match.dev/open-match/pkg/pb"
|
||||
)
|
||||
|
||||
@ -35,6 +36,7 @@ const (
|
||||
|
||||
// CreateTicket creates a new Ticket in the state storage. If the id already exists, it will be overwritten.
|
||||
func (rb *redisBackend) CreateTicket(ctx context.Context, ticket *pb.Ticket) error {
|
||||
|
||||
redisConn, err := rb.redisPool.GetContext(ctx)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Unavailable, "CreateTicket, id: %s, failed to connect to redis: %v", ticket.GetId(), err)
|
||||
@ -47,6 +49,10 @@ func (rb *redisBackend) CreateTicket(ctx context.Context, ticket *pb.Ticket) err
|
||||
return status.Errorf(codes.Internal, "%v", err)
|
||||
}
|
||||
|
||||
if value == nil {
|
||||
return status.Errorf(codes.Internal, "failed to marshal the ticket proto, id: %s: proto: Marshal called with nil", ticket.GetId())
|
||||
}
|
||||
|
||||
_, err = redisConn.Do("SET", ticket.GetId(), value)
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to set the value for ticket, id: %s", ticket.GetId())
|
||||
@ -99,12 +105,16 @@ func (rb *redisBackend) DeleteTicket(ctx context.Context, id string) error {
|
||||
}
|
||||
defer handleConnectionClose(&redisConn)
|
||||
|
||||
_, err = redisConn.Do("DEL", id)
|
||||
value, err := redis.Int(redisConn.Do("DEL", id))
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to delete the ticket from state storage, id: %s", id)
|
||||
return status.Errorf(codes.Internal, "%v", err)
|
||||
}
|
||||
|
||||
if value == 0 {
|
||||
return status.Errorf(codes.NotFound, "Ticket id: %s not found", id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -150,7 +160,7 @@ func (rb *redisBackend) GetIndexedIDSet(ctx context.Context) (map[string]struct{
|
||||
}
|
||||
defer handleConnectionClose(&redisConn)
|
||||
|
||||
ttl := rb.cfg.GetDuration("pendingReleaseTimeout")
|
||||
ttl := getBackfillReleaseTimeout(rb.cfg)
|
||||
curTime := time.Now()
|
||||
endTimeInt := curTime.Add(time.Hour).UnixNano()
|
||||
startTimeInt := curTime.Add(-ttl).UnixNano()
|
||||
@ -251,6 +261,10 @@ func (rb *redisBackend) UpdateAssignments(ctx context.Context, req *pb.AssignTic
|
||||
}
|
||||
}
|
||||
|
||||
if len(idsI) == 0 {
|
||||
return nil, nil, status.Error(codes.InvalidArgument, "AssignmentGroupTicketIds is empty")
|
||||
}
|
||||
|
||||
ticketBytes, err := redis.ByteSlices(redisConn.Do("MGET", idsI...))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -274,7 +288,7 @@ func (rb *redisBackend) UpdateAssignments(ctx context.Context, req *pb.AssignTic
|
||||
tickets = append(tickets, t)
|
||||
}
|
||||
}
|
||||
assignmentTimeout := rb.cfg.GetDuration("assignedDeleteTimeout") / time.Millisecond
|
||||
assignmentTimeout := getAssignedDeleteTimeout(rb.cfg) / time.Millisecond
|
||||
err = redisConn.Send("MULTI")
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "error starting redis multi")
|
||||
@ -438,3 +452,18 @@ func (rb *redisBackend) newExponentialBackoffStrategy() backoff.BackOff {
|
||||
backoffStrat.MaxElapsedTime = rb.cfg.GetDuration("backoff.maxElapsedTime")
|
||||
return backoff.BackOff(backoffStrat)
|
||||
}
|
||||
|
||||
func getAssignedDeleteTimeout(cfg config.View) time.Duration {
|
||||
const (
|
||||
name = "assignedDeleteTimeout"
|
||||
// Default timeout to delete tickets after assignment. This value
|
||||
// will be used if assignedDeleteTimeout is not configured.
|
||||
defaultAssignedDeleteTimeout time.Duration = 10 * time.Minute
|
||||
)
|
||||
|
||||
if !cfg.IsSet(name) {
|
||||
return defaultAssignedDeleteTimeout
|
||||
}
|
||||
|
||||
return cfg.GetDuration(name)
|
||||
}
|
||||
|
@ -75,7 +75,8 @@ func TestTicketLifecycle(t *testing.T) {
|
||||
|
||||
// Validate nonexisting Ticket deletion
|
||||
err = service.DeleteTicket(ctx, id)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, status.Code(err), codes.NotFound)
|
||||
|
||||
// Validate nonexisting Ticket deindexing
|
||||
err = service.DeindexTicket(ctx, id)
|
||||
@ -227,6 +228,23 @@ func TestUpdateAssignments(t *testing.T) {
|
||||
assignedTicketsIDs: []string{"1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "empty ticketIds, error expected",
|
||||
request: &pb.AssignTicketsRequest{
|
||||
Assignments: []*pb.AssignmentGroup{
|
||||
{
|
||||
TicketIds: []string{},
|
||||
Assignment: &pb.Assignment{Connection: "2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: expected{
|
||||
resp: nil,
|
||||
errCode: codes.InvalidArgument,
|
||||
errMessage: "AssignmentGroupTicketIds is empty",
|
||||
assignedTicketsIDs: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "nil assignment, error expected",
|
||||
request: &pb.AssignTicketsRequest{
|
||||
@ -540,10 +558,16 @@ func TestDeleteTicket(t *testing.T) {
|
||||
expectedMessage: "",
|
||||
},
|
||||
{
|
||||
description: "empty id passed, no err expected",
|
||||
description: "empty id passed, err expected",
|
||||
ticketID: "",
|
||||
expectedCode: codes.OK,
|
||||
expectedMessage: "",
|
||||
expectedCode: codes.NotFound,
|
||||
expectedMessage: "Ticket id: not found",
|
||||
},
|
||||
{
|
||||
description: "wrong id passed, err expected",
|
||||
ticketID: "123456",
|
||||
expectedCode: codes.NotFound,
|
||||
expectedMessage: "Ticket id: 123456 not found",
|
||||
},
|
||||
}
|
||||
|
||||
@ -554,11 +578,9 @@ func TestDeleteTicket(t *testing.T) {
|
||||
if tc.expectedCode == codes.OK {
|
||||
require.NoError(t, errActual)
|
||||
|
||||
if tc.ticketID != "" {
|
||||
_, errGetTicket := service.GetTicket(ctx, tc.ticketID)
|
||||
require.Error(t, errGetTicket)
|
||||
require.Equal(t, codes.NotFound.String(), status.Convert(errGetTicket).Code().String())
|
||||
}
|
||||
_, errGetTicket := service.GetTicket(ctx, tc.ticketID)
|
||||
require.Error(t, errGetTicket)
|
||||
require.Equal(t, codes.NotFound.String(), status.Convert(errGetTicket).Code().String())
|
||||
} else {
|
||||
require.Error(t, errActual)
|
||||
require.Equal(t, tc.expectedCode.String(), status.Convert(errActual).Code().String())
|
||||
@ -952,7 +974,7 @@ func createRedis(t *testing.T, withSentinel bool, withPassword string) (config.V
|
||||
}
|
||||
}
|
||||
|
||||
//nolint: unparam
|
||||
// nolint: unparam
|
||||
// generateTickets creates a proper amount of ticket, returns a slice of tickets and a slice of tickets ids
|
||||
func generateTickets(ctx context.Context, t *testing.T, service Service, amount int) ([]*pb.Ticket, []string) {
|
||||
tickets := make([]*pb.Ticket, 0, amount)
|
||||
|
@ -1,57 +0,0 @@
|
||||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"contrib.go.opencensus.io/exporter/jaeger"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
func bindJaeger(p Params, b Bindings) error {
|
||||
cfg := p.Config()
|
||||
|
||||
if !cfg.GetBool("telemetry.jaeger.enable") {
|
||||
logger.Info("Jaeger Tracing: Disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
agentEndpointURI := cfg.GetString("telemetry.jaeger.agentEndpoint")
|
||||
collectorEndpointURI := cfg.GetString("telemetry.jaeger.collectorEndpoint")
|
||||
serviceName := p.ServiceName()
|
||||
|
||||
logger.WithFields(logrus.Fields{
|
||||
"agentEndpoint": agentEndpointURI,
|
||||
"collectorEndpoint": collectorEndpointURI,
|
||||
"serviceName": serviceName,
|
||||
}).Info("Jaeger Tracing: ENABLED")
|
||||
|
||||
je, err := jaeger.NewExporter(jaeger.Options{
|
||||
AgentEndpoint: agentEndpointURI,
|
||||
CollectorEndpoint: collectorEndpointURI,
|
||||
ServiceName: serviceName,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to create the Jaeger exporter")
|
||||
}
|
||||
|
||||
trace.RegisterExporter(je)
|
||||
b.AddCloser(func() {
|
||||
trace.UnregisterExporter(je)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
@ -36,7 +36,6 @@ var (
|
||||
func Setup(p Params, b Bindings) error {
|
||||
bindings := []func(p Params, b Bindings) error{
|
||||
configureOpenCensus,
|
||||
bindJaeger,
|
||||
bindPrometheus,
|
||||
bindStackDriverMetrics,
|
||||
bindOpenCensusAgent,
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
grpc_validator "github.com/grpc-ecosystem/go-grpc-middleware/validator"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
@ -50,7 +51,7 @@ func NewGRPCDialOptions(grpcLogger *logrus.Entry) []grpc.DialOption {
|
||||
grpc_tracing.UnaryClientInterceptor(),
|
||||
}
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(si...)),
|
||||
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(ui...)),
|
||||
grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`),
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package matchfunction provides helper methods to simplify authoring a match fuction.
|
||||
// Package matchfunction provides helper methods to simplify authoring a match function.
|
||||
package matchfunction
|
||||
|
||||
import (
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user