diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index d92a420a40a..00000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# Each line is a file pattern followed by one or more owners. -# https://help.github.com/en/articles/about-code-owners - -* @feast-dev/maintainers diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d210cbe2f41..e8d00798c0c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,9 +2,10 @@ 1. Ensure that your code follows our code conventions: https://github.com/feast-dev/feast/blob/master/CONTRIBUTING.md#code-style--linting 2. Run unit tests and ensure that they are passing: https://github.com/feast-dev/feast/blob/master/CONTRIBUTING.md#unit-tests -3. If your change introduces any API changes, make sure to update the integration tests scripts here: https://github.com/feast-dev/feast/tree/master/sdk/python/tests or https://github.com/feast-dev/feast/tree/master/sdk/go +3. If your change introduces any API changes, make sure to update the integration tests here: https://github.com/feast-dev/feast/tree/master/sdk/python/tests 4. Make sure documentation is updated for your PR! -5. Make sure you have signed the CLA https://cla.developers.google.com/clas +5. Make sure your commits are signed: https://github.com/feast-dev/feast/blob/master/CONTRIBUTING.md#signing-off-commits +6. Make sure your PR title follows conventional commits (e.g. fix: [description] vs feat: [description]) --> @@ -16,16 +17,3 @@ Usage: `Fixes #`, or `Fixes (paste link of issue)`. --> Fixes # - -**Does this PR introduce a user-facing change?**: - -```release-note - -``` diff --git a/.github/workflows/assign_issues.yml b/.github/workflows/assign_issues.yml deleted file mode 100644 index f8702e2485c..00000000000 --- a/.github/workflows/assign_issues.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Issue assignment - -on: - issues: - types: [opened] - -jobs: - auto-assign: - runs-on: ubuntu-latest - steps: - - name: 'Auto-assign issue' - uses: pozil/auto-assign-issue@v1.1.0 - with: - assignees: achals, woop, tsotnet, felix, felixwang9817, adchia - numOfAssignee: 1 diff --git a/.github/workflows/assign_reviewers.yml b/.github/workflows/assign_reviewers.yml deleted file mode 100644 index ab776add0dc..00000000000 --- a/.github/workflows/assign_reviewers.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: 'Assign Reviewers' -on: - pull_request_target: - types: - - opened - - ready_for_review - -jobs: - add-reviews: - runs-on: ubuntu-latest - steps: - - uses: kentaro-m/auto-assign-action@v1.2.0 diff --git a/.github/workflows/java_master_only.yml b/.github/workflows/java_master_only.yml index 04313c4120c..a856fbe2cba 100644 --- a/.github/workflows/java_master_only.yml +++ b/.github/workflows/java_master_only.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v2 with: submodules: 'true' - - uses: google-github-actions/setup-gcloud@master + - uses: google-github-actions/setup-gcloud@v0 with: version: '290.0.1' export_default_credentials: true diff --git a/.github/workflows/java_pr.yml b/.github/workflows/java_pr.yml index 081a4f42744..9906c246ecd 100644 --- a/.github/workflows/java_pr.yml +++ b/.github/workflows/java_pr.yml @@ -53,8 +53,9 @@ jobs: integration-test: # all jobs MUST have this if check for 'ok-to-test' or 'approved' for security purposes. - if: (github.event.action == 'labeled' && (github.event.label.name == 'approved' || github.event.label.name == 'ok-to-test')) - || (github.event.action != 'labeled' && (contains(github.event.pull_request.labels.*.name, 'ok-to-test') || contains(github.event.pull_request.labels.*.name, 'approved'))) + if: + (github.event.action == 'labeled' && (github.event.label.name == 'lgtm' || github.event.label.name == 'approved' || github.event.label.name == 'ok-to-test')) || + (github.event.action != 'labeled' && (contains(github.event.pull_request.labels.*.name, 'ok-to-test') || contains(github.event.pull_request.labels.*.name, 'approved'))) runs-on: ubuntu-latest needs: unit-test-java steps: diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index c1808bf03a7..971282966c5 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -15,6 +15,11 @@ jobs: with: python-version: "3.7" architecture: x64 + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: 1.17.7 - name: Upgrade pip version run: | pip install --upgrade "pip>=21.3.1" @@ -35,16 +40,30 @@ jobs: - name: Install pip-tools run: pip install pip-tools - name: Install dependencies - run: make install-python-ci-dependencies + run: | + make compile-protos-go + make install-python-ci-dependencies - name: Lint python run: make lint-python lint-go: - container: gcr.io/kf-feast/feast-ci:latest - runs-on: [ubuntu-latest] + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: 1.17.7 + - name: Setup Python + id: setup-python + uses: actions/setup-python@v2 + with: + python-version: "3.7" + - name: Upgrade pip version + run: | + pip install --upgrade "pip>=21.3.1" - name: Install dependencies - run: make install-go-ci-dependencies + run: make install-go-proto-dependencies - name: Lint go run: make lint-go \ No newline at end of file diff --git a/.github/workflows/master_only.yml b/.github/workflows/master_only.yml index e7a89815fe4..5546686b247 100644 --- a/.github/workflows/master_only.yml +++ b/.github/workflows/master_only.yml @@ -54,17 +54,28 @@ jobs: docker push $ECR_REGISTRY/$ECR_REPOSITORY:${{ steps.image-tag.outputs.DOCKER_IMAGE_TAG }} outputs: DOCKER_IMAGE_TAG: ${{ steps.image-tag.outputs.DOCKER_IMAGE_TAG }} - integration-test-python: + integration-test-python-and-go: needs: build-lambda-docker-image runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - python-version: [ 3.7, 3.8, 3.9 ] + python-version: [ "3.7", "3.8", "3.9", "3.10" ] + go-version: [ 1.17.0 ] os: [ ubuntu-latest ] env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python-version }} + services: + redis: + image: redis + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 steps: - uses: actions/checkout@v2 - name: Setup Python @@ -73,6 +84,11 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v0 with: @@ -110,16 +126,11 @@ jobs: run: pip install pip-tools - name: Install dependencies run: make install-python-ci-dependencies - - name: Start Redis - uses: supercharge/redis-github-action@1.4.0 - with: - redis-version: ${{ matrix.redis-version }} - redis-port: 12345 - name: Setup Redis Cluster run: | docker pull vishnunair/docker-redis-cluster:latest docker run -d -p 6001:6379 -p 6002:6380 -p 6003:6381 -p 6004:6382 -p 6005:6383 -p 6006:6384 --name redis-cluster vishnunair/docker-redis-cluster - - name: Test python + - name: Test python and go env: FEAST_SERVER_DOCKER_IMAGE_TAG: ${{ needs.build-lambda-docker-image.outputs.DOCKER_IMAGE_TAG }} FEAST_USAGE: "False" @@ -173,7 +184,7 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@master + uses: google-github-actions/setup-gcloud@v0 with: project_id: ${{ secrets.GCP_PROJECT_ID }} service_account_key: ${{ secrets.GCP_SA_KEY }} @@ -194,4 +205,4 @@ jobs: make push-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${GITHUB_SHA} docker tag ${REGISTRY}/${{ matrix.component }}:${GITHUB_SHA} ${REGISTRY}/${{ matrix.component }}:develop - docker push ${REGISTRY}/${{ matrix.component }}:develop + docker push ${REGISTRY}/${{ matrix.component }}:develop \ No newline at end of file diff --git a/.github/workflows/pr_integration_tests.yml b/.github/workflows/pr_integration_tests.yml index 4c758d7601a..2373f96ba7a 100644 --- a/.github/workflows/pr_integration_tests.yml +++ b/.github/workflows/pr_integration_tests.yml @@ -14,9 +14,10 @@ on: jobs: build-docker-image: - # all jobs MUST have this if check for 'ok-to-test' or 'approved' for security purposes. - if: (github.event.action == 'labeled' && (github.event.label.name == 'approved' || github.event.label.name == 'ok-to-test')) - || (github.event.action != 'labeled' && (contains(github.event.pull_request.labels.*.name, 'ok-to-test') || contains(github.event.pull_request.labels.*.name, 'approved'))) + # all jobs MUST have this if check for 'ok-to-test' or 'approved' or 'lgtm' for security purposes. + if: + (github.event.action == 'labeled' && (github.event.label.name == 'lgtm' || github.event.label.name == 'approved' || github.event.label.name == 'ok-to-test')) || + (github.event.action != 'labeled' && (contains(github.event.pull_request.labels.*.name, 'ok-to-test') || contains(github.event.pull_request.labels.*.name, 'approved'))) runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -71,19 +72,30 @@ jobs: outputs: DOCKER_IMAGE_TAG: ${{ steps.image-tag.outputs.DOCKER_IMAGE_TAG }} integration-test-python: - # all jobs MUST have this if check for 'ok-to-test' or 'approved' for security purposes. - if: (github.event.action == 'labeled' && (github.event.label.name == 'approved' || github.event.label.name == 'ok-to-test')) - || (github.event.action != 'labeled' && (contains(github.event.pull_request.labels.*.name, 'ok-to-test') || contains(github.event.pull_request.labels.*.name, 'approved'))) + # all jobs MUST have this if check for 'ok-to-test' or 'approved' or 'lgtm' for security purposes. + if: + (github.event.action == 'labeled' && (github.event.label.name == 'lgtm' || github.event.label.name == 'approved' || github.event.label.name == 'ok-to-test')) || + (github.event.action != 'labeled' && (contains(github.event.pull_request.labels.*.name, 'ok-to-test') || contains(github.event.pull_request.labels.*.name, 'approved'))) needs: build-docker-image runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - python-version: [ 3.7 ] + python-version: [ "3.7" ] os: [ ubuntu-latest ] env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python-version }} + services: + redis: + image: redis + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 steps: - uses: actions/checkout@v2 with: @@ -92,17 +104,17 @@ jobs: # code from the PR. ref: refs/pull/${{ github.event.pull_request.number }}/merge submodules: recursive - - name: Start Redis - uses: supercharge/redis-github-action@1.4.0 - with: - redis-version: ${{ matrix.redis-version }} - redis-port: 12345 - name: Setup Python uses: actions/setup-python@v2 id: setup-python with: python-version: ${{ matrix.python-version }} architecture: x64 + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: 1.17.7 - name: Set up gcloud SDK uses: google-github-actions/setup-gcloud@v0 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0d7476a82ba..f8a8d40fb34 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -64,7 +64,7 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@master + uses: google-github-actions/setup-gcloud@v0 with: project_id: ${{ secrets.GCP_PROJECT_ID }} service_account_key: ${{ secrets.GCP_SA_KEY }} @@ -107,7 +107,7 @@ jobs: VERSION_WITHOUT_PREFIX: ${{ needs.get-version.outputs.version_without_prefix }} steps: - uses: actions/checkout@v2 - - uses: google-github-actions/setup-gcloud@master + - uses: google-github-actions/setup-gcloud@v0 with: version: '290.0.1' export_default_credentials: true @@ -126,37 +126,85 @@ jobs: run: ./infra/scripts/helm/push-helm-charts.sh $VERSION_WITHOUT_PREFIX publish-python-sdk: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + python-version: [ "3.7", "3.8", "3.9", "3.10" ] + os: [ ubuntu-latest, macOS-latest ] + compile-go: [ True ] + include: + - python-version: "3.7" + os: ubuntu-latest + compile-go: False env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - container: python:3.7 + COMPILE_GO: ${{ matrix.compile-go }} steps: - uses: actions/checkout@v2 + - name: Setup Python + id: setup-python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: 1.17.7 + - name: Upgrade pip version + run: | + pip install --upgrade "pip>=21.3.1" - name: Install pip-tools run: pip install pip-tools - name: Install dependencies - run: make install-python-ci-dependencies PYTHON=3.7 + run: make install-python-ci-dependencies PYTHON=${{ matrix.python-version }} - name: Publish Python Package run: | cd sdk/python python3 -m pip install --user --upgrade setuptools wheel twine python3 setup.py sdist bdist_wheel - python3 -m twine upload --verbose dist/* + python3 -m twine upload --verbose dist/*.whl publish-python-sdk-no-telemetry: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + python-version: [ "3.7", "3.8", "3.9", "3.10" ] + os: [ ubuntu-latest, macOS-latest ] + compile-go: [ True ] + include: + - python-version: "3.7" + os: ubuntu-latest + compile-go: False needs: get-version env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - container: python:3.7 + COMPILE_GO: ${{ matrix.compile-go }} steps: - uses: actions/checkout@v2 + - name: Setup Python + id: setup-python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: 1.17.7 + - name: Upgrade pip version + run: | + pip install --upgrade "pip>=21.3.1" - name: Install pip-tools run: pip install pip-tools - name: Install dependencies - run: make install-python-ci-dependencies PYTHON=3.7 + run: make install-python-ci-dependencies PYTHON=${{ matrix.python-version }} - name: Publish Python Package env: SETUPTOOLS_SCM_PRETEND_VERSION: ${{ needs.get-version.outputs.version_without_prefix }} @@ -166,7 +214,7 @@ jobs: sed -i 's/NAME = "feast"/NAME = "feast-no-telemetry"/g' setup.py python3 -m pip install --user --upgrade setuptools wheel twine python3 setup.py sdist bdist_wheel - python3 -m twine upload --verbose dist/* + python3 -m twine upload --verbose dist/*.whl publish-java-sdk: container: maven:3.6-jdk-11 @@ -204,3 +252,22 @@ jobs: mkdir -p /root/.m2/ echo -n "$MAVEN_SETTINGS" > /root/.m2/settings.xml infra/scripts/publish-java-sdk.sh --revision ${VERSION_WITHOUT_PREFIX} --gpg-key-import-dir /root + + publish-web-ui-npm: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '17.x' + registry-url: 'https://registry.npmjs.org' + - name: Install yarn dependencies + working-directory: ./ui + run: yarn install + - name: Build yarn rollup + working-directory: ./ui + run: yarn build:lib + - name: Publish UI package + run: npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d66f895bf54..2f4d15590a1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,4 +40,4 @@ jobs: - name: Release if: github.event.inputs.dry_run == 'false' run: | - npx -p @semantic-release/changelog -p @semantic-release/git -p @semantic-release/exec -p semantic-release semantic-release \ No newline at end of file + npx -p @semantic-release/changelog -p @semantic-release/git -p @semantic-release/exec -p semantic-release semantic-release diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index d9552e175e7..8f37e2e2a36 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.7, 3.8, 3.9 ] + python-version: [ "3.7", "3.8", "3.9", "3.10" ] os: [ ubuntu-latest, macOS-latest] env: OS: ${{ matrix.os }} @@ -20,6 +20,11 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: 1.17.7 - name: Upgrade pip version run: | pip install --upgrade "pip>=21.3.1" @@ -61,11 +66,23 @@ jobs: unit-test-go: runs-on: ubuntu-latest - container: gcr.io/kf-feast/feast-ci:latest steps: - uses: actions/checkout@v2 + - name: Setup Python + id: setup-python + uses: actions/setup-python@v2 + with: + python-version: "3.7" + - name: Upgrade pip version + run: | + pip install --upgrade "pip>=21.3.1" + - name: Setup Go + id: setup-go + uses: actions/setup-go@v2 + with: + go-version: 1.17.7 - name: Install dependencies - run: make install-go-ci-dependencies + run: make install-go-proto-dependencies - name: Compile protos run: make compile-protos-go - name: Test diff --git a/.gitignore b/.gitignore index 05c73a42951..0f3165e8414 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,7 @@ coverage.xml .hypothesis/ .pytest_cache/ infra/scripts/*.conf +go/cmd/server/logging/feature_repo/data/ # Translations *.mo @@ -186,6 +187,7 @@ dmypy.json sdk/python/docs/html sdk/python/feast/protos/ sdk/go/protos/ +go/protos/ #benchmarks .benchmarks @@ -203,7 +205,7 @@ ui/.pnp ui/.pnp.js ui/coverage ui/build -ui/feature_repo/data/online.db +ui/feature_repo/data/online.db ui/feature_repo/registry.db ui/.vercel @@ -218,3 +220,5 @@ ui/.vercel **/yarn-debug.log* **/yarn-error.log* +# Go subprocess binaries (built during feast pip package building) +sdk/python/feast/binaries/ diff --git a/.prow/config.yaml b/.prow/config.yaml index 8b3905e43bb..21adb54fda3 100644 --- a/.prow/config.yaml +++ b/.prow/config.yaml @@ -60,7 +60,6 @@ tide: - do-not-merge/invalid-owners-file - do-not-merge/work-in-progress - needs-rebase - - needs-kind merge_method: feast-dev/feast: squash feast-dev/feast-spark: squash diff --git a/.prow/plugins.yaml b/.prow/plugins.yaml index 0dbf0f4c72b..eca8851c67d 100644 --- a/.prow/plugins.yaml +++ b/.prow/plugins.yaml @@ -12,8 +12,6 @@ plugins: - wip - trigger - config-updater - - require-matching-label - - release-note feast-dev/feast-spark: - approve - assign @@ -27,8 +25,6 @@ plugins: - wip - trigger - config-updater - - require-matching-label - - release-note config_updater: maps: @@ -46,15 +42,3 @@ external_plugins: - name: needs-rebase events: - pull_request - -require_matching_label: -- missing_label: needs-kind - org: feast-dev - repo: feast - prs: true - regexp: ^kind/ -- missing_label: needs-kind - org: feast-dev - repo: feast-spark - prs: true - regexp: ^kind/ diff --git a/.releaserc.js b/.releaserc.js index 60a8616e073..8cdcc1f2779 100644 --- a/.releaserc.js +++ b/.releaserc.js @@ -22,12 +22,26 @@ possible_branches = [{name: "master"}, {name: current_branch}] module.exports = { branches: possible_branches, plugins: [ - "@semantic-release/commit-analyzer", + // Try to guess the type of release we should be doing (minor, patch) + ["@semantic-release/commit-analyzer", { + // Ensure that breaking changes trigger minor instead of major releases + "releaseRules": [ + {breaking: true, release: 'minor'}, + {tag: 'Breaking', release: 'minor'}, + ] + }], + ["@semantic-release/exec", { + // Validate the type of release we are doing "verifyReleaseCmd": "./infra/scripts/validate-release.sh ${nextRelease.type} " + current_branch, - "prepareCmd": "python ./infra/scripts/version_bump/bump_file_versions.py ${lastRelease.version} ${nextRelease.version}" + + // Bump all version files + "prepareCmd": "python ./infra/scripts/release/bump_file_versions.py ${lastRelease.version} ${nextRelease.version}" }], + "@semantic-release/release-notes-generator", + + // Update the changelog [ "@semantic-release/changelog", { @@ -35,6 +49,8 @@ module.exports = { changelogTitle: "# Changelog", } ], + + // Make a git commit, tag, and push the changes [ "@semantic-release/git", { @@ -46,7 +62,21 @@ module.exports = { message: "chore(release): release ${nextRelease.version}\n\n${nextRelease.notes}" } ], - "@semantic-release/github" + + // Publish a GitHub release (but don't spam issues/PRs with comments) + [ + "@semantic-release/github", + { + successComment: false, + failComment: false, + failTitle: false, + labels: false, + } + ], + + // For some reason all patches are tagged as pre-release. This step undoes that. + ["@semantic-release/exec", { + "publishCmd": "python ./infra/scripts/release/unset_prerelease.py ${nextRelease.version}" + }], ] } - diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b8d2f0500..bcb6f8cde3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,81 @@ # Changelog +# [0.20.0](https://github.com/feast-dev/feast/compare/v0.19.0...v0.20.0) (2022-04-14) + + +### Bug Fixes + +* Add inlined data sources to the top level registry ([#2456](https://github.com/feast-dev/feast/issues/2456)) ([356788a](https://github.com/feast-dev/feast/commit/356788a4d3c3677f60512b3e841498245289d9a2)) +* Add new value types to types.ts for web ui ([#2463](https://github.com/feast-dev/feast/issues/2463)) ([ad5694e](https://github.com/feast-dev/feast/commit/ad5694e601559ca1d8f8d3c91307c3c2cae1c69a)) +* Add PushSource proto and Python class ([#2428](https://github.com/feast-dev/feast/issues/2428)) ([9a4bd63](https://github.com/feast-dev/feast/commit/9a4bd63f62b54b76148c069c7665a3067553c456)) +* Add spark to lambda dockerfile ([#2480](https://github.com/feast-dev/feast/issues/2480)) ([514666f](https://github.com/feast-dev/feast/commit/514666f31cf6456dee59a5db750d8bd4ec63d8be)) +* Added private_key auth for Snowflake ([#2508](https://github.com/feast-dev/feast/issues/2508)) ([c42c9b0](https://github.com/feast-dev/feast/commit/c42c9b0f2a962e428d9af0d3e7ba080a62d77008)) +* Added Redshift and Spark typecheck to data_source event_timestamp_col inference ([#2389](https://github.com/feast-dev/feast/issues/2389)) ([04dea73](https://github.com/feast-dev/feast/commit/04dea732a495dfc8fa3dd006c89f73c6d08097c5)) +* Building of go extension fails ([#2448](https://github.com/feast-dev/feast/issues/2448)) ([7d1efd5](https://github.com/feast-dev/feast/commit/7d1efd56387b4a8c373c69f062ea31214f33c5f1)) +* Bump the number of versions bumps expected to 27 ([#2549](https://github.com/feast-dev/feast/issues/2549)) ([ecc9938](https://github.com/feast-dev/feast/commit/ecc9938774e9446f54484272bb3677e8d2fc1682)) +* Create __init__ files for the proto-generated python dirs ([#2410](https://github.com/feast-dev/feast/issues/2410)) ([e17028d](https://github.com/feast-dev/feast/commit/e17028dbb90cb88d9df9a9769abbd90c5c301563)) +* Don't prevent apply from running given duplicate empty names in data sources. Also fix repeated apply of Spark data source. ([#2415](https://github.com/feast-dev/feast/issues/2415)) ([b95f441](https://github.com/feast-dev/feast/commit/b95f4410ee91069ff84e81d2d5f3e9329edc8626)) +* Dynamodb deduplicate batch write request by partition keys ([#2515](https://github.com/feast-dev/feast/issues/2515)) ([70d4a13](https://github.com/feast-dev/feast/commit/70d4a1335312747521fc57e7742abf7eb85c12a6)) +* Ensure that __init__ files exist in proto dirs ([#2433](https://github.com/feast-dev/feast/issues/2433)) ([9b94f7b](https://github.com/feast-dev/feast/commit/9b94f7b35221af0bf1f813ab47e2f52e37a79ca6)) +* Fix DataSource constructor to unbreak custom data sources ([#2492](https://github.com/feast-dev/feast/issues/2492)) ([712653e](https://github.com/feast-dev/feast/commit/712653e91cc4dc51174058a850f00a471c7269b9)) +* Fix default feast apply path without any extras ([#2373](https://github.com/feast-dev/feast/issues/2373)) ([6ba7fc7](https://github.com/feast-dev/feast/commit/6ba7fc789da34f0d239d7cae1b3a95e14eae9e2f)) +* Fix definitions.py with new definition ([#2541](https://github.com/feast-dev/feast/issues/2541)) ([eefc34a](https://github.com/feast-dev/feast/commit/eefc34a5da978ccc686bbc2586b4af5de3917ff1)) +* Fix entity row to use join key instead of name ([#2521](https://github.com/feast-dev/feast/issues/2521)) ([c22fa2c](https://github.com/feast-dev/feast/commit/c22fa2c42c2c2b6b84c1876f12d690806ea8d431)) +* Fix Java Master ([#2499](https://github.com/feast-dev/feast/issues/2499)) ([e083458](https://github.com/feast-dev/feast/commit/e0834587ec1450026a17a7c18f2708d44410da07)) +* Fix registry proto ([#2435](https://github.com/feast-dev/feast/issues/2435)) ([ea6a9b2](https://github.com/feast-dev/feast/commit/ea6a9b2034c35bf36ee5073fad93dde52279ebcd)) +* Fix some inconsistencies in the docs and comments in the code ([#2444](https://github.com/feast-dev/feast/issues/2444)) ([ad008bf](https://github.com/feast-dev/feast/commit/ad008bfd1d826a72247accf993a58505a9e2b308)) +* Fix spark docs ([#2382](https://github.com/feast-dev/feast/issues/2382)) ([d4a606a](https://github.com/feast-dev/feast/commit/d4a606ad68fedeb12839038a956043a66e6f518f)) +* Fix Spark template to work correctly on feast init -t spark ([#2393](https://github.com/feast-dev/feast/issues/2393)) ([ae133fd](https://github.com/feast-dev/feast/commit/ae133fd3ee55da3ff2fb2848456de527935ee94f)) +* Fix the feature repo fixture used by java tests ([#2469](https://github.com/feast-dev/feast/issues/2469)) ([32e925e](https://github.com/feast-dev/feast/commit/32e925e5edebef98449e295e2b1cf0f98ceb8d77)) +* Fix unhashable Snowflake and Redshift sources ([cd8f1c9](https://github.com/feast-dev/feast/commit/cd8f1c9d3a07231343631692b6de67e7f5c93b8f)) +* Fixed bug in passing config file params to snowflake python connector ([#2503](https://github.com/feast-dev/feast/issues/2503)) ([34f2b59](https://github.com/feast-dev/feast/commit/34f2b591bc8de3af59dfd0031ff803b4fe028abd)) +* Fixing Spark template to include source name ([#2381](https://github.com/feast-dev/feast/issues/2381)) ([a985f1d](https://github.com/feast-dev/feast/commit/a985f1d310915bafba3074f9cea776232b956e29)) +* Make name a keyword arg for the Entity class ([#2467](https://github.com/feast-dev/feast/issues/2467)) ([43847de](https://github.com/feast-dev/feast/commit/43847dea74b25bb2081d76b1fd5e43da8cbc0781)) +* Making a name for data sources not a breaking change ([#2379](https://github.com/feast-dev/feast/issues/2379)) ([71d7ae2](https://github.com/feast-dev/feast/commit/71d7ae26f0357646a15a41f7c2b53a0cab1b7c12)) +* Minor link fix in `CONTRIBUTING.md` ([#2481](https://github.com/feast-dev/feast/issues/2481)) ([2917e27](https://github.com/feast-dev/feast/commit/2917e272ab538955d564552a56ef36bb3f75f646)) +* Preserve ordering of features in _get_column_names ([#2457](https://github.com/feast-dev/feast/issues/2457)) ([495b435](https://github.com/feast-dev/feast/commit/495b4353051d9d48886407f2ca7de19c3eb458d7)) +* Relax click python requirement to >=7 ([#2450](https://github.com/feast-dev/feast/issues/2450)) ([f202f92](https://github.com/feast-dev/feast/commit/f202f928ff02f4a263f3b4ce450051e526304c51)) +* Remove date partition column field from datasources that don't s… ([#2478](https://github.com/feast-dev/feast/issues/2478)) ([ce35835](https://github.com/feast-dev/feast/commit/ce35835413d4f5bc174eb177e277be96e8bb9673)) +* Remove docker step from unit test workflow ([#2535](https://github.com/feast-dev/feast/issues/2535)) ([6f22f22](https://github.com/feast-dev/feast/commit/6f22f227a22bea6f9ef171764a4c5e3d74b310ea)) +* Remove spark from the AWS Lambda dockerfile ([#2498](https://github.com/feast-dev/feast/issues/2498)) ([6abae16](https://github.com/feast-dev/feast/commit/6abae16803ef4644c91822626820e99b2f7cfbbd)) +* Request data api update ([#2488](https://github.com/feast-dev/feast/issues/2488)) ([0c9e5b7](https://github.com/feast-dev/feast/commit/0c9e5b7e2132b619056e9b41519d54a93e977f6c)) +* Schema update ([#2509](https://github.com/feast-dev/feast/issues/2509)) ([cf7bbc2](https://github.com/feast-dev/feast/commit/cf7bbc2226e2c3d652df1ddfc411a1feadda26c4)) +* Simplify DataSource.from_proto logic ([#2424](https://github.com/feast-dev/feast/issues/2424)) ([6bda4d2](https://github.com/feast-dev/feast/commit/6bda4d2b2080e5a97333e14863f2235aed989661)) +* Snowflake api update ([#2487](https://github.com/feast-dev/feast/issues/2487)) ([1181a9e](https://github.com/feast-dev/feast/commit/1181a9e62335ee00ee54cd1bc88baa6297238988)) +* Support passing batch source to streaming sources for backfills ([#2523](https://github.com/feast-dev/feast/issues/2523)) ([90db1d1](https://github.com/feast-dev/feast/commit/90db1d1bb079a76a6a26a89a9c70b9f80bb8b08a)) +* Timestamp update ([#2486](https://github.com/feast-dev/feast/issues/2486)) ([bf23111](https://github.com/feast-dev/feast/commit/bf23111acedf0b5180e368e1cffbdeb0da5a8f30)) +* Typos in Feast UI error message ([#2432](https://github.com/feast-dev/feast/issues/2432)) ([e14369d](https://github.com/feast-dev/feast/commit/e14369def00c116e05c91475c29fa32ab2fa8aeb)) +* Update feature view APIs to prefer keyword args ([#2472](https://github.com/feast-dev/feast/issues/2472)) ([7c19cf7](https://github.com/feast-dev/feast/commit/7c19cf7fe3e42674a357e54a6576c772a7bcb107)) +* Update file api ([#2470](https://github.com/feast-dev/feast/issues/2470)) ([83a11c6](https://github.com/feast-dev/feast/commit/83a11c6b3af3b78653fe612989a5f5227cb773c1)) +* Update Makefile to cd into python dir before running commands ([#2437](https://github.com/feast-dev/feast/issues/2437)) ([ca32155](https://github.com/feast-dev/feast/commit/ca3215502bc4c92d0635efaceae22acc914c73a8)) +* Update redshift api ([#2479](https://github.com/feast-dev/feast/issues/2479)) ([4fa73a9](https://github.com/feast-dev/feast/commit/4fa73a9c1fc5f003a5662e497d77e69efdbae6c1)) +* Update some fields optional in UI parser ([#2380](https://github.com/feast-dev/feast/issues/2380)) ([cff7ac3](https://github.com/feast-dev/feast/commit/cff7ac3c6440a78a7fa460b2f19bc07d9ea5aab2)) +* Use a single version of jackson libraries and upgrade to 2.12.6.1 ([#2473](https://github.com/feast-dev/feast/issues/2473)) ([5be1cc6](https://github.com/feast-dev/feast/commit/5be1cc6768c123b592c26099d12f3469f575a52c)) +* Use dateutil parser to parse materialization times ([#2464](https://github.com/feast-dev/feast/issues/2464)) ([6c55e49](https://github.com/feast-dev/feast/commit/6c55e49898e9b5f5aa77fe87ac0807984937a708)) +* Use the correct dockerhub image tag when building feature servers ([#2372](https://github.com/feast-dev/feast/issues/2372)) ([0d62c1d](https://github.com/feast-dev/feast/commit/0d62c1d34b02cd67e13e545d081b90fe1562261e)) + + +### Features + +* Add `/write-to-online-store` method to the python feature server ([#2423](https://github.com/feast-dev/feast/issues/2423)) ([d2fb048](https://github.com/feast-dev/feast/commit/d2fb0487134f011c1a0f217f1a325e3bf6a52d27)) +* Add description, tags, owner fields to all feature view classes ([#2440](https://github.com/feast-dev/feast/issues/2440)) ([ed5e928](https://github.com/feast-dev/feast/commit/ed5e9282678c943c750c5e9d84037376dd1380d3)) +* Add DQM Logging on GRPC Server with FileLogStorage for Testing ([#2403](https://github.com/feast-dev/feast/issues/2403)) ([57a97d8](https://github.com/feast-dev/feast/commit/57a97d8e207e38876901b9a6b1d6e0f7cc6ce43d)) +* Add Feast types in preparation for changing type system ([#2475](https://github.com/feast-dev/feast/issues/2475)) ([4864252](https://github.com/feast-dev/feast/commit/4864252db4e8ef6effb596c689bd17ec884ebffe)) +* Add Field class ([#2500](https://github.com/feast-dev/feast/issues/2500)) ([1279612](https://github.com/feast-dev/feast/commit/1279612fe64d8d24fa57d873f4a617095adc5feb)) +* Add support for DynamoDB online_read in batches ([#2371](https://github.com/feast-dev/feast/issues/2371)) ([702ec49](https://github.com/feast-dev/feast/commit/702ec498eff2fb079d5403e9471b73ae840d6d7f)) +* Add Support for DynamodbOnlineStoreConfig endpoint_url parameter ([#2485](https://github.com/feast-dev/feast/issues/2485)) ([7b863d1](https://github.com/feast-dev/feast/commit/7b863d14e8442007b1403e467130b974b3aba078)) +* Add templating for dynamodb table name ([#2394](https://github.com/feast-dev/feast/issues/2394)) ([f591088](https://github.com/feast-dev/feast/commit/f59108806c6819bcd42828244a2abc66471cd8f8)) +* Allow local feature server to use Go feature server if enabled ([#2538](https://github.com/feast-dev/feast/issues/2538)) ([a2ef375](https://github.com/feast-dev/feast/commit/a2ef3755766a7224298f984a2cadb17829b2f3d2)) +* Allow using entity's join_key in get_online_features ([#2420](https://github.com/feast-dev/feast/issues/2420)) ([068c765](https://github.com/feast-dev/feast/commit/068c765ccf5f984bc0a73a8354711f39a5c17da7)) +* Data Source Api Update ([#2468](https://github.com/feast-dev/feast/issues/2468)) ([6b96b21](https://github.com/feast-dev/feast/commit/6b96b21a32cc6dc3b44b48289711a66b2c33512d)) +* Go server ([#2339](https://github.com/feast-dev/feast/issues/2339)) ([d12e7ef](https://github.com/feast-dev/feast/commit/d12e7ef3b9c79cae30a2401c9ae6c0ac783c4b6b)), closes [#2354](https://github.com/feast-dev/feast/issues/2354) [#2361](https://github.com/feast-dev/feast/issues/2361) [#2332](https://github.com/feast-dev/feast/issues/2332) [#2356](https://github.com/feast-dev/feast/issues/2356) [#2363](https://github.com/feast-dev/feast/issues/2363) [#2349](https://github.com/feast-dev/feast/issues/2349) [#2355](https://github.com/feast-dev/feast/issues/2355) [#2336](https://github.com/feast-dev/feast/issues/2336) [#2361](https://github.com/feast-dev/feast/issues/2361) [#2363](https://github.com/feast-dev/feast/issues/2363) [#2344](https://github.com/feast-dev/feast/issues/2344) [#2354](https://github.com/feast-dev/feast/issues/2354) [#2347](https://github.com/feast-dev/feast/issues/2347) [#2350](https://github.com/feast-dev/feast/issues/2350) [#2356](https://github.com/feast-dev/feast/issues/2356) [#2355](https://github.com/feast-dev/feast/issues/2355) [#2349](https://github.com/feast-dev/feast/issues/2349) [#2352](https://github.com/feast-dev/feast/issues/2352) [#2341](https://github.com/feast-dev/feast/issues/2341) [#2336](https://github.com/feast-dev/feast/issues/2336) [#2373](https://github.com/feast-dev/feast/issues/2373) [#2315](https://github.com/feast-dev/feast/issues/2315) [#2372](https://github.com/feast-dev/feast/issues/2372) [#2332](https://github.com/feast-dev/feast/issues/2332) [#2349](https://github.com/feast-dev/feast/issues/2349) [#2336](https://github.com/feast-dev/feast/issues/2336) [#2361](https://github.com/feast-dev/feast/issues/2361) [#2363](https://github.com/feast-dev/feast/issues/2363) [#2344](https://github.com/feast-dev/feast/issues/2344) [#2354](https://github.com/feast-dev/feast/issues/2354) [#2347](https://github.com/feast-dev/feast/issues/2347) [#2350](https://github.com/feast-dev/feast/issues/2350) [#2356](https://github.com/feast-dev/feast/issues/2356) [#2355](https://github.com/feast-dev/feast/issues/2355) [#2349](https://github.com/feast-dev/feast/issues/2349) [#2352](https://github.com/feast-dev/feast/issues/2352) [#2341](https://github.com/feast-dev/feast/issues/2341) [#2336](https://github.com/feast-dev/feast/issues/2336) [#2373](https://github.com/feast-dev/feast/issues/2373) [#2379](https://github.com/feast-dev/feast/issues/2379) [#2380](https://github.com/feast-dev/feast/issues/2380) [#2382](https://github.com/feast-dev/feast/issues/2382) [#2364](https://github.com/feast-dev/feast/issues/2364) [#2366](https://github.com/feast-dev/feast/issues/2366) [#2386](https://github.com/feast-dev/feast/issues/2386) +* Graduate write_to_online_store out of experimental status ([#2426](https://github.com/feast-dev/feast/issues/2426)) ([e7dd4b7](https://github.com/feast-dev/feast/commit/e7dd4b75ba0fbd86338aacf2ecd0cc8979dc803b)) +* Make feast PEP 561 compliant ([#2405](https://github.com/feast-dev/feast/issues/2405)) ([3c41f94](https://github.com/feast-dev/feast/commit/3c41f944c68fb6687389c0b154f7297941a1f398)), closes [#2420](https://github.com/feast-dev/feast/issues/2420) [#2418](https://github.com/feast-dev/feast/issues/2418) [#2425](https://github.com/feast-dev/feast/issues/2425) [#2426](https://github.com/feast-dev/feast/issues/2426) [#2427](https://github.com/feast-dev/feast/issues/2427) [#2431](https://github.com/feast-dev/feast/issues/2431) [#2433](https://github.com/feast-dev/feast/issues/2433) [#2420](https://github.com/feast-dev/feast/issues/2420) [#2418](https://github.com/feast-dev/feast/issues/2418) [#2425](https://github.com/feast-dev/feast/issues/2425) [#2426](https://github.com/feast-dev/feast/issues/2426) [#2427](https://github.com/feast-dev/feast/issues/2427) [#2431](https://github.com/feast-dev/feast/issues/2431) [#2433](https://github.com/feast-dev/feast/issues/2433) +* Makefile for contrib for Issue [#2364](https://github.com/feast-dev/feast/issues/2364) ([#2366](https://github.com/feast-dev/feast/issues/2366)) ([a02325b](https://github.com/feast-dev/feast/commit/a02325b20f4d1a949ebb1f26bd3b65a22e3ea4f3)) +* Support on demand feature views in go feature server ([#2494](https://github.com/feast-dev/feast/issues/2494)) ([6edd274](https://github.com/feast-dev/feast/commit/6edd274261689b8c67df31d598aa5d5b14dcf5f7)) +* Switch from Feature to Field ([#2514](https://github.com/feast-dev/feast/issues/2514)) ([6a03bed](https://github.com/feast-dev/feast/commit/6a03bed82bf408d2f46d209be7ac9524b4ea6dcd)) +* Use a daemon thread to monitor the go feature server exclusively ([#2391](https://github.com/feast-dev/feast/issues/2391)) ([0bb5e8c](https://github.com/feast-dev/feast/commit/0bb5e8c5a91f6f986f879f965b84e987e71a9d88)) + # [0.19.0](https://github.com/feast-dev/feast/compare/v0.18.0...v0.19.0) (2022-03-05) @@ -24,11 +100,11 @@ * Key ttl setting for redis online store ([#2341](https://github.com/feast-dev/feast/issues/2341)) ([236a108](https://github.com/feast-dev/feast/commit/236a108c87aed106e0a46e48172d31dc94ed9c2b)) * Metadata changes & making data sources top level objects to power Feast UI ([#2336](https://github.com/feast-dev/feast/issues/2336)) ([43da230](https://github.com/feast-dev/feast/commit/43da2302dfcbf3b5e56ed068021b5821d544c05f)) -## [v0.18.1](https://github.com/feast-dev/feast/tree/v0.18.1) (2022-02-15) +# [v0.18.1](https://github.com/feast-dev/feast/tree/v0.18.1) (2022-02-15) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.18.0...v0.18.1) -**Fixed bugs:** +### Bug Fixes - ODFVs raise a PerformanceWarning for very large sets of features [\#2293](https://github.com/feast-dev/feast/issues/2293) - Don't require `snowflake` to always be installed [\#2309](https://github.com/feast-dev/feast/pull/2309) ([judahrand](https://github.com/judahrand)) @@ -39,7 +115,7 @@ - Expose snowflake credentials for unit testing [\#2288](https://github.com/feast-dev/feast/pull/2288) ([sfc-gh-madkins](https://github.com/sfc-gh-madkins)) - Fix flaky tests \(test\_online\_store\_cleanup & test\_feature\_get\_online\_features\_types\_match\) [\#2276](https://github.com/feast-dev/feast/pull/2276) ([pyalex](https://github.com/pyalex)) -**Merged pull requests:** +### Merged Pull Requests - Remove old flag warning with the python feature server [\#2300](https://github.com/feast-dev/feast/pull/2300) ([adchia](https://github.com/adchia)) - Use an OFFLINE schema for Snowflake offline store tests [\#2291](https://github.com/feast-dev/feast/pull/2291) ([sfc-gh-madkins](https://github.com/sfc-gh-madkins)) @@ -47,11 +123,11 @@ - Add -SNAPSHOT suffix to pom.xml version [\#2286](https://github.com/feast-dev/feast/pull/2286) ([tsotnet](https://github.com/tsotnet)) - Update CONTRIBUTING.md [\#2282](https://github.com/feast-dev/feast/pull/2282) ([adchia](https://github.com/adchia)) -## [v0.18.0](https://github.com/feast-dev/feast/tree/v0.18.0) (2022-02-05) +# [v0.18.0](https://github.com/feast-dev/feast/tree/v0.18.0) (2022-02-05) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.17.0...v0.18.0) -**Implemented enhancements:** +### Features - Tutorial on validation of historical features [\#2277](https://github.com/feast-dev/feast/pull/2277) ([pyalex](https://github.com/pyalex)) - Feast plan clean up [\#2256](https://github.com/feast-dev/feast/pull/2256) ([felixwang9817](https://github.com/felixwang9817)) @@ -66,7 +142,7 @@ - Add InfraDiff class for feast plan [\#2190](https://github.com/feast-dev/feast/pull/2190) ([felixwang9817](https://github.com/felixwang9817)) - Use FeatureViewProjection instead of FeatureView in ODFV [\#2186](https://github.com/feast-dev/feast/pull/2186) ([judahrand](https://github.com/judahrand)) -**Fixed bugs:** +### Bug Fixes - Set `created\_timestamp` and `last\_updated\_timestamp` fields [\#2266](https://github.com/feast-dev/feast/pull/2266) ([judahrand](https://github.com/judahrand)) - Use `datetime.utcnow\(\)` to avoid timezone issues [\#2265](https://github.com/feast-dev/feast/pull/2265) ([judahrand](https://github.com/judahrand)) @@ -91,7 +167,7 @@ - Speed up Datastore deletes by batch deletions with multithreading [\#2182](https://github.com/feast-dev/feast/pull/2182) ([ptoman-pa](https://github.com/ptoman-pa)) - Fixes large payload runtime exception in Datastore \(issue 1633\) [\#2181](https://github.com/feast-dev/feast/pull/2181) ([ptoman-pa](https://github.com/ptoman-pa)) -**Merged pull requests:** +### Merged Pull Requests - Add link to community plugin for Spark offline store [\#2279](https://github.com/feast-dev/feast/pull/2279) ([adchia](https://github.com/adchia)) - Fix broken links on documentation [\#2278](https://github.com/feast-dev/feast/pull/2278) ([adchia](https://github.com/adchia)) @@ -125,11 +201,11 @@ - Add a unit test for the tag\_proto\_objects method [\#2163](https://github.com/feast-dev/feast/pull/2163) ([achals](https://github.com/achals)) -## [v0.17.0](https://github.com/feast-dev/feast/tree/v0.17.0) (2021-12-31) +# [v0.17.0](https://github.com/feast-dev/feast/tree/v0.17.0) (2021-12-31) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.16.1...v0.17.0) -**Implemented enhancements:** +### Features - Add feast-python-server helm chart [\#2177](https://github.com/feast-dev/feast/pull/2177) ([michelle-rascati-sp](https://github.com/michelle-rascati-sp)) - Add SqliteTable as an InfraObject [\#2157](https://github.com/feast-dev/feast/pull/2157) ([felixwang9817](https://github.com/felixwang9817)) @@ -141,7 +217,7 @@ - Add Infra and InfraObjects classes [\#2125](https://github.com/feast-dev/feast/pull/2125) ([felixwang9817](https://github.com/felixwang9817)) - Pre compute the timestamp range for feature views [\#2103](https://github.com/feast-dev/feast/pull/2103) ([judahrand](https://github.com/judahrand)) -**Fixed bugs:** +### Bug Fixes - Fix issues with java docker building [\#2178](https://github.com/feast-dev/feast/pull/2178) ([achals](https://github.com/achals)) - unpin boto dependency in setup [\#2168](https://github.com/feast-dev/feast/pull/2168) ([fengyu05](https://github.com/fengyu05)) @@ -157,7 +233,7 @@ - Remove spring-boot from the feast serving application [\#2127](https://github.com/feast-dev/feast/pull/2127) ([achals](https://github.com/achals)) - Fix Makefile to properly create the ECR\_VERSION [\#2123](https://github.com/feast-dev/feast/pull/2123) ([adchia](https://github.com/adchia)) -**Closed issues:** +### Closes Issues - In GH workflow docker images are being built but not published [\#2152](https://github.com/feast-dev/feast/issues/2152) - Any plan to make Feast 0.10+ support docker [\#2148](https://github.com/feast-dev/feast/issues/2148) @@ -165,7 +241,7 @@ - Release workflow does not work [\#2136](https://github.com/feast-dev/feast/issues/2136) - Redis Online Store - Truncate and Load [\#2129](https://github.com/feast-dev/feast/issues/2129) -**Merged pull requests:** +### Merged Pull Requests - Update roadmap to include Snowflake + Trino. Also fix docs + update FAQ [\#2175](https://github.com/feast-dev/feast/pull/2175) ([adchia](https://github.com/adchia)) - Convert python values into proto values in bulk [\#2172](https://github.com/feast-dev/feast/pull/2172) ([pyalex](https://github.com/pyalex)) @@ -188,33 +264,33 @@ - Fix leaking dynamodb tables in integration tests [\#2104](https://github.com/feast-dev/feast/pull/2104) ([pyalex](https://github.com/pyalex)) - Remove untested and undocumented interfaces [\#2084](https://github.com/feast-dev/feast/pull/2084) ([judahrand](https://github.com/judahrand)) - Update creating-a-custom-provider.md [\#2070](https://github.com/feast-dev/feast/pull/2070) ([ChaitanyaKN](https://github.com/ChaitanyaKN)) -## [v0.16.1](https://github.com/feast-dev/feast/tree/v0.16.1) (2021-12-10) +# [v0.16.1](https://github.com/feast-dev/feast/tree/v0.16.1) (2021-12-10) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.16.0...v0.16.1) -**Fixed bugs:** +### Bug Fixes - Bump log4j-api from 2.13.2 to 2.15.0 in /java [\#2133](https://github.com/feast-dev/feast/pull/2133) ([dependabot[bot]](https://github.com/apps/dependabot)) - Fix release workflow to use the new GCP action [\#2132](https://github.com/feast-dev/feast/pull/2132) ([adchia](https://github.com/adchia)) - Fix Makefile to properly create the ECR\_VERSION [\#2123](https://github.com/feast-dev/feast/pull/2123) ([adchia](https://github.com/adchia)) -**Merged pull requests:** +### Merged Pull Requests - Updating lambda docker image to feature-server-python-aws [\#2130](https://github.com/feast-dev/feast/pull/2130) ([adchia](https://github.com/adchia)) - Fix README to reflect new integration test suites [\#2124](https://github.com/feast-dev/feast/pull/2124) ([adchia](https://github.com/adchia)) - Remove argument `feature_refs` [\#2115](https://github.com/feast-dev/feast/pull/2115) ([judahrand](https://github.com/judahrand)) -## [v0.16.0](https://github.com/feast-dev/feast/tree/v0.16.0) (2021-12-08) +# [v0.16.0](https://github.com/feast-dev/feast/tree/v0.16.0) (2021-12-08) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.15.1...v0.16.0) -**Implemented enhancements:** +### Features - Install redis extra in AWS Lambda feature server & add hiredis depend… [\#2057](https://github.com/feast-dev/feast/pull/2057) ([tsotnet](https://github.com/tsotnet)) - Support of GC and S3 storages for registry in Java Feature Server [\#2043](https://github.com/feast-dev/feast/pull/2043) ([pyalex](https://github.com/pyalex)) - Adding stream ingestion alpha documentation [\#2005](https://github.com/feast-dev/feast/pull/2005) ([adchia](https://github.com/adchia)) -**Fixed bugs:** +### Bug Fixes - requested\_features are not passed to online\_read\(\) from passthrough\_provider [\#2106](https://github.com/feast-dev/feast/issues/2106) - `feast apply` broken with 0.15.\* if the registry already exists [\#2086](https://github.com/feast-dev/feast/issues/2086) @@ -244,7 +320,7 @@ - Fix duplicate update infra [\#1990](https://github.com/feast-dev/feast/pull/1990) ([felixwang9817](https://github.com/felixwang9817)) - Improve performance of \_convert\_arrow\_to\_proto [\#1984](https://github.com/feast-dev/feast/pull/1984) ([nossrannug](https://github.com/nossrannug)) -**Merged pull requests:** +### Merged Pull Requests - Add changelog for v0.16.0 [\#2120](https://github.com/feast-dev/feast/pull/2120) ([adchia](https://github.com/adchia)) - Update FAQ [\#2118](https://github.com/feast-dev/feast/pull/2118) ([felixwang9817](https://github.com/felixwang9817)) @@ -288,18 +364,18 @@ - Add changelog for v0.15.0 [\#2006](https://github.com/feast-dev/feast/pull/2006) ([adchia](https://github.com/adchia)) - Add integration tests for AWS Lambda feature server [\#2001](https://github.com/feast-dev/feast/pull/2001) ([tsotnet](https://github.com/tsotnet)) -## [v0.15.1](https://github.com/feast-dev/feast/tree/v0.15.1) (2021-11-13) +# [v0.15.1](https://github.com/feast-dev/feast/tree/v0.15.1) (2021-11-13) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.15.0...v0.15.1) -**Fixed bugs:** +### Bug Fixes - Add missing comma in setup.py [\#2031](https://github.com/feast-dev/feast/pull/2031) ([achals](https://github.com/achals)) - Correct cleanup after usage e2e tests [\#2015](https://github.com/feast-dev/feast/pull/2015) ([pyalex](https://github.com/pyalex)) - Change Environment timestamps to be in UTC [\#2007](https://github.com/feast-dev/feast/pull/2007) ([felixwang9817](https://github.com/felixwang9817)) - ODFV UDFs should handle list types [\#2002](https://github.com/feast-dev/feast/pull/2002) ([Agent007](https://github.com/Agent007)) -**Merged pull requests:** +### Merged Pull Requests - Remove unsupported java parts [\#2029](https://github.com/feast-dev/feast/pull/2029) ([pyalex](https://github.com/pyalex)) - Fix checked out branch for PR docker image build workflow [\#2018](https://github.com/feast-dev/feast/pull/2018) ([tsotnet](https://github.com/tsotnet)) @@ -308,11 +384,11 @@ - Add integration tests for AWS Lambda feature server [\#2001](https://github.com/feast-dev/feast/pull/2001) ([tsotnet](https://github.com/tsotnet)) - Moving Feast Java back into main repo under java/ package [\#1997](https://github.com/feast-dev/feast/pull/1997) ([adchia](https://github.com/adchia)) -## [v0.15.0](https://github.com/feast-dev/feast/tree/v0.15.0) (2021-11-08) +# [v0.15.0](https://github.com/feast-dev/feast/tree/v0.15.0) (2021-11-08) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.14.1...v0.15.0) -**Implemented enhancements:** +### Features - Adding stream ingestion alpha documentation [\#2005](https://github.com/feast-dev/feast/pull/2005) ([adchia](https://github.com/adchia)) - Feature transformation server docker image [\#1972](https://github.com/feast-dev/feast/pull/1972) ([felixwang9817](https://github.com/felixwang9817)) @@ -324,7 +400,7 @@ - Add final\_output\_feature\_names in Query context to avoid SELECT \* EXCEPT [\#1911](https://github.com/feast-dev/feast/pull/1911) ([MattDelac](https://github.com/MattDelac)) - Add Dockerfile for GCP CloudRun FeatureServer [\#1887](https://github.com/feast-dev/feast/pull/1887) ([judahrand](https://github.com/judahrand)) -**Fixed bugs:** +### Bug Fixes - feast=0.14.0 `query_generator()` unecessary used twice [\#1978](https://github.com/feast-dev/feast/issues/1978) - get\_online\_features on demand transform bug fixes + local integration test mode [\#2004](https://github.com/feast-dev/feast/pull/2004) ([adchia](https://github.com/adchia)) @@ -346,7 +422,7 @@ - Fix \_\_getitem\_\_ return value for feature view and on-demand feature view [\#1936](https://github.com/feast-dev/feast/pull/1936) ([mavysavydav](https://github.com/mavysavydav)) - Corrected setup.py BigQuery version that's needed for a contributor's merged PR 1844 [\#1934](https://github.com/feast-dev/feast/pull/1934) ([mavysavydav](https://github.com/mavysavydav)) -**Merged pull requests:** +### Merged Pull Requests - Fix protobuf version conflict in \[gcp\] and \[ci\] packages [\#1992](https://github.com/feast-dev/feast/pull/1992) ([ysk24ok](https://github.com/ysk24ok)) - Improve aws lambda deployment \(logging, idempotency, etc\) [\#1985](https://github.com/feast-dev/feast/pull/1985) ([tsotnet](https://github.com/tsotnet)) @@ -360,11 +436,11 @@ - Add David and Matt as reviewers, and add actions for issue/PR assignment [\#1942](https://github.com/feast-dev/feast/pull/1942) ([achals](https://github.com/achals)) - Simplify BigQuery load jobs [\#1935](https://github.com/feast-dev/feast/pull/1935) ([judahrand](https://github.com/judahrand)) -## [v0.14.1](https://github.com/feast-dev/feast/tree/v0.14.1) (2021-10-28) +# [v0.14.1](https://github.com/feast-dev/feast/tree/v0.14.1) (2021-10-28) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.14.0...v0.14.1) -**Fixed bugs:** +### Bug Fixes - Fix duplicate upload entity [\#1981](https://github.com/feast-dev/feast/pull/1981) ([achals](https://github.com/achals)) - Fix bug in feast alpha enable CLI command [\#1940](https://github.com/feast-dev/feast/pull/1940) ([felixwang9817](https://github.com/felixwang9817)) @@ -372,16 +448,16 @@ - Fix \_\_getitem\_\_ return value for feature view and on-demand feature view [\#1936](https://github.com/feast-dev/feast/pull/1936) ([mavysavydav](https://github.com/mavysavydav)) - Corrected setup.py BigQuery version that's needed for a contributor's merged PR 1844 [\#1934](https://github.com/feast-dev/feast/pull/1934) ([mavysavydav](https://github.com/mavysavydav)) -**Merged pull requests:** +### Merged Pull Requests - Updating roadmap + hero image [\#1950](https://github.com/feast-dev/feast/pull/1950) ([adchia](https://github.com/adchia)) - Simplify BigQuery load jobs [\#1935](https://github.com/feast-dev/feast/pull/1935) ([judahrand](https://github.com/judahrand)) -## [v0.14.0](https://github.com/feast-dev/feast/tree/v0.14.0) (2021-10-08) +# [v0.14.0](https://github.com/feast-dev/feast/tree/v0.14.0) (2021-10-08) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.13.0...v0.14.0) -**Implemented enhancements:** +### Features - Changed FVProjection 'name\_to\_use' field to 'name\_alias' and changed '.set\_projection' in FeatureView to ".with\_projection". Also adjustments for some edge cases [\#1929](https://github.com/feast-dev/feast/pull/1929) ([mavysavydav](https://github.com/mavysavydav)) - Make serverless alpha feature [\#1928](https://github.com/feast-dev/feast/pull/1928) ([felixwang9817](https://github.com/felixwang9817)) @@ -392,7 +468,7 @@ - Upload docker image to ECR during feast apply [\#1877](https://github.com/feast-dev/feast/pull/1877) ([felixwang9817](https://github.com/felixwang9817)) - Added .with\_name method in FeatureView/OnDemandFeatureView classes for name aliasing. FeatureViewProjection will hold this information [\#1872](https://github.com/feast-dev/feast/pull/1872) ([mavysavydav](https://github.com/mavysavydav)) -**Fixed bugs:** +### Bug Fixes - Update makefile to use pip installed dependencies [\#1920](https://github.com/feast-dev/feast/pull/1920) ([loftiskg](https://github.com/loftiskg)) - Delete tables [\#1916](https://github.com/feast-dev/feast/pull/1916) ([felixwang9817](https://github.com/felixwang9817)) @@ -403,7 +479,7 @@ - Fix issue with feature views being detected as duplicated when imported [\#1905](https://github.com/feast-dev/feast/pull/1905) ([achals](https://github.com/achals)) - Use contextvars to maintain a call stack during the usage calls [\#1882](https://github.com/feast-dev/feast/pull/1882) ([achals](https://github.com/achals)) -**Merged pull requests:** +### Merged Pull Requests - Update concepts/README.md [\#1926](https://github.com/feast-dev/feast/pull/1926) ([ysk24ok](https://github.com/ysk24ok)) - Add CI for feature server Docker image [\#1925](https://github.com/feast-dev/feast/pull/1925) ([felixwang9817](https://github.com/felixwang9817)) @@ -413,16 +489,16 @@ - Add provider, offline store, online store, registry to RTD [\#1918](https://github.com/feast-dev/feast/pull/1918) ([felixwang9817](https://github.com/felixwang9817)) - Cleanup tests [\#1901](https://github.com/feast-dev/feast/pull/1901) ([felixwang9817](https://github.com/felixwang9817)) -## [v0.13.0](https://github.com/feast-dev/feast/tree/v0.13.0) (2021-09-22) +# [v0.13.0](https://github.com/feast-dev/feast/tree/v0.13.0) (2021-09-22) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.12.1...v0.13.0) -**Breaking changes:** +### Breaking Changes - Enforce case-insensitively unique feature view names [\#1835](https://github.com/feast-dev/feast/pull/1835) ([codyjlin](https://github.com/codyjlin)) - Add init to Provider contract [\#1796](https://github.com/feast-dev/feast/pull/1796) ([woop](https://github.com/woop)) -**Implemented enhancements:** +### Features - Add on demand feature view experimental docs [\#1880](https://github.com/feast-dev/feast/pull/1880) ([adchia](https://github.com/adchia)) - Adding telemetry for on demand feature views and making existing usage calls async [\#1873](https://github.com/feast-dev/feast/pull/1873) ([adchia](https://github.com/adchia)) @@ -442,7 +518,7 @@ - Add s3 support \(with custom endpoints\) [\#1789](https://github.com/feast-dev/feast/pull/1789) ([woop](https://github.com/woop)) - Local feature server implementation \(HTTP endpoint\) [\#1780](https://github.com/feast-dev/feast/pull/1780) ([tsotnet](https://github.com/tsotnet)) -**Fixed bugs:** +### Bug Fixes - Fixing odfv cli group description [\#1890](https://github.com/feast-dev/feast/pull/1890) ([adchia](https://github.com/adchia)) - Fix list feature format for BigQuery offline datasources. [\#1889](https://github.com/feast-dev/feast/pull/1889) ([judahrand](https://github.com/judahrand)) @@ -468,7 +544,7 @@ - Fix BQ historical retrieval with rows that got backfilled [\#1744](https://github.com/feast-dev/feast/pull/1744) ([MattDelac](https://github.com/MattDelac)) - Handle case where`_LIST` type is empty [\#1703](https://github.com/feast-dev/feast/pull/1703) ([judahrand](https://github.com/judahrand)) -**Merged pull requests:** +### Merged Pull Requests - Add `ValueType.NULL` [\#1893](https://github.com/feast-dev/feast/pull/1893) ([judahrand](https://github.com/judahrand)) - Adding more details to the CONTRIBUTING.md [\#1888](https://github.com/feast-dev/feast/pull/1888) ([adchia](https://github.com/adchia)) @@ -504,23 +580,23 @@ - Adding initial type support related tests for BQ [\#1768](https://github.com/feast-dev/feast/pull/1768) ([adchia](https://github.com/adchia)) - Add release-patch script [\#1554](https://github.com/feast-dev/feast/pull/1554) ([jklegar](https://github.com/jklegar)) -## [v0.12.1](https://github.com/feast-dev/feast/tree/v0.12.1) (2021-08-20) +# [v0.12.1](https://github.com/feast-dev/feast/tree/v0.12.1) (2021-08-20) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.12.0...v0.12.1) -**Fixed bugs:** +### Bug Fixes - Fix get\_online\_features telemetry to only log every 10000 times [\#1786](https://github.com/feast-dev/feast/pull/1786) ([felixwang9817](https://github.com/felixwang9817)) -## [v0.12.0](https://github.com/feast-dev/feast/tree/v0.12.0) (2021-08-05) +# [v0.12.0](https://github.com/feast-dev/feast/tree/v0.12.0) (2021-08-05) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.11.0...v0.12.0) -**Breaking changes:** +### Breaking Changes - Set default feature naming to not include feature view name. Add option to include feature view name in feature naming. [\#1641](https://github.com/feast-dev/feast/pull/1641) ([Mwad22](https://github.com/Mwad22)) -**Implemented enhancements:** +### Features - AWS Template improvements \(input prompt for configs, default to Redshift\) [\#1731](https://github.com/feast-dev/feast/pull/1731) ([tsotnet](https://github.com/tsotnet)) - Clean up uploaded entities in Redshift offline store [\#1730](https://github.com/feast-dev/feast/pull/1730) ([tsotnet](https://github.com/tsotnet)) @@ -535,7 +611,7 @@ - Add to\_table\(\) to RetrievalJob object [\#1663](https://github.com/feast-dev/feast/pull/1663) ([MattDelac](https://github.com/MattDelac)) - Provide the user with more options for setting the to\_bigquery config [\#1661](https://github.com/feast-dev/feast/pull/1661) ([codyjlin](https://github.com/codyjlin)) -**Fixed bugs:** +### Bug Fixes - Fix `feast apply` bugs [\#1754](https://github.com/feast-dev/feast/pull/1754) ([tsotnet](https://github.com/tsotnet)) - Teardown integration tests resources for aws [\#1740](https://github.com/feast-dev/feast/pull/1740) ([achals](https://github.com/achals)) @@ -556,7 +632,7 @@ - Cancel BigQuery job if timeout hits [\#1672](https://github.com/feast-dev/feast/pull/1672) ([MattDelac](https://github.com/MattDelac)) - Make sure FeatureViews with same name can not be applied at the same … [\#1651](https://github.com/feast-dev/feast/pull/1651) ([tedhtchang](https://github.com/tedhtchang)) -**Merged pull requests:** +### Merged Pull Requests - Add AWS docs in summary.md [\#1761](https://github.com/feast-dev/feast/pull/1761) ([tsotnet](https://github.com/tsotnet)) - Document permissions for AWS \(DynamoDB & Redshift\) [\#1753](https://github.com/feast-dev/feast/pull/1753) ([tsotnet](https://github.com/tsotnet)) @@ -590,11 +666,11 @@ - Rename telemetry to usage [\#1660](https://github.com/feast-dev/feast/pull/1660) ([tsotnet](https://github.com/tsotnet)) - Update charts README [\#1659](https://github.com/feast-dev/feast/pull/1659) ([szalai1](https://github.com/szalai1)) -## [v0.11.0](https://github.com/feast-dev/feast/tree/v0.11.0) (2021-06-24) +# [v0.11.0](https://github.com/feast-dev/feast/tree/v0.11.0) (2021-06-24) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.8...v0.11.0) -**Implemented enhancements:** +### Features - Allow BigQuery project to be configured [\#1656](https://github.com/feast-dev/feast/pull/1656) ([MattDelac](https://github.com/MattDelac)) - Add to_bigquery function to BigQueryRetrievalJob [\#1634](https://github.com/feast-dev/feast/pull/1634) ([vtao2](https://github.com/vtao2)) @@ -609,7 +685,7 @@ - Add support for Redis and Redis Cluster [\#1511](https://github.com/feast-dev/feast/pull/1511) ([qooba](https://github.com/qooba)) - Add path option to cli [\#1509](https://github.com/feast-dev/feast/pull/1509) ([tedhtchang](https://github.com/tedhtchang)) -**Fixed bugs:** +### Bug Fixes - Schema Inferencing should happen at apply time [\#1646](https://github.com/feast-dev/feast/pull/1646) ([mavysavydav](https://github.com/mavysavydav)) - Don't use .result\(\) in BigQueryOfflineStore, since it still leads to OOM [\#1642](https://github.com/feast-dev/feast/pull/1642) ([tsotnet](https://github.com/tsotnet)) @@ -630,7 +706,7 @@ - Validate project and repo names for apply and init commands [\#1558](https://github.com/feast-dev/feast/pull/1558) ([tedhtchang](https://github.com/tedhtchang)) - Bump supported Python version to 3.7 [\#1504](https://github.com/feast-dev/feast/pull/1504) ([tsotnet](https://github.com/tsotnet)) -**Merged pull requests:** +### Merged Pull Requests - Rename telemetry to usage [\#1660](https://github.com/feast-dev/feast/pull/1660) ([tsotnet](https://github.com/tsotnet)) - Refactor OfflineStoreConfig classes into their owning modules [\#1657](https://github.com/feast-dev/feast/pull/1657) ([achals](https://github.com/achals)) @@ -668,35 +744,35 @@ - Add optional telemetry to other CLI commands [\#1505](https://github.com/feast-dev/feast/pull/1505) ([jklegar](https://github.com/jklegar)) -## [v0.10.8](https://github.com/feast-dev/feast/tree/v0.10.8) (2021-06-17) +# [v0.10.8](https://github.com/feast-dev/feast/tree/v0.10.8) (2021-06-17) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.7...v0.10.8) -**Implemented enhancements:** +### Features - Add `to_bigquery()` function to BigQueryRetrievalJob [\#1634](https://github.com/feast-dev/feast/pull/1634) ([vtao2](https://github.com/vtao2)) -**Fixed bugs:** +### Bug Fixes - Don't use .result\(\) in BigQueryOfflineStore, since it still leads to OOM [\#1642](https://github.com/feast-dev/feast/pull/1642) ([tsotnet](https://github.com/tsotnet)) - Don't load entire bigquery query results in memory [\#1638](https://github.com/feast-dev/feast/pull/1638) ([tsotnet](https://github.com/tsotnet)) - Add entity column validations when getting historical features from bigquery [\#1614](https://github.com/feast-dev/feast/pull/1614) ([achals](https://github.com/achals)) -**Merged pull requests:** +### Merged Pull Requests - Make test historical retrieval longer [\#1630](https://github.com/feast-dev/feast/pull/1630) ([MattDelac](https://github.com/MattDelac)) - Fix failing historical retrieval assertion [\#1622](https://github.com/feast-dev/feast/pull/1622) ([woop](https://github.com/woop)) - Optimize historical retrieval with BigQuery offline store [\#1602](https://github.com/feast-dev/feast/pull/1602) ([MattDelac](https://github.com/MattDelac)) -## [v0.10.7](https://github.com/feast-dev/feast/tree/v0.10.7) (2021-06-07) +# [v0.10.7](https://github.com/feast-dev/feast/tree/v0.10.7) (2021-06-07) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.6...v0.10.7) -**Fixed bugs:** +### Bug Fixes - Fix race condition in historical e2e tests [\#1620](https://github.com/feast-dev/feast/pull/1620) ([woop](https://github.com/woop)) -**Merged pull requests:** +### Merged Pull Requests - Use drop\_duplicates\(\) instead of groupby \(about 1.5~2x faster\) [\#1617](https://github.com/feast-dev/feast/pull/1617) ([rightx2](https://github.com/rightx2)) - Use CONCAT\(\) instead of ROW\_NUMBER\(\) [\#1601](https://github.com/feast-dev/feast/pull/1601) ([MattDelac](https://github.com/MattDelac)) @@ -704,38 +780,38 @@ - Append nanoseconds to dataset name in test\_historical\_retrival to prevent tests stomping over each other [\#1593](https://github.com/feast-dev/feast/pull/1593) ([achals](https://github.com/achals)) - Make start and end timestamps tz aware in the CLI [\#1590](https://github.com/feast-dev/feast/pull/1590) ([achals](https://github.com/achals)) -## [v0.10.6](https://github.com/feast-dev/feast/tree/v0.10.6) (2021-05-27) +# [v0.10.6](https://github.com/feast-dev/feast/tree/v0.10.6) (2021-05-27) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.5...v0.10.6) -**Implemented enhancements:** +### Features - Add datastore namespace option in configs [\#1581](https://github.com/feast-dev/feast/pull/1581) ([tsotnet](https://github.com/tsotnet)) -**Fixed bugs:** +### Bug Fixes - Fix contention issue [\#1582](https://github.com/feast-dev/feast/pull/1582) ([woop](https://github.com/woop)) - Ensure that only None types fail predicate [\#1580](https://github.com/feast-dev/feast/pull/1580) ([woop](https://github.com/woop)) - Don't create bigquery dataset if it already exists [\#1569](https://github.com/feast-dev/feast/pull/1569) ([tsotnet](https://github.com/tsotnet)) -**Merged pull requests:** +### Merged Pull Requests - Change OfflineStore class description [\#1571](https://github.com/feast-dev/feast/pull/1571) ([tedhtchang](https://github.com/tedhtchang)) -## [v0.10.5](https://github.com/feast-dev/feast/tree/v0.10.5) (2021-05-19) +# [v0.10.5](https://github.com/feast-dev/feast/tree/v0.10.5) (2021-05-19) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.4...v0.10.5) -**Implemented enhancements:** +### Features - Add offline\_store config [\#1552](https://github.com/feast-dev/feast/pull/1552) ([tsotnet](https://github.com/tsotnet)) -**Fixed bugs:** +### Bug Fixes - Validate project and repo names for apply and init commands [\#1558](https://github.com/feast-dev/feast/pull/1558) ([tedhtchang](https://github.com/tedhtchang)) -**Merged pull requests:** +### Merged Pull Requests - Fix Sphinx documentation building [\#1563](https://github.com/feast-dev/feast/pull/1563) ([woop](https://github.com/woop)) - Add test coverage and remove MacOS integration tests [\#1562](https://github.com/feast-dev/feast/pull/1562) ([woop](https://github.com/woop)) @@ -744,17 +820,17 @@ - Add opt-out exception logging telemetry [\#1535](https://github.com/feast-dev/feast/pull/1535) ([jklegar](https://github.com/jklegar)) - Add instruction for install Feast on IKS and OpenShift using Kustomize [\#1534](https://github.com/feast-dev/feast/pull/1534) ([tedhtchang](https://github.com/tedhtchang)) -## [v0.10.4](https://github.com/feast-dev/feast/tree/v0.10.4) (2021-05-12) +# [v0.10.4](https://github.com/feast-dev/feast/tree/v0.10.4) (2021-05-12) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.3...v0.10.4) -**Implemented enhancements:** +### Features - Inferencing of Features in FeatureView and timestamp column of DataSource [\#1523](https://github.com/feast-dev/feast/pull/1523) ([mavysavydav](https://github.com/mavysavydav)) - Add Unix Timestamp value type [\#1520](https://github.com/feast-dev/feast/pull/1520) ([MattDelac](https://github.com/MattDelac)) - Fix materialize for None [\#1481](https://github.com/feast-dev/feast/pull/1481) ([qooba](https://github.com/qooba)) -**Merged pull requests:** +### Merged Pull Requests - BigQuery type to Feast type conversion chart update [\#1530](https://github.com/feast-dev/feast/pull/1530) ([mavysavydav](https://github.com/mavysavydav)) - remove unnecessay path join in setup.py [\#1529](https://github.com/feast-dev/feast/pull/1529) ([shihabuddinbuet](https://github.com/shihabuddinbuet)) @@ -765,22 +841,22 @@ - Better logging for materialize command [\#1499](https://github.com/feast-dev/feast/pull/1499) ([jklegar](https://github.com/jklegar)) -## [v0.10.3](https://github.com/feast-dev/feast/tree/v0.10.3) (2021-04-21) +# [v0.10.3](https://github.com/feast-dev/feast/tree/v0.10.3) (2021-04-21) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.2...v0.10.3) -**Implemented enhancements:** +### Features - Add support for third party providers [\#1501](https://github.com/feast-dev/feast/pull/1501) ([tsotnet](https://github.com/tsotnet)) - Infer entity dataframe event timestamp column [\#1495](https://github.com/feast-dev/feast/pull/1495) ([jklegar](https://github.com/jklegar)) - Allow Feast apply to import files recursively \(and add .feastignore\) [\#1482](https://github.com/feast-dev/feast/pull/1482) ([tsotnet](https://github.com/tsotnet)) -**Fixed bugs:** +### Bug Fixes - Bump supported Python version to 3.7 [\#1504](https://github.com/feast-dev/feast/pull/1504) ([tsotnet](https://github.com/tsotnet)) - Fix bug in allowing empty repositories to be applied to a GCS registry [\#1488](https://github.com/feast-dev/feast/pull/1488) ([woop](https://github.com/woop)) -**Merged pull requests:** +### Merged Pull Requests - Add a fixed timestamp to quickstart data [\#1513](https://github.com/feast-dev/feast/pull/1513) ([jklegar](https://github.com/jklegar)) - Make gcp imports optional [\#1512](https://github.com/feast-dev/feast/pull/1512) ([jklegar](https://github.com/jklegar)) @@ -791,23 +867,23 @@ - Update broken urls in contributing.md [\#1489](https://github.com/feast-dev/feast/pull/1489) ([tedhtchang](https://github.com/tedhtchang)) - Python docs formatting fixes [\#1473](https://github.com/feast-dev/feast/pull/1473) ([jklegar](https://github.com/jklegar)) -## [v0.10.2](https://github.com/feast-dev/feast/tree/v0.10.2) (2021-04-21) +# [v0.10.2](https://github.com/feast-dev/feast/tree/v0.10.2) (2021-04-21) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.1...v0.10.2) -**Fixed bugs:** +### Bug Fixes - Fix bug in allowing empty repositories to be applied to a GCS registry [\#1488](https://github.com/feast-dev/feast/pull/1488) ([woop](https://github.com/woop)) -## [v0.10.1](https://github.com/feast-dev/feast/tree/v0.10.1) (2021-04-21) +# [v0.10.1](https://github.com/feast-dev/feast/tree/v0.10.1) (2021-04-21) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.10.0...v0.10.1) -**Fixed bugs:** +### Bug Fixes - Fix time zone issue with get\_historical\_features [\#1475](https://github.com/feast-dev/feast/pull/1475) ([tsotnet](https://github.com/tsotnet)) -**Merged pull requests:** +### Merged Pull Requests - Improve exception handling, logging, and validation [\#1477](https://github.com/feast-dev/feast/pull/1477) ([woop](https://github.com/woop)) - Remove duped pic [\#1476](https://github.com/feast-dev/feast/pull/1476) ([YikSanChan](https://github.com/YikSanChan)) @@ -816,11 +892,11 @@ - Fix CLI entities command & add feature-views command [\#1471](https://github.com/feast-dev/feast/pull/1471) ([tsotnet](https://github.com/tsotnet)) -## [v0.10.0](https://github.com/feast-dev/feast/tree/0.10.0) (2021-04-15) +# [v0.10.0](https://github.com/feast-dev/feast/tree/0.10.0) (2021-04-15) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.9.5...v0.10.0) -** Implemented enhancements:** +### Features - Add template generation to Feast CLI for Google Cloud Platform [\#1460](https://github.com/feast-dev/feast/pull/1460) ([woop](https://github.com/woop)) - Add support for retrieving data from sources that don't match providers [\#1454](https://github.com/feast-dev/feast/pull/1454) ([woop](https://github.com/woop)) @@ -842,7 +918,7 @@ - FeatureStore, FeatureView, Config, and BigQuerySource classes for updated SDK [\#1364](https://github.com/feast-dev/feast/pull/1364) ([jklegar](https://github.com/jklegar)) - Add support for new deploy CLI [\#1362](https://github.com/feast-dev/feast/pull/1362) ([oavdeev](https://github.com/oavdeev)) -** Fixed bugs:** +### Bug Fixes - Fix time zone access with native python datetimes [\#1469](https://github.com/feast-dev/feast/pull/1469) ([tsotnet](https://github.com/tsotnet)) - Small fixes for created\_timestamp [\#1468](https://github.com/feast-dev/feast/pull/1468) ([jklegar](https://github.com/jklegar)) @@ -859,7 +935,7 @@ - Make CLI apply in local mode idempotent [\#1401](https://github.com/feast-dev/feast/pull/1401) ([oavdeev](https://github.com/oavdeev)) - Fix a bug in client archive\_project method and fix lint in grpc auth [\#1396](https://github.com/feast-dev/feast/pull/1396) ([randxie](https://github.com/randxie)) -**Merged pull requests:** +### Merged Pull Requests - Change GCP template names to match local template [\#1470](https://github.com/feast-dev/feast/pull/1470) ([jklegar](https://github.com/jklegar)) - Add logging to materialize [\#1467](https://github.com/feast-dev/feast/pull/1467) ([woop](https://github.com/woop)) @@ -906,25 +982,25 @@ - Add Firestore online format specification [\#1367](https://github.com/feast-dev/feast/pull/1367) ([oavdeev](https://github.com/oavdeev)) - Improve documentation for k8s-spark resource template [\#1363](https://github.com/feast-dev/feast/pull/1363) ([theofpa](https://github.com/theofpa)) -## [v0.9.1](https://github.com/feast-dev/feast/tree/v0.9.1) (2021-01-29) +# [v0.9.1](https://github.com/feast-dev/feast/tree/v0.9.1) (2021-01-29) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.9.0...v0.9.1) -**Implemented enhancements:** +### Features - Add telemetry to Python SDK [\#1289](https://github.com/feast-dev/feast/pull/1289) ([jklegar](https://github.com/jklegar)) -**Fixed bugs:** +### Bug Fixes - Fix kafka download url [\#1298](https://github.com/feast-dev/feast/pull/1298) ([jklegar](https://github.com/jklegar)) - disable telemetry in docker-compose test and job\_service [\#1297](https://github.com/feast-dev/feast/pull/1297) ([jklegar](https://github.com/jklegar)) -## [v0.9.0](https://github.com/feast-dev/feast/tree/v0.9.0) (2021-01-28) +# [v0.9.0](https://github.com/feast-dev/feast/tree/v0.9.0) (2021-01-28) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.8.4...v0.9.0) -**Implemented enhancements:** +### Features - Enable user to provide spark job template as input for jobservice deployment [\#1285](https://github.com/feast-dev/feast/pull/1285) ([khorshuheng](https://github.com/khorshuheng)) - Add feature table name filter to jobs list api [\#1282](https://github.com/feast-dev/feast/pull/1282) ([terryyylim](https://github.com/terryyylim)) @@ -933,7 +1009,7 @@ - Azure example terraform [\#1274](https://github.com/feast-dev/feast/pull/1274) ([jklegar](https://github.com/jklegar)) -**Fixed bugs:** +### Bug Fixes - make EMR jar uploader work the same as k8s one [\#1284](https://github.com/feast-dev/feast/pull/1284) ([oavdeev](https://github.com/oavdeev)) - Don't error when azure vars not set [\#1277](https://github.com/feast-dev/feast/pull/1277) ([jklegar](https://github.com/jklegar)) @@ -944,7 +1020,7 @@ - Bump terraform rds module version [\#1204](https://github.com/feast-dev/feast/pull/1204) ([oavdeev](https://github.com/oavdeev)) -**Merged pull requests:** +### Merged Pull Requests - Use date partitioning column in FileSource [\#1293](https://github.com/feast-dev/feast/pull/1293) ([pyalex](https://github.com/pyalex)) - Add EMR CI/CD entrypoint script [\#1290](https://github.com/feast-dev/feast/pull/1290) ([oavdeev](https://github.com/oavdeev)) @@ -1001,41 +1077,41 @@ - Remove unnecessary Google Auth dependency [\#1170](https://github.com/feast-dev/feast/pull/1170) ([woop](https://github.com/woop)) -## [v0.8.2](https://github.com/feast-dev/feast/tree/v0.8.2) (2020-12-01) +# [v0.8.2](https://github.com/feast-dev/feast/tree/v0.8.2) (2020-12-01) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.8.1...v0.8.2) -**Implemented enhancements:** +### Features - Configurable materialization destination for view in BigQuerySource [\#1201](https://github.com/feast-dev/feast/pull/1201) ([pyalex](https://github.com/pyalex)) -**Fixed bugs:** +### Bug Fixes - Fix tag order for release workflow [\#1205](https://github.com/feast-dev/feast/pull/1205) ([terryyylim](https://github.com/terryyylim)) - Fix Feature Table not updated on new feature addition [\#1197](https://github.com/feast-dev/feast/pull/1197) ([khorshuheng](https://github.com/khorshuheng)) -**Merged pull requests:** +### Merged Pull Requests - Suppress kafka logs in Ingestion Job [\#1206](https://github.com/feast-dev/feast/pull/1206) ([pyalex](https://github.com/pyalex)) - Add project name to metrics labels in Ingestion Job [\#1202](https://github.com/feast-dev/feast/pull/1202) ([pyalex](https://github.com/pyalex)) -## [v0.8.1](https://github.com/feast-dev/feast/tree/v0.8.1) (2020-11-24) +# [v0.8.1](https://github.com/feast-dev/feast/tree/v0.8.1) (2020-11-24) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.8.0...v0.8.1) -**Implemented enhancements:** +### Features - Expires Redis Keys based on Feature Table Max Age [\#1161](https://github.com/feast-dev/feast/pull/1161) ([khorshuheng](https://github.com/khorshuheng)) - Jobservice control loop \(based on \#1140\) [\#1156](https://github.com/feast-dev/feast/pull/1156) ([oavdeev](https://github.com/oavdeev)) -**Fixed bugs:** +### Bug Fixes - Lazy metrics initialization \(to correct pick up in executor\) [\#1195](https://github.com/feast-dev/feast/pull/1195) ([pyalex](https://github.com/pyalex)) - Add missing third\_party folder [\#1185](https://github.com/feast-dev/feast/pull/1185) ([terryyylim](https://github.com/terryyylim)) - Fix missing name variable instantiation [\#1166](https://github.com/feast-dev/feast/pull/1166) ([terryyylim](https://github.com/terryyylim)) -**Merged pull requests:** +### Merged Pull Requests - Bump ssh-agent version [\#1175](https://github.com/feast-dev/feast/pull/1175) ([terryyylim](https://github.com/terryyylim)) - Refactor configurable options and add sphinx docs [\#1174](https://github.com/feast-dev/feast/pull/1174) ([terryyylim](https://github.com/terryyylim)) @@ -1046,11 +1122,11 @@ - Ensure consistency of github workflow [\#1157](https://github.com/feast-dev/feast/pull/1157) ([terryyylim](https://github.com/terryyylim)) -## [v0.8.0](https://github.com/feast-dev/feast/tree/v0.8.0) (2020-11-10) +# [v0.8.0](https://github.com/feast-dev/feast/tree/v0.8.0) (2020-11-10) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.7.1...v0.8.0) -**Implemented enhancements:** +### Features - Implement JobService API calls & connect it to SDK [\#1129](https://github.com/feast-dev/feast/pull/1129) ([tsotnet](https://github.com/tsotnet)) - Allow user to specify custom secrets to be mounted on Feast Serving and Feast Core pods [\#1127](https://github.com/feast-dev/feast/pull/1127) ([khorshuheng](https://github.com/khorshuheng)) @@ -1088,7 +1164,7 @@ - Add Feature Tables API to Core & Python SDK [\#1019](https://github.com/feast-dev/feast/pull/1019) ([mrzzy](https://github.com/mrzzy)) - Introduce Entity as higher-level concept [\#1014](https://github.com/feast-dev/feast/pull/1014) ([terryyylim](https://github.com/terryyylim)) -**Fixed bugs:** +### Bug Fixes - Fix stencil client serialization issue [\#1147](https://github.com/feast-dev/feast/pull/1147) ([pyalex](https://github.com/pyalex)) - Deadletter path is being incorrectly joined [\#1144](https://github.com/feast-dev/feast/pull/1144) ([pyalex](https://github.com/pyalex)) @@ -1099,7 +1175,7 @@ - Fix java class name validation [\#1084](https://github.com/feast-dev/feast/pull/1084) ([oavdeev](https://github.com/oavdeev)) - Multiple tiny AWS related fixes [\#1083](https://github.com/feast-dev/feast/pull/1083) ([oavdeev](https://github.com/oavdeev)) -**Merged pull requests:** +### Merged Pull Requests - Make created\_timestamp property optional in KafkaSource [\#1146](https://github.com/feast-dev/feast/pull/1146) ([pyalex](https://github.com/pyalex)) - In Streaming E2E Test filter kafka consumers by group id prefix [\#1145](https://github.com/feast-dev/feast/pull/1145) ([pyalex](https://github.com/pyalex)) @@ -1148,17 +1224,17 @@ - Refactor Python SDK to remove v1 concepts [\#1023](https://github.com/feast-dev/feast/pull/1023) ([terryyylim](https://github.com/terryyylim)) -## [v0.7.1](https://github.com/feast-dev/feast/tree/v0.7.1) (2020-10-07) +# [v0.7.1](https://github.com/feast-dev/feast/tree/v0.7.1) (2020-10-07) [Full Changelog](https://github.com/feast-dev/feast/compare/sdk/go/v0.7.0...v0.7.1) -**Fixed bugs:** +### Bug Fixes - Provide stable jobName in RowMetrics labels [\#1028](https://github.com/feast-dev/feast/pull/1028) ([pyalex](https://github.com/pyalex)) -## [v0.7.0](https://github.com/feast-dev/feast/tree/v0.7.0) (2020-09-09) +# [v0.7.0](https://github.com/feast-dev/feast/tree/v0.7.0) (2020-09-09) [Full Changelog](https://github.com/feast-dev/feast/compare/sdk/go/v0.6.2...v0.7.0) -**Breaking changes:** +### Breaking Changes - Add request response logging via fluentd [\#961](https://github.com/feast-dev/feast/pull/961) ([terryyylim](https://github.com/terryyylim)) - Run JobCoontroller as separate application [\#951](https://github.com/feast-dev/feast/pull/951) ([pyalex](https://github.com/pyalex)) @@ -1166,7 +1242,7 @@ - Use JobManager's backend as persistent storage and source of truth [\#903](https://github.com/feast-dev/feast/pull/903) ([pyalex](https://github.com/pyalex)) - Fix invalid characters for project, featureset, entity and features creation [\#976](https://github.com/feast-dev/feast/pull/976) ([terryyylim](https://github.com/terryyylim)) -**Implemented enhancements:** +### Features - Add redis key prefix as an option to Redis cluster [\#975](https://github.com/feast-dev/feast/pull/975) ([khorshuheng](https://github.com/khorshuheng)) - Authentication Support for Java & Go SDKs [\#971](https://github.com/feast-dev/feast/pull/971) ([mrzzy](https://github.com/mrzzy)) @@ -1176,7 +1252,7 @@ - Add REST endpoints for Feast UI [\#878](https://github.com/feast-dev/feast/pull/878) ([SwampertX](https://github.com/SwampertX)) - Upgrade Feast dependencies [\#876](https://github.com/feast-dev/feast/pull/876) ([pyalex](https://github.com/pyalex)) -**Fixed bugs:** +### Bug Fixes - Fix Java & Go SDK TLS support [\#986](https://github.com/feast-dev/feast/pull/986) ([mrzzy](https://github.com/mrzzy)) - Fix Python SDK setuptools not supporting tags required for Go SDK to be versioned. [\#983](https://github.com/feast-dev/feast/pull/983) ([mrzzy](https://github.com/mrzzy)) @@ -1211,7 +1287,7 @@ - Fix lint version not pulling tags. [\#999](https://github.com/feast-dev/feast/pull/999)([mrzzy](https://github.com/mrzzy)) - Call fallback only when theres missing keys [\#1009](https://github.com/feast-dev/feast/pull/751) ([pyalex](https://github.com/pyalex)) -**Merged pull requests:** +### Merged Pull Requests - Add cryptography to python ci-requirements [\#988](https://github.com/feast-dev/feast/pull/988) ([pyalex](https://github.com/pyalex)) - Allow maps in environment variables in helm charts [\#987](https://github.com/feast-dev/feast/pull/987) ([pyalex](https://github.com/pyalex)) @@ -1234,10 +1310,10 @@ - BQ sink produces sample of successful inserts [\#875](https://github.com/feast-dev/feast/pull/875) ([pyalex](https://github.com/pyalex)) - Add Branch and RC Awareness to Version Lint & Fix Semver Regex [\#998](https://github.com/feast-dev/feast/pull/998) ([mrzzy](https://github.com/mrzzy)) -## [v0.6.2](https://github.com/feast-dev/feast/tree/v0.6.2) (2020-08-02) +# [v0.6.2](https://github.com/feast-dev/feast/tree/v0.6.2) (2020-08-02) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.6.1...v0.6.2) -**Implemented enhancements:** +### Features - Redis sink flushes only rows that have more recent eventTimestamp [\#913](https://github.com/feast-dev/feast/pull/913) ([pyalex](https://github.com/pyalex)) - Dataflow runner options: disk type & streaming engine [\#906](https://github.com/feast-dev/feast/pull/906) ([pyalex](https://github.com/pyalex)) @@ -1247,40 +1323,40 @@ - Add caching to authorization [\#884](https://github.com/feast-dev/feast/pull/884) ([jmelinav](https://github.com/jmelinav)) - Add Auth header [\#885](https://github.com/feast-dev/feast/pull/885) ([AnujaVane](https://github.com/AnujaVane)) -**Fixed bugs:** +### Bug Fixes - Fix Online Serving unable to retrieve feature data after Feature Set update. [\#908](https://github.com/feast-dev/feast/pull/908) ([mrzzy](https://github.com/mrzzy)) - Fix Python SDK ingestion for featureset name that exist in multiple projects [\#868](https://github.com/feast-dev/feast/pull/868) ([terryyylim](https://github.com/terryyylim)) - Backport delay in Redis acknowledgement of spec [\#915](https://github.com/feast-dev/feast/pull/915) ([woop](https://github.com/woop)) - Allow unauthenticated access when Authorization is disabled and to Health Probe [\#927](https://github.com/feast-dev/feast/pull/927) ([mrzzy](https://github.com/mrzzy)) -**Merged pull requests:** +### Merged Pull Requests - Upgrade Feast dependencies [\#876](https://github.com/feast-dev/feast/pull/876) ([pyalex](https://github.com/pyalex)) -## [v0.6.1](https://github.com/feast-dev/feast/tree/v0.6.1) (2020-07-17) +# [v0.6.1](https://github.com/feast-dev/feast/tree/v0.6.1) (2020-07-17) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.6.0...v0.6.1) -**Implemented enhancements:** +### Features - Improve parallelization in Redis Sink [\#866](https://github.com/feast-dev/feast/pull/866) ([pyalex](https://github.com/pyalex)) - BQ sink produces sample of successful inserts [\#875](https://github.com/feast-dev/feast/pull/875) ([pyalex](https://github.com/pyalex)) -**Fixed bugs:** +### Bug Fixes - Add IngestionId & EventTimestamp to FeatureRowBatch to calculate lag metric correctly [\#874](https://github.com/feast-dev/feast/pull/874) ([pyalex](https://github.com/pyalex)) - Prevent race condition in BQ sink jobId generation [\#877](https://github.com/feast-dev/feast/pull/877) ([pyalex](https://github.com/pyalex)) -## [v0.6.0](https://github.com/feast-dev/feast/tree/v0.6.0) (2020-07-13) +# [v0.6.0](https://github.com/feast-dev/feast/tree/v0.6.0) (2020-07-13) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.5.1...v0.6.0) -**Breaking changes:** +### Breaking Changes - Compute and write metrics for rows prior to store writes [\#763](https://github.com/feast-dev/feast/pull/763) ([zhilingc](https://github.com/zhilingc)) -**Implemented enhancements:** +### Features - Allow users compute statistics over retrieved batch datasets [\#799](https://github.com/feast-dev/feast/pull/799) ([zhilingc](https://github.com/zhilingc)) - Replace Keto Authorization with External HTTP Authorization [\#864](https://github.com/feast-dev/feast/pull/864) ([woop](https://github.com/woop)) @@ -1298,7 +1374,7 @@ - Authentication and authorization support [\#793](https://github.com/feast-dev/feast/pull/793) ([dr3s](https://github.com/dr3s)) - Add API for listing feature sets using labels [\#785](https://github.com/feast-dev/feast/pull/785) ([terryyylim](https://github.com/terryyylim)) -**Fixed bugs:** +### Bug Fixes - Bypass authentication for metric endpoints [\#862](https://github.com/feast-dev/feast/pull/862) ([woop](https://github.com/woop)) - Python SDK listing of ingestion job fails for featureset reference filter [\#861](https://github.com/feast-dev/feast/pull/861) ([terryyylim](https://github.com/terryyylim)) @@ -1318,7 +1394,7 @@ - Fix pipeline options toArgs\(\) returning empty list [\#765](https://github.com/feast-dev/feast/pull/765) ([zhilingc](https://github.com/zhilingc)) - Remove usage of parallel stream for feature value map generation [\#751](https://github.com/feast-dev/feast/pull/751) ([khorshuheng](https://github.com/khorshuheng)) -**Merged pull requests:** +### Merged Pull Requests - Remove Spring Boot from auth tests [\#859](https://github.com/feast-dev/feast/pull/859) ([woop](https://github.com/woop)) - Authentication and Authorization into feast-auth module. [\#856](https://github.com/feast-dev/feast/pull/856) ([jmelinav](https://github.com/jmelinav)) @@ -1356,11 +1432,11 @@ [Full Changelog](https://github.com/feast-dev/feast/compare/v0.5.0...v0.5.1) -**Implemented enhancements:** +### Features - Add support for version method in Feast SDK and Core [\#759](https://github.com/feast-dev/feast/pull/759) ([woop](https://github.com/woop)) - Refactor runner configuration, add labels to dataflow options [\#718](https://github.com/feast-dev/feast/pull/718) ([zhilingc](https://github.com/zhilingc)) -**Fixed bugs:** +### Bug Fixes - Fix pipeline options toArgs\(\) returning empty list [\#765](https://github.com/feast-dev/feast/pull/765) ([zhilingc](https://github.com/zhilingc)) - Fix project argument for feature set describe in CLI [\#731](https://github.com/feast-dev/feast/pull/731) ([terryyylim](https://github.com/terryyylim)) - Fix Go and Java SDK Regressions [\#729](https://github.com/feast-dev/feast/pull/729) ([mrzzy](https://github.com/mrzzy)) @@ -1368,17 +1444,17 @@ - Restore Feast Java SDK and Ingestion compatibility with Java 8 runtimes [\#722](https://github.com/feast-dev/feast/pull/722) ([ches](https://github.com/ches)) - Python sdk bug fixes [\#723](https://github.com/feast-dev/feast/pull/723) ([zhilingc](https://github.com/zhilingc)) -**Merged pull requests:** +### Merged Pull Requests - Increase Jaeger Tracing coverage [\#719](https://github.com/feast-dev/feast/pull/719) ([terryyylim](https://github.com/terryyylim)) - Recompile golang protos to include new FeatureSetStatus [\#755](https://github.com/feast-dev/feast/pull/755) ([zhilingc](https://github.com/zhilingc)) - Merge Redis cluster connector with Redis connector [\#752](https://github.com/feast-dev/feast/pull/752) ([pyalex](https://github.com/pyalex)) - Remove unused Hibernate dep from Serving [\#721](https://github.com/feast-dev/feast/pull/721) ([ches](https://github.com/ches)) -## [v0.5.0](https://github.com/feast-dev/feast/tree/v0.5.0) (2020-05-19) +# [v0.5.0](https://github.com/feast-dev/feast/tree/v0.5.0) (2020-05-19) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.7...v0.5.0) -**Breaking changes:** +### Breaking Changes - Add .proto to packages of Protobuf generated Java classes [\#700](https://github.com/feast-dev/feast/pull/700) ([woop](https://github.com/woop)) - Add support for feature set updates and remove versions [\#676](https://github.com/feast-dev/feast/pull/676) ([zhilingc](https://github.com/zhilingc)) @@ -1386,7 +1462,7 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for more details. -**Implemented enhancements:** +### Features - Add general storage API and refactor existing store implementations [\#567](https://github.com/feast-dev/feast/pull/567) ([zhilingc](https://github.com/zhilingc)) - Add support for feature set updates and remove versions [\#676](https://github.com/feast-dev/feast/pull/676) ([zhilingc](https://github.com/zhilingc)) @@ -1399,7 +1475,7 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Add feature and feature set labels for metadata [\#536](https://github.com/feast-dev/feast/pull/536) ([imjuanleonard](https://github.com/imjuanleonard)) - Update Python SDK so FeatureSet can import Schema from Tensorflow metadata [\#450](https://github.com/feast-dev/feast/pull/450) ([davidheryanto](https://github.com/davidheryanto)) -**Fixed bugs:** +### Bug Fixes - Add feature set status JOB\_STARTING to denote feature sets waiting for job to get to RUNNING state [\#714](https://github.com/feast-dev/feast/pull/714) ([zhilingc](https://github.com/zhilingc)) - Remove feature set status check for job update requirement [\#708](https://github.com/feast-dev/feast/pull/708) ([khorshuheng](https://github.com/khorshuheng)) @@ -1415,7 +1491,7 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Fix Feast Serving not registering its store in Feast Core [\#641](https://github.com/feast-dev/feast/pull/641) ([mrzzy](https://github.com/mrzzy)) - Kafka producer should raise an exception when it fails to connect to broker [\#636](https://github.com/feast-dev/feast/pull/636) ([junhui096](https://github.com/junhui096)) -**Merged pull requests:** +### Merged Pull Requests - Change organization from gojek to feast-dev [\#712](https://github.com/feast-dev/feast/pull/712) ([woop](https://github.com/woop)) - Extract feature set update tests so CI doesn't run it [\#709](https://github.com/feast-dev/feast/pull/709) ([zhilingc](https://github.com/zhilingc)) @@ -1449,11 +1525,11 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Apply a fixed window before writing row metrics [\#590](https://github.com/feast-dev/feast/pull/590) ([davidheryanto](https://github.com/davidheryanto)) - Allow tests to run on non-master branches [\#588](https://github.com/feast-dev/feast/pull/588) ([woop](https://github.com/woop)) -## [v0.4.7](https://github.com/feast-dev/feast/tree/v0.4.7) (2020-03-17) +# [v0.4.7](https://github.com/feast-dev/feast/tree/v0.4.7) (2020-03-17) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.6...v0.4.7) -**Merged pull requests:** +### Merged Pull Requests - Add log4j-web jar to core and serving. [\#498](https://github.com/feast-dev/feast/pull/498) ([Yanson](https://github.com/Yanson)) - Clear all the futures when sync is called. [\#501](https://github.com/feast-dev/feast/pull/501) ([lavkesh](https://github.com/lavkesh)) - Encode feature row before storing in Redis [\#530](https://github.com/feast-dev/feast/pull/530) ([khorshuheng](https://github.com/khorshuheng)) @@ -1462,11 +1538,11 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Parameterize end to end test scripts. [\#433](https://github.com/feast-dev/feast/pull/433) ([Yanson](https://github.com/Yanson)) - Replacing Jedis With Lettuce in ingestion and serving [\#485](https://github.com/feast-dev/feast/pull/485) ([lavkesh](https://github.com/lavkesh)) -## [v0.4.6](https://github.com/feast-dev/feast/tree/v0.4.6) (2020-02-26) +# [v0.4.6](https://github.com/feast-dev/feast/tree/v0.4.6) (2020-02-26) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.5...v0.4.6) -**Merged pull requests:** +### Merged Pull Requests - Rename metric name for request latency in feast serving [\#488](https://github.com/feast-dev/feast/pull/488) ([davidheryanto](https://github.com/davidheryanto)) - Allow use of secure gRPC in Feast Python client [\#459](https://github.com/feast-dev/feast/pull/459) ([Yanson](https://github.com/Yanson)) - Extend WriteMetricsTransform in Ingestion to write feature value stats to StatsD [\#486](https://github.com/feast-dev/feast/pull/486) ([davidheryanto](https://github.com/davidheryanto)) @@ -1475,11 +1551,11 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Fail Spotless formatting check before tests execute [\#487](https://github.com/feast-dev/feast/pull/487) ([ches](https://github.com/ches)) - Reduce refresh rate of specification refresh in Serving to 10 seconds [\#481](https://github.com/feast-dev/feast/pull/481) ([woop](https://github.com/woop)) -## [v0.4.5](https://github.com/feast-dev/feast/tree/v0.4.5) (2020-02-14) +# [v0.4.5](https://github.com/feast-dev/feast/tree/v0.4.5) (2020-02-14) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.4...v0.4.5) -**Merged pull requests:** +### Merged Pull Requests - Use bzip2 compressed feature set json as pipeline option [\#466](https://github.com/feast-dev/feast/pull/466) ([khorshuheng](https://github.com/khorshuheng)) - Make redis key creation more determinisitic [\#471](https://github.com/feast-dev/feast/pull/471) ([zhilingc](https://github.com/zhilingc)) - Helm Chart Upgrades [\#458](https://github.com/feast-dev/feast/pull/458) ([Yanson](https://github.com/Yanson)) @@ -1490,11 +1566,11 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Deduplicate example notebooks [\#456](https://github.com/feast-dev/feast/pull/456) ([woop](https://github.com/woop)) - Allow users not to set max age for batch retrieval [\#446](https://github.com/feast-dev/feast/pull/446) ([zhilingc](https://github.com/zhilingc)) -## [v0.4.4](https://github.com/feast-dev/feast/tree/v0.4.4) (2020-01-28) +# [v0.4.4](https://github.com/feast-dev/feast/tree/v0.4.4) (2020-01-28) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.3...v0.4.4) -**Merged pull requests:** +### Merged Pull Requests - Change RedisBackedJobService to use a connection pool [\#439](https://github.com/feast-dev/feast/pull/439) ([zhilingc](https://github.com/zhilingc)) - Update GKE installation and chart values to work with 0.4.3 [\#434](https://github.com/feast-dev/feast/pull/434) ([lgvital](https://github.com/lgvital)) @@ -1506,23 +1582,23 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Update basic Feast example to Feast 0.4 [\#424](https://github.com/feast-dev/feast/pull/424) ([woop](https://github.com/woop)) - Introduce datatypes/java module for proto generation [\#391](https://github.com/feast-dev/feast/pull/391) ([ches](https://github.com/ches)) -## [v0.4.3](https://github.com/feast-dev/feast/tree/v0.4.3) (2020-01-08) +# [v0.4.3](https://github.com/feast-dev/feast/tree/v0.4.3) (2020-01-08) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.2...v0.4.3) -**Fixed bugs:** +### Bug Fixes - Bugfix for redis ingestion retries throwing NullPointerException on remote runners [\#417](https://github.com/feast-dev/feast/pull/417) ([khorshuheng](https://github.com/khorshuheng)) -## [v0.4.2](https://github.com/feast-dev/feast/tree/v0.4.2) (2020-01-07) +# [v0.4.2](https://github.com/feast-dev/feast/tree/v0.4.2) (2020-01-07) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.1...v0.4.2) -**Fixed bugs:** +### Bug Fixes - Missing argument in error string in ValidateFeatureRowDoFn [\#401](https://github.com/feast-dev/feast/issues/401) -**Merged pull requests:** +### Merged Pull Requests - Define maven revision property when packaging jars in Dockerfile so the images are built successfully [\#410](https://github.com/feast-dev/feast/pull/410) ([davidheryanto](https://github.com/davidheryanto)) - Deduplicate rows in subquery [\#409](https://github.com/feast-dev/feast/pull/409) ([zhilingc](https://github.com/zhilingc)) @@ -1533,24 +1609,24 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Use Nexus staging plugin for deployment [\#394](https://github.com/feast-dev/feast/pull/394) ([khorshuheng](https://github.com/khorshuheng)) - Handle retry for redis io flow [\#274](https://github.com/feast-dev/feast/pull/274) ([khorshuheng](https://github.com/khorshuheng)) -## [v0.4.1](https://github.com/feast-dev/feast/tree/v0.4.1) (2019-12-30) +# [v0.4.1](https://github.com/feast-dev/feast/tree/v0.4.1) (2019-12-30) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.4.0...v0.4.1) -**Merged pull requests:** +### Merged Pull Requests - Add project-related commands to CLI [\#397](https://github.com/feast-dev/feast/pull/397) ([zhilingc](https://github.com/zhilingc)) -## [v0.4.0](https://github.com/feast-dev/feast/tree/v0.4.0) (2019-12-28) +# [v0.4.0](https://github.com/feast-dev/feast/tree/v0.4.0) (2019-12-28) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.5...v0.4.0) -**Implemented enhancements:** +### Features - Edit description in feature specification to also reflect in BigQuery schema description. [\#239](https://github.com/feast-dev/feast/issues/239) - Allow for disabling of metrics pushing [\#57](https://github.com/feast-dev/feast/issues/57) -**Merged pull requests:** +### Merged Pull Requests - Java SDK release script [\#406](https://github.com/feast-dev/feast/pull/406) ([davidheryanto](https://github.com/davidheryanto)) - Use fixed 'dev' revision for test-e2e-batch [\#395](https://github.com/feast-dev/feast/pull/395) ([davidheryanto](https://github.com/davidheryanto)) @@ -1568,62 +1644,62 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Add readiness checks for Feast services in end to end test [\#337](https://github.com/feast-dev/feast/pull/337) ([davidheryanto](https://github.com/davidheryanto)) - Create CHANGELOG.md [\#321](https://github.com/feast-dev/feast/pull/321) ([woop](https://github.com/woop)) -## [v0.3.8](https://github.com/feast-dev/feast/tree/v0.3.8) (2020-06-10) +# [v0.3.8](https://github.com/feast-dev/feast/tree/v0.3.8) (2020-06-10) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.7...v0.3.8) -**Implemented enhancements:** +### Features - v0.3 backport: Add feature and feature set labels [\#737](https://github.com/feast-dev/feast/pull/737) ([ches](https://github.com/ches)) -**Merged pull requests:** +### Merged Pull Requests - v0.3 backport: Add Java coverage reporting [\#734](https://github.com/feast-dev/feast/pull/734) ([ches](https://github.com/ches)) -## [v0.3.7](https://github.com/feast-dev/feast/tree/v0.3.7) (2020-05-01) +# [v0.3.7](https://github.com/feast-dev/feast/tree/v0.3.7) (2020-05-01) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.6...v0.3.7) -**Merged pull requests:** +### Merged Pull Requests - Moved end-to-end test scripts from .prow to infra [\#657](https://github.com/feast-dev/feast/pull/657) ([khorshuheng](https://github.com/khorshuheng)) - Backported \#566 & \#647 to v0.3 [\#654](https://github.com/feast-dev/feast/pull/654) ([ches](https://github.com/ches)) -## [v0.3.6](https://github.com/feast-dev/feast/tree/v0.3.6) (2020-01-03) +# [v0.3.6](https://github.com/feast-dev/feast/tree/v0.3.6) (2020-01-03) -**Merged pull requests:** +### Merged Pull Requests [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.5...v0.3.6) - Add support for file paths for providing entity rows during batch retrieval [\#375](https://github.com/feast-dev/feast/pull/375) ([voonhous](https://github.com/voonhous)) -## [v0.3.5](https://github.com/feast-dev/feast/tree/v0.3.5) (2019-12-26) +# [v0.3.5](https://github.com/feast-dev/feast/tree/v0.3.5) (2019-12-26) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.4...v0.3.5) -**Merged pull requests:** +### Merged Pull Requests - Always set destination table in BigQuery query config in Feast Batch Serving so it can handle large results [\#392](https://github.com/feast-dev/feast/pull/392) ([davidheryanto](https://github.com/davidheryanto)) -## [v0.3.4](https://github.com/feast-dev/feast/tree/v0.3.4) (2019-12-23) +# [v0.3.4](https://github.com/feast-dev/feast/tree/v0.3.4) (2019-12-23) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.3...v0.3.4) -**Merged pull requests:** +### Merged Pull Requests - Make redis key creation more determinisitic [\#380](https://github.com/feast-dev/feast/pull/380) ([zhilingc](https://github.com/zhilingc)) -## [v0.3.3](https://github.com/feast-dev/feast/tree/v0.3.3) (2019-12-18) +# [v0.3.3](https://github.com/feast-dev/feast/tree/v0.3.3) (2019-12-18) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.2...v0.3.3) -**Implemented enhancements:** +### Features - Added Docker Compose for Feast [\#272](https://github.com/feast-dev/feast/issues/272) - Added ability to check import job status and cancel job through Python SDK [\#194](https://github.com/feast-dev/feast/issues/194) - Added basic customer transactions example [\#354](https://github.com/feast-dev/feast/pull/354) ([woop](https://github.com/woop)) -**Merged pull requests:** +### Merged Pull Requests - Added Prow jobs to automate the release of Docker images and Python SDK [\#369](https://github.com/feast-dev/feast/pull/369) ([davidheryanto](https://github.com/davidheryanto)) - Fixed installation link in README.md [\#368](https://github.com/feast-dev/feast/pull/368) ([Jeffwan](https://github.com/Jeffwan)) @@ -1639,11 +1715,11 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Added docker-compose file with Jupyter notebook [\#328](https://github.com/feast-dev/feast/pull/328) ([khorshuheng](https://github.com/khorshuheng)) - Added minimal implementation of ingesting Parquet and CSV files [\#327](https://github.com/feast-dev/feast/pull/327) ([voonhous](https://github.com/voonhous)) -## [v0.3.2](https://github.com/feast-dev/feast/tree/v0.3.2) (2019-11-29) +# [v0.3.2](https://github.com/feast-dev/feast/tree/v0.3.2) (2019-11-29) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.1...v0.3.2) -**Merged pull requests:** +### Merged Pull Requests - Fixed incorrect BigQuery schema creation from FeatureSetSpec [\#340](https://github.com/feast-dev/feast/pull/340) ([davidheryanto](https://github.com/davidheryanto)) - Filtered out feature sets that dont share the same source [\#339](https://github.com/feast-dev/feast/pull/339) ([zhilingc](https://github.com/zhilingc)) @@ -1656,17 +1732,17 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Pinned Python SDK to minor versions for dependencies [\#322](https://github.com/feast-dev/feast/pull/322) ([woop](https://github.com/woop)) - Added Auto format to Google style with Spotless [\#317](https://github.com/feast-dev/feast/pull/317) ([ches](https://github.com/ches)) -## [v0.3.1](https://github.com/feast-dev/feast/tree/v0.3.1) (2019-11-25) +# [v0.3.1](https://github.com/feast-dev/feast/tree/v0.3.1) (2019-11-25) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.3.0...v0.3.1) -**Merged pull requests:** +### Merged Pull Requests - Added Prometheus metrics to serving [\#316](https://github.com/feast-dev/feast/pull/316) ([zhilingc](https://github.com/zhilingc)) - Changed default job metrics sink to Statsd [\#315](https://github.com/feast-dev/feast/pull/315) ([zhilingc](https://github.com/zhilingc)) - Fixed module import error in Feast CLI [\#314](https://github.com/feast-dev/feast/pull/314) ([davidheryanto](https://github.com/davidheryanto)) -## [v0.3.0](https://github.com/feast-dev/feast/tree/v0.3.0) (2019-11-19) +# [v0.3.0](https://github.com/feast-dev/feast/tree/v0.3.0) (2019-11-19) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.1.8...v0.3.0) @@ -1681,7 +1757,7 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for * Added job management to Feast Core to manage ingestion/population jobs to remote Feast deployments * Added metric support through Prometheus -**Merged pull requests:** +### Merged Pull Requests - Regenerate go protos [\#313](https://github.com/feast-dev/feast/pull/313) ([zhilingc](https://github.com/zhilingc)) - Bump chart version to 0.3.0 [\#311](https://github.com/feast-dev/feast/pull/311) ([zhilingc](https://github.com/zhilingc)) @@ -1709,11 +1785,11 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Move storage configuration to serving [\#254](https://github.com/feast-dev/feast/pull/254) ([zhilingc](https://github.com/zhilingc)) - Serving API changes for 0.3 [\#253](https://github.com/feast-dev/feast/pull/253) ([zhilingc](https://github.com/zhilingc)) -## [v0.1.8](https://github.com/feast-dev/feast/tree/v0.1.8) (2019-10-30) +# [v0.1.8](https://github.com/feast-dev/feast/tree/v0.1.8) (2019-10-30) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.1.2...v0.1.8) -**Implemented enhancements:** +### Features - Feast cli config file should be settable by an env var [\#149](https://github.com/feast-dev/feast/issues/149) - Helm chart for deploying feast using Flink as runner [\#64](https://github.com/feast-dev/feast/issues/64) @@ -1722,28 +1798,28 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Change config to yaml [\#51](https://github.com/feast-dev/feast/issues/51) - Ability to pass runner option during ingestion job submission [\#50](https://github.com/feast-dev/feast/issues/50) -**Fixed bugs:** +### Bug Fixes - Fix Print Method in Feast CLI [\#211](https://github.com/feast-dev/feast/issues/211) - Dataflow monitoring by core is failing with incorrect job id [\#153](https://github.com/feast-dev/feast/issues/153) - Feast core crashes without logger set [\#150](https://github.com/feast-dev/feast/issues/150) -**Merged pull requests:** +### Merged Pull Requests - Remove redis transaction [\#280](https://github.com/feast-dev/feast/pull/280) ([pradithya](https://github.com/pradithya)) - Fix tracing to continue from existing trace created by grpc client [\#245](https://github.com/feast-dev/feast/pull/245) ([pradithya](https://github.com/pradithya)) -## [v0.1.2](https://github.com/feast-dev/feast/tree/v0.1.2) (2019-08-23) +# [v0.1.2](https://github.com/feast-dev/feast/tree/v0.1.2) (2019-08-23) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.1.1...v0.1.2) -**Fixed bugs:** +### Bug Fixes - Batch Import, feature with datetime format issue [\#203](https://github.com/feast-dev/feast/issues/203) - Serving not correctly reporting readiness check if there is no activity [\#190](https://github.com/feast-dev/feast/issues/190) - Serving stop periodically reloading feature specification after a while [\#188](https://github.com/feast-dev/feast/issues/188) -**Merged pull requests:** +### Merged Pull Requests - Add `romanwozniak` to prow owners config [\#216](https://github.com/feast-dev/feast/pull/216) ([romanwozniak](https://github.com/romanwozniak)) - Implement filter for create dataset api [\#215](https://github.com/feast-dev/feast/pull/215) ([pradithya](https://github.com/pradithya)) @@ -1767,36 +1843,36 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Continuous integration and deployment \(CI/CD\) update [\#183](https://github.com/feast-dev/feast/pull/183) ([davidheryanto](https://github.com/davidheryanto)) - Remove feature specs being able to declare their serving or warehouse stores [\#159](https://github.com/feast-dev/feast/pull/159) ([tims](https://github.com/tims)) -## [v0.1.1](https://github.com/feast-dev/feast/tree/v0.1.1) (2019-04-18) +# [v0.1.1](https://github.com/feast-dev/feast/tree/v0.1.1) (2019-04-18) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.1.0...v0.1.1) -**Fixed bugs:** +### Bug Fixes - Fix BigQuery query template to retrieve training data [\#182](https://github.com/feast-dev/feast/pull/182) ([davidheryanto](https://github.com/davidheryanto)) -**Merged pull requests:** +### Merged Pull Requests - Add python init files [\#176](https://github.com/feast-dev/feast/pull/176) ([zhilingc](https://github.com/zhilingc)) - Change pypi package from Feast to feast [\#173](https://github.com/feast-dev/feast/pull/173) ([zhilingc](https://github.com/zhilingc)) -## [v0.1.0](https://github.com/feast-dev/feast/tree/v0.1.0) (2019-04-09) +# [v0.1.0](https://github.com/feast-dev/feast/tree/v0.1.0) (2019-04-09) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.0.2...v0.1.0) -**Implemented enhancements:** +### Features - Removal of storing historical value of feature in serving storage [\#53](https://github.com/feast-dev/feast/issues/53) - Remove feature "granularity" and relegate to metadata [\#17](https://github.com/feast-dev/feast/issues/17) -**Closed issues:** +### Closes Issues - Add ability to name an import job [\#167](https://github.com/feast-dev/feast/issues/167) - Ingestion retrying an invalid FeatureRow endlessly [\#163](https://github.com/feast-dev/feast/issues/163) - Ability to associate data ingested in Warehouse store to its ingestion job [\#145](https://github.com/feast-dev/feast/issues/145) - Missing \(Fixing\) unit test for FeatureRowKafkaIO [\#132](https://github.com/feast-dev/feast/issues/132) -**Merged pull requests:** +### Merged Pull Requests - Catch all kind of exception to avoid retrying [\#171](https://github.com/feast-dev/feast/pull/171) ([pradithya](https://github.com/pradithya)) - Integration test [\#170](https://github.com/feast-dev/feast/pull/170) ([zhilingc](https://github.com/zhilingc)) @@ -1824,16 +1900,16 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Coalesce rows [\#89](https://github.com/feast-dev/feast/pull/89) ([tims](https://github.com/tims)) - Remove historical feature in serving store [\#87](https://github.com/feast-dev/feast/pull/87) ([pradithya](https://github.com/pradithya)) -## [v0.0.2](https://github.com/feast-dev/feast/tree/v0.0.2) (2019-03-11) +# [v0.0.2](https://github.com/feast-dev/feast/tree/v0.0.2) (2019-03-11) [Full Changelog](https://github.com/feast-dev/feast/compare/v0.0.1...v0.0.2) -**Implemented enhancements:** +### Features - Coalesce FeatureRows for improved "latest" value consistency in serving stores [\#88](https://github.com/feast-dev/feast/issues/88) - Kafka source [\#22](https://github.com/feast-dev/feast/issues/22) -**Closed issues:** +### Closes Issues - Preload Feast's spec in serving cache [\#151](https://github.com/feast-dev/feast/issues/151) - Feast csv data upload job [\#137](https://github.com/feast-dev/feast/issues/137) @@ -1843,16 +1919,16 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - Listing resources and finding out system state [\#131](https://github.com/feast-dev/feast/issues/131) - Reorganise ingestion store classes to match architecture [\#109](https://github.com/feast-dev/feast/issues/109) -## [v0.0.1](https://github.com/feast-dev/feast/tree/v0.0.1) (2019-02-11) +# [v0.0.1](https://github.com/feast-dev/feast/tree/v0.0.1) (2019-02-11) [Full Changelog](https://github.com/feast-dev/feast/compare/ec9def2bbb06dc759538e4424caadd70f548ea64...v0.0.1) -**Implemented enhancements:** +### Features - Spring boot CLI logs show up as JSON [\#104](https://github.com/feast-dev/feast/issues/104) - Allow for registering feature that doesn't have warehouse store [\#5](https://github.com/feast-dev/feast/issues/5) -**Fixed bugs:** +### Bug Fixes - Error when submitting large import spec [\#125](https://github.com/feast-dev/feast/issues/125) - Ingestion is not ignoring unknown feature in streaming source [\#99](https://github.com/feast-dev/feast/issues/99) @@ -1863,7 +1939,7 @@ See [Feast 0.5 Release Issue](https://github.com/feast-dev/feast/issues/527) for - \[FlinkRunner\] Core should not follow remote flink runner job to completion [\#21](https://github.com/feast-dev/feast/issues/21) - Go packages in protos use incorrect repo [\#16](https://github.com/feast-dev/feast/issues/16) -**Merged pull requests:** +### Merged Pull Requests - Disable test during docker image creation [\#129](https://github.com/feast-dev/feast/pull/129) ([pradithya](https://github.com/pradithya)) - Repackage helm chart [\#127](https://github.com/feast-dev/feast/pull/127) ([pradithya](https://github.com/pradithya)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62e42d4df09..cb17012eea3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,11 +4,24 @@ ## Overview This guide is targeted at developers looking to contribute to Feast components in the main Feast repository: -- [Feast Python SDK / CLI](#feast-python-sdk-%2F-cli) +- [Feast Python SDK / CLI](#feast-python-sdk--cli) - [Feast Java Serving](#feast-java-serving) - [Feast Go Client](#feast-go-client) +## Community +See [Contribution process](https://docs.feast.dev/project/contributing) and [Community](https://docs.feast.dev/community) for details on how to get more involved in the community. + +A quick few highlights: +- [RFCs](https://drive.google.com/drive/u/0/folders/0AAe8j7ZK3sxSUk9PVA) +- [Community Slack](https://slack.feast.dev/) +- [Feast Dev Mailing List](https://groups.google.com/g/feast-dev) +- [Community Calendar](https://calendar.google.com/calendar/u/0?cid=ZTFsZHVhdGM3MDU3YTJucTBwMzNqNW5rajBAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ) + - Includes biweekly community calls at 10AM PST + ## Making a pull request +We use the convention that the assignee of a PR is the person with the next action. + +This means that often, the assignee may be empty (if no reviewer has been found yet), the reviewer, or the PR writer if there are comments to be addressed. ### Pull request checklist A quick list of things to keep in mind as you're making changes: @@ -20,12 +33,12 @@ A quick list of things to keep in mind as you're making changes: - When you make the PR - Make a pull request from the forked repo you made - Ensure you add a GitHub **label** (i.e. a kind tag to the PR (e.g. `kind/bug` or `kind/housekeeping`)) or else checks will fail. - - Ensure you leave a release note for any user facing changes in the PR. There is a field automatically generated in the PR request. You can write `NONE` in that field if there are no user facing changes. + - Ensure you leave a release note for any user facing changes in the PR. There is a field automatically generated in the PR request. You can write `NONE` in that field if there are no user facing changes. - Please run tests locally before submitting a PR (e.g. for Python, the [local integration tests](#local-integration-tests)) - Try to keep PRs smaller. This makes them easier to review. ### Forking the repo -Fork the Feast Github repo and clone your fork locally. Then make changes to a local branch to the fork. +Fork the Feast Github repo and clone your fork locally. Then make changes to a local branch to the fork. See [Creating a pull request from a fork](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) @@ -40,10 +53,10 @@ pre-commit install --hook-type pre-commit --hook-type pre-push 3. On push, the pre-commit hook will run. This runs `make format` and `make lint`. ### Signing off commits -> :warning: Warning: using the default integrations with IDEs like VSCode or IntelliJ will not sign commits. +> :warning: Warning: using the default integrations with IDEs like VSCode or IntelliJ will not sign commits. > When you submit a PR, you'll have to re-sign commits to pass the DCO check. -Use git signoffs to sign your commits. See +Use git signoffs to sign your commits. See https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification for details Then, you can sign off commits with the `-s` flag: @@ -121,15 +134,15 @@ There are two sets of tests you can run: To get local integration tests running, you'll need to have Redis setup: Redis -1. Install Redis: [Quickstart](https://redis.io/topics/quickstart) -2. Run `redis-server` +1. Install Redis: [Quickstart](https://redis.io/topics/quickstart) +2. Run `redis-server` Now run `make test-python-universal-local` #### Full integration tests To test across clouds, on top of setting up Redis, you also need GCP / AWS / Snowflake setup. -> Note: you can manually control what tests are run today by inspecting +> Note: you can manually control what tests are run today by inspecting > [RepoConfiguration](https://github.com/feast-dev/feast/blob/master/sdk/python/tests/integration/feature_repos/repo_configuration.py) > and commenting out tests that are added to `DEFAULT_FULL_REPO_CONFIGS` @@ -151,6 +164,22 @@ To test across clouds, on top of setting up Redis, you also need GCP / AWS / Sno Then run `make test-python-integration`. Note that for Snowflake / GCP / AWS, this will create new temporary tables / datasets. +#### (Experimental) Run full integration tests against containerized services +Test across clouds requires existing accounts on GCP / AWS / Snowflake, and may incur costs when using these services. + +For this approach of running tests, you'll need to have docker set up locally: [Get Docker](https://docs.docker.com/get-docker/) + +It's possible to run some integration tests against emulated local versions of these services, using ephemeral containers. +These tests create new temporary tables / datasets locally only, and they are cleaned up. when the containers are torn down. + +The services with containerized replacements currently implemented are: +- Datastore +- DynamoDB +- Redis + +You can run `make test-python-integration-container` to run tests against the containerized versions of dependencies. + + ## Feast Java Serving See [Java contributing guide](java/CONTRIBUTING.md) @@ -187,4 +216,18 @@ go vet Unit tests for the Feast Go Client can be run as follows: ```sh go test -``` \ No newline at end of file +``` + +### Testing with Github Actions workflows +* Update your current master on your forked branch and make a pull request against your own forked master. +* Enable workflows by going to actions and clicking `Enable Workflows`. + * Pushes will now run your edited workflow yaml file against your test code. + * Unfortunately, in order to test any github workflow changes, you must push the code to the branch and see the output in the actions tab. + +## Issues +* pr-integration-tests workflow is skipped + * Add `ok-to-test` github label. +* pr-integration-tests errors out with `Error: fatal: invalid refspec '+refs/pull//merge:refs/remotes/pull//merge'` + * This is because github actions cannot pull the branch version for some reason so just find your PR number in your pull request header and hard code it into the `uses: actions/checkout@v2` section (i.e replace `refs/pull/${{ github.event.pull_request.number }}/merge` with `refs/pull//merge`) +* AWS/GCP workflow + * Currently still cannot test GCP/AWS workflow without setting up secrets in a forked repository. diff --git a/Makefile b/Makefile index 164f6afb54d..4d961a04725 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,11 @@ ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) MVN := mvn -f java/pom.xml ${MAVEN_EXTRA_OPTS} -PROTO_TYPE_SUBDIRS = core serving types storage -PROTO_SERVICE_SUBDIRS = core serving OS := linux ifeq ($(shell uname -s), Darwin) OS = osx endif +TRINO_VERSION ?= 376 # General @@ -33,15 +32,13 @@ test: test-python test-java test-go protos: compile-protos-go compile-protos-python compile-protos-docs -build: protos build-java build-docker build-html - -install-ci-dependencies: install-python-ci-dependencies install-java-ci-dependencies install-go-ci-dependencies +build: protos build-java build-docker # Python SDK -install-python-ci-dependencies: +install-python-ci-dependencies: install-go-proto-dependencies install-go-ci-dependencies cd sdk/python && python -m piptools sync requirements/py$(PYTHON)-ci-requirements.txt - cd sdk/python && python setup.py develop + cd sdk/python && COMPILE_GO=true python setup.py develop lock-python-ci-dependencies: cd sdk/python && python -m piptools compile -U --extra ci --output-file requirements/py$(PYTHON)-ci-requirements.txt @@ -50,8 +47,7 @@ package-protos: cp -r ${ROOT_DIR}/protos ${ROOT_DIR}/sdk/python/feast/protos compile-protos-python: - @$(foreach dir,$(PROTO_TYPE_SUBDIRS),cd ${ROOT_DIR}/protos; python -m grpc_tools.protoc -I. --grpc_python_out=../sdk/python/feast/protos/ --python_out=../sdk/python/feast/protos/ --mypy_out=../sdk/python/feast/protos/ feast/$(dir)/*.proto;) - @$(foreach dir,$(PROTO_TYPE_SUBDIRS),grep -rli 'from feast.$(dir)' sdk/python/feast/protos | xargs -I@ sed -i.bak 's/from feast.$(dir)/from feast.protos.feast.$(dir)/g' @;) + cd sdk/python && python setup.py build_python_protos install-python: cd sdk/python && python -m piptools sync requirements/py$(PYTHON)-requirements.txt @@ -72,12 +68,21 @@ test-python: test-python-integration: FEAST_USAGE=False IS_TEST=True python -m pytest -n 8 --integration sdk/python/tests +test-python-integration-container: + FEAST_USAGE=False IS_TEST=True FEAST_LOCAL_ONLINE_CONTAINER=True python -m pytest -n 8 --integration sdk/python/tests + +test-python-universal-contrib: + PYTHONPATH='.' FULL_REPO_CONFIGS_MODULE=sdk.python.feast.infra.offline_stores.contrib.contrib_repo_configuration FEAST_USAGE=False IS_TEST=True python -m pytest -n 8 --integration --universal sdk/python/tests + test-python-universal-local: FEAST_USAGE=False IS_TEST=True FEAST_IS_LOCAL_TEST=True python -m pytest -n 8 --integration --universal sdk/python/tests test-python-universal: FEAST_USAGE=False IS_TEST=True python -m pytest -n 8 --integration --universal sdk/python/tests +test-python-go-server: compile-go-lib + FEAST_USAGE=False IS_TEST=True FEAST_GO_FEATURE_RETRIEVAL=True pytest --integration --goserver sdk/python/tests + format-python: # Sort cd ${ROOT_DIR}/sdk/python; python -m isort feast/ tests/ @@ -86,7 +91,7 @@ format-python: cd ${ROOT_DIR}/sdk/python; python -m black --target-version py37 feast tests lint-python: - cd ${ROOT_DIR}/sdk/python; python -m mypy feast/ tests/ + cd ${ROOT_DIR}/sdk/python; python -m mypy cd ${ROOT_DIR}/sdk/python; python -m isort feast/ tests/ --check-only cd ${ROOT_DIR}/sdk/python; python -m flake8 feast/ tests/ cd ${ROOT_DIR}/sdk/python; python -m black --check feast tests @@ -117,23 +122,50 @@ build-java: build-java-no-tests: ${MVN} --no-transfer-progress -Dmaven.javadoc.skip=true -Dgpg.skip -DskipUTs=true -DskipITs=true -Drevision=${REVISION} clean package -# Go SDK +# Trino plugin +start-trino-locally: + cd ${ROOT_DIR}; docker run --detach --rm -p 8080:8080 --name trino -v ${ROOT_DIR}/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/properties/:/etc/catalog/:ro trinodb/trino:${TRINO_VERSION} + sleep 15 + +test-trino-plugin-locally: + cd ${ROOT_DIR}/sdk/python; FULL_REPO_CONFIGS_MODULE=feast.infra.offline_stores.contrib.trino_offline_store.test_config.manual_tests FEAST_USAGE=False IS_TEST=True python -m pytest --integration --universal tests/ + +kill-trino-locally: + cd ${ROOT_DIR}; docker stop trino + +# Go SDK & embedded + +install-go-proto-dependencies: + go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26.0 + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0 install-go-ci-dependencies: - go get -u github.com/golang/protobuf/protoc-gen-go - go get -u golang.org/x/lint/golint + # ToDo: currently gopy installation doesn't work w/o explicit go get in the next line + # ToDo: there should be a better way to install gopy + go get github.com/go-python/gopy + go install golang.org/x/tools/cmd/goimports + go install github.com/go-python/gopy + +install-protoc-dependencies: + pip install grpcio-tools==1.34.0 + +compile-protos-go: install-go-proto-dependencies install-protoc-dependencies + cd sdk/python && python setup.py build_go_protos -compile-protos-go: - $(foreach dir,types serving core storage,cd ${ROOT_DIR}/protos; protoc -I/usr/local/include -I. --go_out=plugins=grpc,paths=source_relative:../sdk/go/protos feast/$(dir)/*.proto;) +compile-go-lib: install-go-proto-dependencies install-go-ci-dependencies + python -m pip install pybindgen==0.22.0 + cd sdk/python && python setup.py build_go_lib -test-go: - cd ${ROOT_DIR}/sdk/go; go test ./... +# Needs feast package to setup the feature store +test-go: compile-protos-go + pip install -e "sdk/python[ci]" + go test ./... format-go: - cd ${ROOT_DIR}/sdk/go; gofmt -s -w *.go + gofmt -s -w go/ -lint-go: - cd ${ROOT_DIR}/sdk/go; go vet +lint-go: compile-protos-go + go vet ./go/internal/feast ./go/cmd/server # Docker @@ -198,4 +230,4 @@ build-sphinx: compile-protos-python cd $(ROOT_DIR)/sdk/python/docs && $(MAKE) build-api-source build-templates: - python infra/scripts/compile-templates.py \ No newline at end of file + python infra/scripts/compile-templates.py diff --git a/OWNERS b/OWNERS index 199f9d19f23..bc7342c3d61 100644 --- a/OWNERS +++ b/OWNERS @@ -9,6 +9,7 @@ approvers: - felixwang9817 - mavysavydav - MattDelac + - kevjumba reviewers: - woop - tsotnet @@ -18,3 +19,4 @@ reviewers: - felixwang9817 - mavysavydav - MattDelac + - kevjumba diff --git a/README.md b/README.md index 9f15c1a1714..b0cc61c91dc 100644 --- a/README.md +++ b/README.md @@ -147,8 +147,8 @@ The list below contains the functionality that contributors are planning to deve * [x] [Synapse source (community plugin)](https://github.com/Azure/feast-azure) * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) - * [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) - * [x] Kafka source (with [push support into the online store](https://docs.feast.dev/reference/alpha-stream-ingestion)) + * [x] [Spark (community plugin)](https://docs.feast.dev/reference/data-sources/spark) + * [x] Kafka / Kinesis sources (via [push support into the online store](https://docs.feast.dev/reference/data-sources/push) * [ ] HTTP source * **Offline Stores** * [x] [Snowflake](https://docs.feast.dev/reference/offline-stores/snowflake) @@ -158,7 +158,7 @@ The list below contains the functionality that contributors are planning to deve * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) * [x] [Trino (community plugin)](https://github.com/Shopify/feast-trino) - * [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) + * [x] [Spark (community plugin)](https://docs.feast.dev/reference/offline-stores/spark) * [x] [In-memory / Pandas](https://docs.feast.dev/reference/offline-stores/file) * [x] [Custom offline store support](https://docs.feast.dev/how-to-guides/adding-a-new-offline-store) * **Online Stores** @@ -173,12 +173,12 @@ The list below contains the functionality that contributors are planning to deve * [ ] Cassandra * **Streaming** * [x] [Custom streaming ingestion job support](https://docs.feast.dev/how-to-guides/creating-a-custom-provider) - * [x] [Push based streaming data ingestion](reference/alpha-stream-ingestion.md) + * [x] [Push based streaming data ingestion](https://docs.feast.dev/reference/data-sources/push.md) * [ ] Streaming ingestion on AWS * [ ] Streaming ingestion on GCP * **Feature Engineering** * [x] On-demand Transformations (Alpha release. See [RFC](https://docs.google.com/document/d/1lgfIw0Drc65LpaxbUu49RCeJgMew547meSJttnUqz7c/edit#)) - * [ ] Batch transformation (SQL. In progress. See [RFC](https://docs.google.com/document/d/1964OkzuBljifDvkV-0fakp2uaijnVzdwWNGdz7Vz50A/edit)) + * [ ] Batch transformation (In progress. See [RFC](https://docs.google.com/document/d/1964OkzuBljifDvkV-0fakp2uaijnVzdwWNGdz7Vz50A/edit)) * [ ] Streaming transformation * **Deployments** * [x] AWS Lambda (Alpha release. See [RFC](https://docs.google.com/document/d/1eZWKWzfBif66LDN32IajpaG-j82LSHCCOzY6R7Ax7MI/edit)) @@ -204,7 +204,7 @@ The list below contains the functionality that contributors are planning to deve * [x] CLI for browsing feature registry * [x] Model-centric feature tracking (feature services) * [x] Amundsen integration (see [Feast extractor](https://github.com/amundsen-io/amundsen/blob/main/databuilder/databuilder/extractor/feast_extractor.py)) - * [ ] Feast Web UI (in progress) + * [x] Feast Web UI (alpha) * [ ] REST API for browsing feature registry * [ ] Feature versioning diff --git a/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1) (1).svg b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1) (1).svg new file mode 100644 index 00000000000..b707f490461 --- /dev/null +++ b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1) (2).svg b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1) (2).svg new file mode 100644 index 00000000000..b707f490461 --- /dev/null +++ b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1).svg b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1).svg new file mode 100644 index 00000000000..b707f490461 --- /dev/null +++ b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (2).svg b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (2).svg new file mode 100644 index 00000000000..b707f490461 --- /dev/null +++ b/docs/.gitbook/assets/basic-architecture-diagram (3) (3) (3) (3) (3) (3) (1) (1) (1) (2) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (1).svg b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (1).svg new file mode 100644 index 00000000000..fb5e0659e55 --- /dev/null +++ b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (2).svg b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (2).svg new file mode 100644 index 00000000000..fb5e0659e55 --- /dev/null +++ b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (3).svg b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (3).svg new file mode 100644 index 00000000000..fb5e0659e55 --- /dev/null +++ b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1) (3).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1).svg b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1).svg new file mode 100644 index 00000000000..fb5e0659e55 --- /dev/null +++ b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (2).svg b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (2).svg new file mode 100644 index 00000000000..fb5e0659e55 --- /dev/null +++ b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (3).svg b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (3).svg new file mode 100644 index 00000000000..fb5e0659e55 --- /dev/null +++ b/docs/.gitbook/assets/blank-diagram-4 (4) (4) (4) (4) (4) (4) (4) (4) (2) (1) (1) (1) (1) (2) (3).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (1).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (1).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (2).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (2).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (3).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (3).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (3).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (4).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (4).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (4).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (5).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (5).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (5).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (6).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (6).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1) (6).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (2).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (2).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (3).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (3).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (3).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (4).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (4).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (4).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (5).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (5).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (5).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (6).svg b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (6).svg new file mode 100644 index 00000000000..7335c131c44 --- /dev/null +++ b/docs/.gitbook/assets/feast-architecture-diagrams (1) (1) (1) (2) (3) (4) (3) (1) (1) (1) (1) (2) (6).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (1).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (1).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (2).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (2).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (3).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (3).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (3).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (4).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (4).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (4).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (5).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (5).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1) (5).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (1).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (2).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (2).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (2).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (3).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (3).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (3).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (4).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (4).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (4).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (5).svg b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (5).svg new file mode 100644 index 00000000000..7f30963ec78 --- /dev/null +++ b/docs/.gitbook/assets/feast-docs-overview-diagram-2 (5) (1) (2) (5).svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (1).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (1).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (2).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (2).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (3).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (3).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (3).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (4).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (4).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (4).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (5).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (5).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (5).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (6).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (6).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1) (6).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (1).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (2).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (2).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (2).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (3).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (3).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (3).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (4).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (4).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (4).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (5).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (5).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (5).png differ diff --git a/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (6).png b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (6).png new file mode 100644 index 00000000000..28efa1206ad Binary files /dev/null and b/docs/.gitbook/assets/feast-landing-page-blog-post-page-5 (1) (1) (1) (2) (2) (5) (7) (7) (3) (2) (6).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (1).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (1).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (2).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (2).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (3).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (3).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (3).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (4).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (4).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (4).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (5).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (5).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (5).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (6).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (6).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1) (6).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (1).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (4).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (4).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (4).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (5).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (5).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (5).png differ diff --git a/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (6).png b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (6).png new file mode 100644 index 00000000000..e6de77dde9b Binary files /dev/null and b/docs/.gitbook/assets/feast-on-aws-3- (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (6).png differ diff --git a/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1) (1).png b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1) (1).png new file mode 100644 index 00000000000..d3b359a5988 Binary files /dev/null and b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1) (2).png b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1) (2).png new file mode 100644 index 00000000000..d3b359a5988 Binary files /dev/null and b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1).png b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1).png new file mode 100644 index 00000000000..d3b359a5988 Binary files /dev/null and b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (1).png differ diff --git a/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (2).png b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (2).png new file mode 100644 index 00000000000..d3b359a5988 Binary files /dev/null and b/docs/.gitbook/assets/image (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2) (2).png differ diff --git a/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (1).png b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (1).png new file mode 100644 index 00000000000..2442410112f Binary files /dev/null and b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (2).png b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (2).png new file mode 100644 index 00000000000..2442410112f Binary files /dev/null and b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (3).png b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (3).png new file mode 100644 index 00000000000..2442410112f Binary files /dev/null and b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1) (3).png differ diff --git a/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1).png b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1).png new file mode 100644 index 00000000000..2442410112f Binary files /dev/null and b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (1).png differ diff --git a/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (2).png b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (2).png new file mode 100644 index 00000000000..2442410112f Binary files /dev/null and b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (2).png differ diff --git a/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (3).png b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (3).png new file mode 100644 index 00000000000..2442410112f Binary files /dev/null and b/docs/.gitbook/assets/image (3) (2) (2) (4) (4) (4) (4) (4) (4) (3) (1) (2) (3).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (1).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (1).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (2).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (2).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (3).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (3).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (3).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (4).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (4).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (4).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (5).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (5).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (5).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (6).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (6).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1) (6).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (1).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (2).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (2).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (2).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (3).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (3).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (3).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (4).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (4).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (4).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (5).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (5).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (5).png differ diff --git a/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (6).png b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (6).png new file mode 100644 index 00000000000..cd77f27cc45 Binary files /dev/null and b/docs/.gitbook/assets/image (4) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (2) (3) (3) (3) (3) (2) (6).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (1).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (1).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (2).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (2).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (3).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (3).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (3).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (4).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (4).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (4).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (5).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (5).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (5).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (6).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (6).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (6).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (7).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (7).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1) (7).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (1).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (2).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (2).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (2).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (3).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (3).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (3).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (4).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (4).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (4).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (5).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (5).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (5).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (6).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (6).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (6).png differ diff --git a/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (7).png b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (7).png new file mode 100644 index 00000000000..49670e20054 Binary files /dev/null and b/docs/.gitbook/assets/image (6) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2) (7).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (1).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (1).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (2).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (2).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (3).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (3).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (3).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (4).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (4).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (4).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (5).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (5).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (5).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (6).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (6).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (6).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (7).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (7).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1) (7).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (1).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (2).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (2).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (2).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (3).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (3).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (3).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (4).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (4).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (4).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (5).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (5).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (5).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (6).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (6).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (6).png differ diff --git a/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (7).png b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (7).png new file mode 100644 index 00000000000..331a090d719 Binary files /dev/null and b/docs/.gitbook/assets/point_in_time_join (1) (2) (2) (3) (3) (3) (3) (2) (7).png differ diff --git a/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (1).jpg b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (1).jpg new file mode 100644 index 00000000000..b92ec6fed72 Binary files /dev/null and b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (1).jpg differ diff --git a/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2).jpg b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2).jpg new file mode 100644 index 00000000000..b92ec6fed72 Binary files /dev/null and b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (2).jpg differ diff --git a/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (3).jpg b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (3).jpg new file mode 100644 index 00000000000..b92ec6fed72 Binary files /dev/null and b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1) (3).jpg differ diff --git a/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1).jpg b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1).jpg new file mode 100644 index 00000000000..b92ec6fed72 Binary files /dev/null and b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (1).jpg differ diff --git a/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2).jpg b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2).jpg new file mode 100644 index 00000000000..b92ec6fed72 Binary files /dev/null and b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (2).jpg differ diff --git a/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (3).jpg b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (3).jpg new file mode 100644 index 00000000000..b92ec6fed72 Binary files /dev/null and b/docs/.gitbook/assets/rsz_untitled23 (2) (2) (2) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (3) (2) (3).jpg differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (1) (1).png b/docs/.gitbook/assets/statistics-sources (2) (1) (1).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (1) (1).png differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (1) (2).png b/docs/.gitbook/assets/statistics-sources (2) (1) (2).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (1) (2).png differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (1) (3).png b/docs/.gitbook/assets/statistics-sources (2) (1) (3).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (1) (3).png differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (1) (4).png b/docs/.gitbook/assets/statistics-sources (2) (1) (4).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (1) (4).png differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (1).png b/docs/.gitbook/assets/statistics-sources (2) (1).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (1).png differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (2).png b/docs/.gitbook/assets/statistics-sources (2) (2).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (2).png differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (3).png b/docs/.gitbook/assets/statistics-sources (2) (3).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (3).png differ diff --git a/docs/.gitbook/assets/statistics-sources (2) (4).png b/docs/.gitbook/assets/statistics-sources (2) (4).png new file mode 100644 index 00000000000..02be233968d Binary files /dev/null and b/docs/.gitbook/assets/statistics-sources (2) (4).png differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (1).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (1).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (1).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (2).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (2).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (2).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (3).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (3).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (3).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (4).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (4).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (4).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (5).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (5).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (5).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (6).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (6).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (6).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (7).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (7).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1) (7).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (1).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (2).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (2).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (2).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (3).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (3).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (3).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (4).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (4).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (4).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (5).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (5).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (5).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (6).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (6).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (6).jpg differ diff --git a/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (7).jpg b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (7).jpg new file mode 100644 index 00000000000..93d010406bd Binary files /dev/null and b/docs/.gitbook/assets/untitled-25-1- (2) (2) (2) (3) (3) (3) (3) (3) (3) (1) (2) (7).jpg differ diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index deec3e9eed0..e73996665e5 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -60,11 +60,14 @@ * [Snowflake](reference/data-sources/snowflake.md) * [BigQuery](reference/data-sources/bigquery.md) * [Redshift](reference/data-sources/redshift.md) + * [Spark](reference/data-sources/spark.md) + * [Push](reference/data-sources/push.md) * [Offline stores](reference/offline-stores/README.md) * [File](reference/offline-stores/file.md) * [Snowflake](reference/offline-stores/snowflake.md) * [BigQuery](reference/offline-stores/bigquery.md) * [Redshift](reference/offline-stores/redshift.md) + * [Spark](reference/offline-stores/spark.md) * [Online stores](reference/online-stores/README.md) * [SQLite](reference/online-stores/sqlite.md) * [Redis](reference/online-stores/redis.md) @@ -79,6 +82,7 @@ * [.feastignore](reference/feature-repository/feast-ignore.md) * [Feature servers](reference/feature-servers/README.md) * [Local feature server](reference/feature-servers/local-feature-server.md) + * [Go-based feature retrieval](reference/feature-servers/go-feature-retrieval.md) * [\[Alpha\] Data quality monitoring](reference/dqm.md) * [\[Alpha\] On demand feature view](reference/alpha-on-demand-feature-view.md) * [\[Alpha\] Stream ingestion](reference/alpha-stream-ingestion.md) diff --git a/docs/community.md b/docs/community.md index 53e00eb4ebf..c0ead3dda1a 100644 --- a/docs/community.md +++ b/docs/community.md @@ -10,6 +10,8 @@ * [Mailing list](https://groups.google.com/d/forum/feast-dev): We have both a user and developer mailing list. * Feast users should join [feast-discuss@googlegroups.com](mailto:feast-discuss@googlegroups.com) group by clicking [here](https://groups.google.com/g/feast-discuss). * Feast developers should join [feast-dev@googlegroups.com](mailto:feast-dev@googlegroups.com) group by clicking [here](https://groups.google.com/d/forum/feast-dev). + * People interested in the Feast community newsletter should join feast-announce by clicking [here](https://groups.google.com/d/forum/feast-announce). +* [Community Calendar](https://calendar.google.com/calendar/u/0?cid=ZTFsZHVhdGM3MDU3YTJucTBwMzNqNW5rajBAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ): Includes community calls and design meetings. * [Google Folder](https://drive.google.com/drive/u/0/folders/1jgMHOPDT2DvBlJeO9LCM79DP4lm4eOrR): This folder is used as a central repository for all Feast resources. For example: * Design proposals in the form of Request for Comments (RFC). * User surveys and meeting minutes. @@ -31,12 +33,11 @@ We have a user and contributor community call every two weeks (Asia & US friendl Please join the above Feast user groups in order to see calendar invites to the community calls {% endhint %} -### Frequency (alternating times every 2 weeks) +### Frequency (every 2 weeks) -* Tuesday 18:00 pm to 18:30 pm (US, Asia) -* Tuesday 10:00 am to 10:30 am (US, Europe) +* Tuesday 10:00 am to 10:30 am PST ### Links * Zoom: [https://zoom.us/j/6325193230](https://zoom.us/j/6325193230) -* Meeting notes: [https://bit.ly/feast-notes](https://bit.ly/feast-notes) +* Meeting notes (incl recordings): [https://bit.ly/feast-notes](https://bit.ly/feast-notes) diff --git a/docs/getting-started/architecture-and-components/README.md b/docs/getting-started/architecture-and-components/README.md index c5a9aea9a16..c3286b8315a 100644 --- a/docs/getting-started/architecture-and-components/README.md +++ b/docs/getting-started/architecture-and-components/README.md @@ -4,7 +4,7 @@ {% page-ref page="feature-repository.md" %} -{% page-ref page="untitled.md" %} +{% page-ref page="registry.md" %} {% page-ref page="offline-store.md" %} diff --git a/docs/getting-started/architecture-and-components/online-store.md b/docs/getting-started/architecture-and-components/online-store.md index c74f47e69f9..4f2e44c92ce 100644 --- a/docs/getting-started/architecture-and-components/online-store.md +++ b/docs/getting-started/architecture-and-components/online-store.md @@ -12,3 +12,4 @@ Once the above data source is materialized into Feast \(using `feast materialize ![](../../.gitbook/assets/image%20%285%29.png) +Features can also be written to the online store via [push sources](https://docs.feast.dev/reference/data-sources/push) \ No newline at end of file diff --git a/docs/getting-started/concepts/entity.md b/docs/getting-started/concepts/entity.md index a4db98cfd1a..bc8aa2ac995 100644 --- a/docs/getting-started/concepts/entity.md +++ b/docs/getting-started/concepts/entity.md @@ -6,7 +6,7 @@ An entity is a collection of semantically related features. Users define entitie driver = Entity(name='driver', value_type=ValueType.STRING, join_key='driver_id') ``` -Entities are typically defined as part of feature views. Entities are used to identify the primary key on which feature values should be stored and retrieved. These keys are used during the lookup of feature values from the online store and the join process in point-in-time joins. It is possible to define composite entities \(more than one entity object\) in a feature view. It is also possible for feature views to have zero entities. See [feature view](feature-view.md) for more details. +Entities are typically defined as part of feature views. Entity name is used to reference the entity from a feature view definition and join key is used to identify the physical primary key on which feature values should be stored and retrieved. These keys are used during the lookup of feature values from the online store and the join process in point-in-time joins. It is possible to define composite entities \(more than one entity object\) in a feature view. It is also possible for feature views to have zero entities. See [feature view](feature-view.md) for more details. Entities should be reused across feature views. diff --git a/docs/getting-started/concepts/feature-retrieval.md b/docs/getting-started/concepts/feature-retrieval.md index dfbbd99073b..bece0f55271 100644 --- a/docs/getting-started/concepts/feature-retrieval.md +++ b/docs/getting-started/concepts/feature-retrieval.md @@ -20,7 +20,10 @@ online_features = fs.get_online_features( 'driver_locations:lon', 'drivers_activity:trips_today' ], - entity_rows=[{'driver': 'driver_1001'}] + entity_rows=[ + # {join_key: entity_value} + {'driver': 'driver_1001'} + ] ) ``` diff --git a/docs/getting-started/concepts/feature-view.md b/docs/getting-started/concepts/feature-view.md index 0bb4f96a317..80fd803d1f2 100644 --- a/docs/getting-started/concepts/feature-view.md +++ b/docs/getting-started/concepts/feature-view.md @@ -7,15 +7,18 @@ A feature view is an object that represents a logical group of time-series featu {% tabs %} {% tab title="driver_trips_feature_view.py" %} ```python +from feast import BigQuerySource, FeatureView, Field +from feast.types import Float32, Int64 + driver_stats_fv = FeatureView( name="driver_activity", entities=["driver"], - features=[ - Feature(name="trips_today", dtype=ValueType.INT64), - Feature(name="rating", dtype=ValueType.FLOAT), + schema=[ + Field(name="trips_today", dtype=Int64), + Field(name="rating", dtype=Float32), ], - batch_source=BigQuerySource( - table_ref="feast-oss.demo_data.driver_activity" + source=BigQuerySource( + table="feast-oss.demo_data.driver_activity" ) ) ``` @@ -25,7 +28,7 @@ driver_stats_fv = FeatureView( Feature views are used during * The generation of training datasets by querying the data source of feature views in order to find historical feature values. A single training dataset may consist of features from multiple feature views. -* Loading of feature values into an online store. Feature views determine the storage schema in the online store. Feature values can be loaded from batch sources or from [stream sources](../../reference/alpha-stream-ingestion.md). +* Loading of feature values into an online store. Feature views determine the storage schema in the online store. Feature values can be loaded from batch sources or from [stream sources](../../reference/data-sources/push.md). * Retrieval of features from the online store. Feature views provide the schema definition to Feast in order to look up features from the online store. {% hint style="info" %} @@ -34,19 +37,22 @@ Feast does not generate feature values. It acts as the ingestion and serving sys ## Feature views without entities -If a feature view contains features that are not related to a specific entity, the feature view can be defined without entities. +If a feature view contains features that are not related to a specific entity, the feature view can be defined without entities (only event timestamps are needed for this feature view). {% tabs %} {% tab title="global_stats.py" %} ```python +from feast import BigQuerySource, FeatureView, Field +from feast.types import Int64 + global_stats_fv = FeatureView( name="global_stats", entities=[], - features=[ - Feature(name="total_trips_today_by_all_drivers", dtype=ValueType.INT64), + schema=[ + Field(name="total_trips_today_by_all_drivers", dtype=Int64), ], - batch_source=BigQuerySource( - table_ref="feast-oss.demo_data.global_stats" + source=BigQuerySource( + table="feast-oss.demo_data.global_stats" ) ) ``` @@ -70,16 +76,19 @@ It is suggested that you dynamically specify the new FeatureView name using `.wi {% tabs %} {% tab title="location_stats_feature_view.py" %} ```python +from feast import BigQuerySource, Entity, FeatureView, Field, ValueType +from feast.types import Int32 + location = Entity(name="location", join_key="location_id", value_type=ValueType.INT64) location_stats_fv= FeatureView( name="location_stats", entities=["location"], - features=[ - Feature(name="temperature", dtype=ValueType.INT32) + schema=[ + Field(name="temperature", dtype=Int32) ], - batch_source=BigQuerySource( - table_ref="feast-oss.demo_data.location_stats" + source=BigQuerySource( + table="feast-oss.demo_data.location_stats" ), ) ``` @@ -115,9 +124,12 @@ A feature is an individual measurable property. It is typically a property obser Features are defined as part of feature views. Since Feast does not transform data, a feature is essentially a schema that only contains a name and a type: ```python -trips_today = Feature( +from feast import Field +from feast.types import Float32 + +trips_today = Field( name="trips_today", - dtype=ValueType.FLOAT + dtype=Float32 ) ``` @@ -130,25 +142,28 @@ Feature names must be unique within a [feature view](feature-view.md#feature-vie On demand feature views allows users to use existing features and request time data (features only available at request time) to transform and create new features. Users define python transformation logic which is executed in both historical retrieval and online retrieval paths: ```python -# Define a request data source which encodes features / information only +from feast import Field, RequestSource +from feast.types import Float64 + +# Define a request data source which encodes features / information only # available at request time (e.g. part of the user initiated HTTP request) -input_request = RequestDataSource( +input_request = RequestSource( name="vals_to_add", - schema={ - "val_to_add": ValueType.INT64, - "val_to_add_2": ValueType.INT64 - } + schema=[ + Field(name="val_to_add", dtype=PrimitiveFeastType.INT64), + Field(name="val_to_add_2": dtype=PrimitiveFeastType.INT64), + ] ) # Use the input data and feature view features to create new features @on_demand_feature_view( - inputs={ + sources={ 'driver_hourly_stats': driver_hourly_stats_view, 'vals_to_add': input_request }, - features=[ - Feature(name='conv_rate_plus_val1', dtype=ValueType.DOUBLE), - Feature(name='conv_rate_plus_val2', dtype=ValueType.DOUBLE) + schema=[ + Field(name='conv_rate_plus_val1', dtype=Float64), + Field(name='conv_rate_plus_val2', dtype=Float64) ] ) def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: diff --git a/docs/getting-started/concepts/point-in-time-joins.md b/docs/getting-started/concepts/point-in-time-joins.md index 3e876ba01f0..d2961e2f748 100644 --- a/docs/getting-started/concepts/point-in-time-joins.md +++ b/docs/getting-started/concepts/point-in-time-joins.md @@ -7,15 +7,19 @@ Feature values in Feast are modeled as time-series records. Below is an example The above table can be registered with Feast through the following feature view: ```python +from feast import FeatureView, Field, FileSource +from feast.types import Float32, Int64 +from datetime import timedelta + driver_stats_fv = FeatureView( name="driver_hourly_stats", entities=["driver"], - features=[ - Feature(name="trips_today", dtype=ValueType.INT64), - Feature(name="earnings_today", dtype=ValueType.FLOAT), + schema=[ + Field(name="trips_today", dtype=Int64), + Field(name="earnings_today", dtype=Float32), ], ttl=timedelta(hours=2), - batch_source=FileSource( + source=FileSource( path="driver_hourly_stats.parquet" ) ) diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index c067513d313..b188e0189d6 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -80,37 +80,40 @@ online_store: ```python # This is an example feature definition file -from google.protobuf.duration_pb2 import Duration +from datetime import timedelta -from feast import Entity, Feature, FeatureView, FileSource, ValueType +from feast import Entity, FeatureView, Field, FileSource, ValueType +from feast.types import Float32, Int64 # Read data from parquet files. Parquet is convenient for local development mode. For # production, you can use your favorite DWH, such as BigQuery. See Feast documentation # for more info. driver_hourly_stats = FileSource( path="/content/feature_repo/data/driver_stats.parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) # Define an entity for the driver. You can think of entity as a primary key used to # fetch features. -driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",) +# Entity has a name used for later reference (in a feature view, eg) +# and join_key to identify physical field name used in storages +driver = Entity(name="driver", value_type=ValueType.INT64, join_key="driver_id", description="driver id",) # Our parquet files contain sample data that includes a driver_id column, timestamps and # three feature column. Here we define a Feature View that will allow us to serve this # data to our model online. driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", - entities=["driver_id"], - ttl=Duration(seconds=86400 * 1), - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + entities=["driver"], # reference entity by name + ttl=timedelta(seconds=86400 * 1), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], online=True, - batch_source=driver_hourly_stats, + source=driver_hourly_stats, tags={}, ) ``` @@ -147,37 +150,40 @@ feast apply ```python # This is an example feature definition file -from google.protobuf.duration_pb2 import Duration +from datetime import timedelta -from feast import Entity, Feature, FeatureView, FileSource, ValueType +from feast import Entity, FeatureView, Field, FileSource, ValueType +from feast.types import Float32, Int64 # Read data from parquet files. Parquet is convenient for local development mode. For # production, you can use your favorite DWH, such as BigQuery. See Feast documentation # for more info. driver_hourly_stats = FileSource( path="/content/feature_repo/data/driver_stats.parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) # Define an entity for the driver. You can think of entity as a primary key used to # fetch features. -driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",) +# Entity has a name used for later reference (in a feature view, eg) +# and join_key to identify physical field name used in storages +driver = Entity(name="driver", value_type=ValueType.INT64, join_key="driver_id", description="driver id",) # Our parquet files contain sample data that includes a driver_id column, timestamps and # three feature column. Here we define a Feature View that will allow us to serve this # data to our model online. driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", - entities=["driver_id"], - ttl=Duration(seconds=86400 * 1), - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + entities=["driver"], # reference entity by name + ttl=timedelta(seconds=86400 * 1), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], online=True, - batch_source=driver_hourly_stats, + source=driver_hourly_stats, tags={}, ) ``` @@ -213,8 +219,13 @@ from feast import FeatureStore # The entity dataframe is the dataframe we want to enrich with feature values entity_df = pd.DataFrame.from_dict( { + # entity's join key -> entity values "driver_id": [1001, 1002, 1003], + + # label name -> label values "label_driver_reported_satisfaction": [1, 5, 3], + + # "event_timestamp" (reserved key) -> timestamps "event_timestamp": [ datetime.now() - timedelta(minutes=11), datetime.now() - timedelta(minutes=36), @@ -320,6 +331,7 @@ feature_vector = store.get_online_features( "driver_hourly_stats:avg_daily_trips", ], entity_rows=[ + # {join_key: entity_value} {"driver_id": 1004}, {"driver_id": 1005}, ], diff --git a/docs/getting-started/third-party-integrations.md b/docs/getting-started/third-party-integrations.md index 0bf8733b3f5..a731fd85dc3 100644 --- a/docs/getting-started/third-party-integrations.md +++ b/docs/getting-started/third-party-integrations.md @@ -20,8 +20,8 @@ Don't see your offline store or online store of choice here? Check out our guide * [x] [Synapse source (community plugin)](https://github.com/Azure/feast-azure) * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) -* [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) -* [x] Kafka source (with [push support into the online store](https://docs.feast.dev/reference/alpha-stream-ingestion)) +* [x] [Spark (community plugin)](https://docs.feast.dev/reference/data-sources/spark) +* [x] Kafka / Kinesis sources (via [push support into the online store](https://docs.feast.dev/reference/data-sources/push) * [ ] HTTP source ### Offline Stores @@ -33,7 +33,7 @@ Don't see your offline store or online store of choice here? Check out our guide * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) * [x] [Trino (community plugin)](https://github.com/Shopify/feast-trino) -* [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) +* [x] [Spark (community plugin)](https://docs.feast.dev/reference/offline-stores/spark) * [x] [In-memory / Pandas](https://docs.feast.dev/reference/offline-stores/file) * [x] [Custom offline store support](https://docs.feast.dev/how-to-guides/adding-a-new-offline-store) diff --git a/docs/how-to-guides/adding-a-new-offline-store.md b/docs/how-to-guides/adding-a-new-offline-store.md index c77e88c7c8e..8eeac7bcf44 100644 --- a/docs/how-to-guides/adding-a-new-offline-store.md +++ b/docs/how-to-guides/adding-a-new-offline-store.md @@ -28,7 +28,8 @@ The OfflineStore class contains a couple of methods to read features from the of There are two methods that deal with reading data from the offline stores`get_historical_features`and `pull_latest_from_table_or_query`. * `pull_latest_from_table_or_query` is invoked when running materialization (using the `feast materialize` or `feast materialize-incremental` commands, or the corresponding `FeatureStore.materialize()` method. This method pull data from the offline store, and the `FeatureStore` class takes care of writing this data into the online store. -* `get_historical_features `is invoked when reading values from the offline store using the `FeatureStore.get_historica_features()` method. Typically, this method is used to retrieve features when training ML models. +* `get_historical_features` is invoked when reading values from the offline store using the `FeatureStore.get_historical_features()` method. Typically, this method is used to retrieve features when training ML models. +* `pull_all_from_table_or_query` is a method that pulls all the data from an offline store from a specified start date to a specified end date. {% code title="feast_custom_offline_store/file.py" %} ```python @@ -53,7 +54,7 @@ There are two methods that deal with reading data from the offline stores`get_hi data_source: DataSource, join_key_columns: List[str], feature_name_columns: List[str], - event_timestamp_column: str, + timestamp_field: str, created_timestamp_column: Optional[str], start_date: datetime, end_date: datetime) -> RetrievalJob: @@ -62,7 +63,7 @@ There are two methods that deal with reading data from the offline stores`get_hi data_source, join_key_columns, feature_name_columns, - event_timestamp_column, + timestamp_field=timestamp_field, created_timestamp_column, start_date, end_date) @@ -164,14 +165,14 @@ class CustomFileDataSource(FileSource): """Custom data source class for local files""" def __init__( self, - event_timestamp_column: Optional[str] = "", + timestamp_field: Optional[str] = "", path: Optional[str] = None, field_mapping: Optional[Dict[str, str]] = None, created_timestamp_column: Optional[str] = "", date_partition_column: Optional[str] = "", ): super(CustomFileDataSource, self).__init__( - event_timestamp_column, + timestamp_field=timestamp_field, created_timestamp_column, field_mapping, date_partition_column, @@ -188,7 +189,7 @@ class CustomFileDataSource(FileSource): return CustomFileDataSource( field_mapping=dict(data_source.field_mapping), path=path, - event_timestamp_column=data_source.event_timestamp_column, + timestamp_field=data_source.timestamp_field, created_timestamp_column=data_source.created_timestamp_column, date_partition_column=data_source.date_partition_column, ) @@ -202,7 +203,7 @@ class CustomFileDataSource(FileSource): ), ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column data_source_proto.date_partition_column = self.date_partition_column @@ -223,7 +224,7 @@ To use our custom file offline store, we can use the following `feature_store.ya project: test_custom registry: data/registry.db provider: local -offline_store: +offline_store: type: feast_custom_offline_store.file.CustomFileOfflineStore ``` {% endcode %} @@ -245,13 +246,13 @@ Finally, the custom data source class can be use in the feature repo to define a ```python pdriver_hourly_stats = CustomFileDataSource( path="feature_repo/data/driver_stats.parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) driver_hourly_stats_view = FeatureView( - batch_source=driver_hourly_stats, + source=driver_hourly_stats, ... ) ``` diff --git a/docs/how-to-guides/adding-or-reusing-tests.md b/docs/how-to-guides/adding-or-reusing-tests.md index 5a29342d6e1..86c116442f2 100644 --- a/docs/how-to-guides/adding-or-reusing-tests.md +++ b/docs/how-to-guides/adding-or-reusing-tests.md @@ -161,6 +161,13 @@ The key fixtures are the `environment` and `universal_data_sources` fixtures, wh * In `repo_configuration.py` add a new`IntegrationTestRepoConfig` or two (depending on how many online stores you want to test). * Run the full test suite with `make test-python-integration.` +### Including a new offline / online store in the main Feast repo from external plugins with community maintainers. + +* This folder is for plugins that are officially maintained with community owners. Place the APIs in feast/infra/offline_stores/contrib/. +* Extend `data_source_creator.py` for your offline store and implement the required APIs. +* In `contrib_repo_configuration.py` add a new `IntegrationTestRepoConfig` (depending on how many online stores you want to test). +* Run the test suite on the contrib test suite with `make test-python-contrib-universal`. + ### To include a new online store * In `repo_configuration.py` add a new config that maps to a serialized version of configuration you need in `feature_store.yaml` to setup the online store. @@ -202,4 +209,3 @@ Starting 6006 * You should be able to run the integration tests and have the redis cluster tests pass. * If you would like to run your own redis cluster, you can run the above commands with your own specified ports and connect to the newly configured cluster. * To stop the cluster, run `./create-cluster stop` and then `./create-cluster clean`. - diff --git a/docs/how-to-guides/feast-snowflake-gcp-aws/read-features-from-the-online-store.md b/docs/how-to-guides/feast-snowflake-gcp-aws/read-features-from-the-online-store.md index 16568fd62a5..7b0a46239b2 100644 --- a/docs/how-to-guides/feast-snowflake-gcp-aws/read-features-from-the-online-store.md +++ b/docs/how-to-guides/feast-snowflake-gcp-aws/read-features-from-the-online-store.md @@ -34,6 +34,7 @@ fs = FeatureStore(repo_path="path/to/feature/repo") online_features = fs.get_online_features( features=features, entity_rows=[ + # {join_key: entity_value, ...} {"driver_id": 1001}, {"driver_id": 1002}] ).to_dict() diff --git a/docs/how-to-guides/running-feast-in-production.md b/docs/how-to-guides/running-feast-in-production.md index 4161f5e220d..8518bb28d07 100644 --- a/docs/how-to-guides/running-feast-in-production.md +++ b/docs/how-to-guides/running-feast-in-production.md @@ -287,7 +287,7 @@ store = FeatureStore(...) def feast_writer(spark_df): pandas_df = spark_df.to_pandas() - store.write_to_online_store("driver_hourly_stats", pandas_df) + store.push("driver_hourly_stats", pandas_df) streamingDF.writeStream.foreachBatch(feast_writer).start() ``` diff --git a/docs/project/contributing.md b/docs/project/contributing.md index ac1ab480a0a..933237f204f 100644 --- a/docs/project/contributing.md +++ b/docs/project/contributing.md @@ -4,11 +4,8 @@ We use [RFCs](https://en.wikipedia.org/wiki/Request_for_Comments) and [GitHub is We follow a process of [lazy consensus](http://community.apache.org/committers/lazyConsensus.html). If you believe you know what the project needs then just start development. If you are unsure about which direction to take with development then please communicate your ideas through a GitHub issue or through our [Slack Channel](../community.md) before starting development. -Please [submit a PR ](https://github.com/feast-dev/feast/pulls)to the master branch of the Feast repository once you are ready to submit your contribution. Code submission to Feast \(including submission from project maintainers\) require review and approval from maintainers or code owners. +Please [submit a PR](https://github.com/feast-dev/feast/pulls) to the master branch of the Feast repository once you are ready to submit your contribution. Code submission to Feast \(including submission from project maintainers\) require review and approval from maintainers or code owners. PRs that are submitted by the general public need to be identified as `ok-to-test`. Once enabled, [Prow](https://github.com/kubernetes/test-infra/tree/master/prow) will run a range of tests to verify the submission, after which community members will help to review the pull request. -{% hint style="success" %} -Please sign the [Google CLA](https://cla.developers.google.com/) in order to have your code merged into the Feast repository. -{% endhint %} - +See also [Community](../community.md) for other ways to get involved with the community (e.g. joining community calls) \ No newline at end of file diff --git a/docs/reference/alpha-on-demand-feature-view.md b/docs/reference/alpha-on-demand-feature-view.md index 18416d74e23..6be55fb735e 100644 --- a/docs/reference/alpha-on-demand-feature-view.md +++ b/docs/reference/alpha-on-demand-feature-view.md @@ -25,28 +25,32 @@ See [https://github.com/feast-dev/on-demand-feature-views-demo](https://github.c ### **Registering transformations** -We register `RequestDataSource` inputs and the transform in `on_demand_feature_view`: +We register `RequestSource` inputs and the transform in `on_demand_feature_view`: ```python +from feast import Field, RequestSource +from feast.types import Float64, Int64 +import pandas as pd + # Define a request data source which encodes features / information only # available at request time (e.g. part of the user initiated HTTP request) -input_request = RequestDataSource( +input_request = RequestSource( name="vals_to_add", - schema={ - "val_to_add": ValueType.INT64, - "val_to_add_2": ValueType.INT64 - } + schema=[ + Field(name='val_to_add', dtype=Int64), + Field(name='val_to_add_2', dtype=Int64) + ] ) # Use the input data and feature view features to create new features @on_demand_feature_view( - inputs={ + sources={ 'driver_hourly_stats': driver_hourly_stats_view, 'vals_to_add': input_request }, - features=[ - Feature(name='conv_rate_plus_val1', dtype=ValueType.DOUBLE), - Feature(name='conv_rate_plus_val2', dtype=ValueType.DOUBLE) + schema=[ + Field(name='conv_rate_plus_val1', dtype=Float64), + Field(name='conv_rate_plus_val2', dtype=Float64) ] ) def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: diff --git a/docs/reference/alpha-stream-ingestion.md b/docs/reference/alpha-stream-ingestion.md deleted file mode 100644 index 3d2498a8c38..00000000000 --- a/docs/reference/alpha-stream-ingestion.md +++ /dev/null @@ -1,45 +0,0 @@ -# \[Alpha] Stream ingestion - -**Warning**: This is an _experimental_ feature. It's intended for early testing and feedback, and could change without warnings in future releases. - -{% hint style="info" %} -To enable this feature, run **`feast alpha enable direct_ingest_to_online_store`** -{% endhint %} - -## Overview - -Streaming data sources are important sources of feature values. A typical setup with streaming data looks like: - -1. Raw events come in (stream 1) -2. Streaming transformations applied (e.g. `last_N_purchased_categories`) (stream 2) -3. Write stream 2 values to an offline store as a historical log for training -4. Write stream 2 values to an online store for low latency feature serving -5. Periodically materialize feature values from the offline store into the online store for improved correctness - -Feast now allows users to push features previously registered in a feature view to the online store. This most commonly would be done from a stream processing job (e.g. a Beam or Spark Streaming job). Future versions of Feast will allow writing features directly to the offline store as well. - -## Example - -See [https://github.com/feast-dev/feast-demo](https://github.com/feast-dev/on-demand-feature-views-demo) for an example on how to ingest stream data into Feast. - -We register a feature view as normal, and during stream processing (e.g. Kafka consumers), now we push a dataframe matching the feature view schema: - -```python -event_df = pd.DataFrame.from_dict( - { - "driver_id": [1001], - "event_timestamp": [ - datetime(2021, 5, 13, 10, 59, 42), - ], - "created": [ - datetime(2021, 5, 13, 10, 59, 42), - ], - "conv_rate": [1.0], - "acc_rate": [1.0], - "avg_daily_trips": [1000], - } -) -store.write_to_online_store("driver_hourly_stats", event_df) -``` - -Feast will coordinate between pushed stream data and regular materialization jobs to ensure only the latest feature values are written to the online store. This ensures correctness in served features for model inference. diff --git a/docs/reference/data-sources/README.md b/docs/reference/data-sources/README.md index cba652a91ad..43adf0d5936 100644 --- a/docs/reference/data-sources/README.md +++ b/docs/reference/data-sources/README.md @@ -2,12 +2,26 @@ Please see [Data Source](../../getting-started/concepts/feature-view.md#data-source) for an explanation of data sources. -{% page-ref page="file.md" %} +{% content-ref url="file.md" %} +[file.md](file.md) +{% endcontent-ref %} -{% page-ref page="snowflake.md" %} +{% content-ref url="snowflake.md" %} +[snowflake.md](snowflake.md) +{% endcontent-ref %} -{% page-ref page="bigquery.md" %} +{% content-ref url="bigquery.md" %} +[bigquery.md](bigquery.md) +{% endcontent-ref %} -{% page-ref page="redshift.md" %} +{% content-ref url="redshift.md" %} +[redshift.md](redshift.md) +{% endcontent-ref %} -{% page-ref page="spark.md" %} +{% content-ref url="spark.md" %} +[spark.md](spark.md) +{% endcontent-ref %} + +{% content-ref url="push.md" %} +[push.md](push.md) +{% endcontent-ref %} diff --git a/docs/reference/data-sources/file.md b/docs/reference/data-sources/file.md index 80e262aa9f8..12e6529840d 100644 --- a/docs/reference/data-sources/file.md +++ b/docs/reference/data-sources/file.md @@ -16,7 +16,7 @@ from feast.data_format import ParquetFormat parquet_file_source = FileSource( file_format=ParquetFormat(), - file_url="file:///feast/customer.parquet", + path="file:///feast/customer.parquet", ) ``` diff --git a/docs/reference/data-sources/push.md b/docs/reference/data-sources/push.md new file mode 100644 index 00000000000..9f377d20998 --- /dev/null +++ b/docs/reference/data-sources/push.md @@ -0,0 +1,58 @@ +# Push source + +## Description + +Push sources allow feature values to be pushed to the online store in real time. This allows fresh feature values to be made available to applications. Push sources supercede the +[FeatureStore.write_to_online_store](https://rtd.feast.dev/en/latest/index.html#feast.feature_store.FeatureStore.write_to_online_store). + +Push sources can be used by multiple feature views. When data is pushed to a push source, Feast propagates the feature values to all the consuming feature views. + +Push sources must have a batch source specified, since that's the source used when retrieving historical features. +When using a PushSource as a stream source in the definition of a feature view, a batch source doesn't need to be specified in the definition explicitly. + +## Stream sources +Streaming data sources are important sources of feature values. A typical setup with streaming data looks like: + +1. Raw events come in (stream 1) +2. Streaming transformations applied (e.g. generating features like `last_N_purchased_categories`) (stream 2) +3. Write stream 2 values to an offline store as a historical log for training +4. Write stream 2 values to an online store for low latency feature serving +5. Periodically materialize feature values from the offline store into the online store for improved correctness + +Feast now allows users to push features previously registered in a feature view to the online store for fresher features. + +## Example +### Defining a push source +Note that the push schema needs to also include the entity + +```python +from feast import PushSource, ValueType, BigQuerySource, FeatureView, Feature, Field +from feast.types import Int64 + +push_source = PushSource( + name="push_source", + schema=[ + Field(name="user_id", dtype=Int64), + Field(name="life_time_value", dtype=Int64) + ], + batch_source=BigQuerySource(table="test.test"), +) + +fv = FeatureView( + name="feature view", + entities=["user_id"], + schema=[Field(name="life_time_value", dtype=Int64)], + stream_source=push_source, +) +``` + +### Pushing data +```python +from feast import FeatureStore +import pandas as pd + +fs = FeatureStore(...) +feature_data_frame = pd.DataFrame() +fs.push("push_source", feature_data_frame) +``` + diff --git a/docs/reference/data-sources/spark.md b/docs/reference/data-sources/spark.md index 25b69c7355e..2c1d1ec879d 100644 --- a/docs/reference/data-sources/spark.md +++ b/docs/reference/data-sources/spark.md @@ -13,7 +13,9 @@ The spark data source API allows for the retrieval of historical feature values Using a table reference from SparkSession(for example, either in memory or a Hive Metastore) ```python -from feast import SparkSource +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SparkSource, +) my_spark_source = SparkSource( table="FEATURE_TABLE", @@ -23,7 +25,9 @@ my_spark_source = SparkSource( Using a query ```python -from feast import SparkSource +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SparkSource, +) my_spark_source = SparkSource( query="SELECT timestamp as ts, created, f1, f2 " @@ -34,12 +38,14 @@ my_spark_source = SparkSource( Using a file reference ```python -from feast import SparkSource +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SparkSource, +) my_spark_source = SparkSource( path=f"{CURRENT_DIR}/data/driver_hourly_stats", file_format="parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) ``` diff --git a/docs/reference/feature-repository.md b/docs/reference/feature-repository.md index f6f880d56f6..a9790349899 100644 --- a/docs/reference/feature-repository.md +++ b/docs/reference/feature-repository.md @@ -89,11 +89,12 @@ A feature repository can also contain one or more Python files that contain feat ```python from datetime import timedelta -from feast import BigQuerySource, Entity, Feature, FeatureView, ValueType +from feast import BigQuerySource, Entity, Feature, FeatureView, Field, ValueType +from feast.types import Float32, String driver_locations_source = BigQuerySource( - table_ref="rh_prod.ride_hailing_co.drivers", - event_timestamp_column="event_timestamp", + table="rh_prod.ride_hailing_co.drivers", + timestamp_field="event_timestamp", created_timestamp_column="created_timestamp", ) @@ -107,19 +108,19 @@ driver_locations = FeatureView( name="driver_locations", entities=["driver"], ttl=timedelta(days=1), - features=[ - Feature(name="lat", dtype=ValueType.FLOAT), - Feature(name="lon", dtype=ValueType.STRING), + schema=[ + Field(name="lat", dtype=Float32), + Field(name="lon", dtype=String), ], - batch_source=driver_locations_source, + source=driver_locations_source, ) ``` {% endcode %} -To declare new feature definitions, just add code to the feature repository, either in existing files or in a new file. For more information on how to define features, see [Feature Views](../concepts/data-model-and-concepts.md#feature-view). +To declare new feature definitions, just add code to the feature repository, either in existing files or in a new file. For more information on how to define features, see [Feature Views](../getting-started/concepts/feature-view.md). ### Next steps -* See [Create a feature repository](../getting-started/create-a-feature-repository.md) to get started with an example feature repository. -* See [feature\_store.yaml](feature-store-yaml.md), [.feastignore](feast-ignore.md) or [Feature Views](../concepts/data-model-and-concepts.md#feature-view) for more information on the configuration files that live in a feature registry. +* See [Create a feature repository](../how-to-guides/feast-snowflake-gcp-aws/README.md) to get started with an example feature repository. +* See [feature\_store.yaml](feature-store-yaml.md), [.feastignore](feast-ignore.md) or [Feature Views](../getting-started/concepts/feature-view.md) for more information on the configuration files that live in a feature registry. diff --git a/docs/reference/feature-repository/README.md b/docs/reference/feature-repository/README.md index 90a6799c274..f737318773c 100644 --- a/docs/reference/feature-repository/README.md +++ b/docs/reference/feature-repository/README.md @@ -26,7 +26,7 @@ Typically, users store their feature repositories in a Git repository, especiall The structure of a feature repository is as follows: * The root of the repository should contain a `feature_store.yaml` file and may contain a `.feastignore` file. -* The repository should contain Python files that contain feature definitions. +* The repository should contain Python files that contain feature definitions. * The repository can contain other files as well, including documentation and potentially data files. An example structure of a feature repository is shown below: @@ -94,11 +94,12 @@ A feature repository can also contain one or more Python files that contain feat ```python from datetime import timedelta -from feast import BigQuerySource, Entity, Feature, FeatureView, ValueType +from feast import BigQuerySource, Entity, Feature, FeatureView, Field, ValueType +from feast.types import Float32, String driver_locations_source = BigQuerySource( table_ref="rh_prod.ride_hailing_co.drivers", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created_timestamp", ) @@ -112,18 +113,18 @@ driver_locations = FeatureView( name="driver_locations", entities=["driver"], ttl=timedelta(days=1), - features=[ - Feature(name="lat", dtype=ValueType.FLOAT), - Feature(name="lon", dtype=ValueType.STRING), + schema=[ + Field(name="lat", dtype=Float32), + Field(name="lon", dtype=String), ], - batch_source=driver_locations_source, + source=driver_locations_source, ) ``` {% endcode %} -To declare new feature definitions, just add code to the feature repository, either in existing files or in a new file. For more information on how to define features, see [Feature Views](../../getting-started/concepts/#feature-view). +To declare new feature definitions, just add code to the feature repository, either in existing files or in a new file. For more information on how to define features, see [Feature Views](../../getting-started/concepts/feature-view.md). ### Next steps -* See [Create a feature repository](../../how-to-guides/feast-gcp-aws/create-a-feature-repository.md) to get started with an example feature repository. -* See [feature_store.yaml](feature-store-yaml.md), [.feastignore](feast-ignore.md), or [Feature Views](../../getting-started/concepts/#feature-view) for more information on the configuration files that live in a feature registry. +* See [Create a feature repository](../../how-to-guides/feast-snowflake-gcp-aws/create-a-feature-repository.md) to get started with an example feature repository. +* See [feature_store.yaml](feature-store-yaml.md), [.feastignore](feast-ignore.md), or [Feature Views](../../getting-started/concepts/feature-view.md) for more information on the configuration files that live in a feature registry. diff --git a/docs/reference/feature-repository/registration-inferencing.md b/docs/reference/feature-repository/registration-inferencing.md index 1bd5f0f1a80..84faf949e11 100644 --- a/docs/reference/feature-repository/registration-inferencing.md +++ b/docs/reference/feature-repository/registration-inferencing.md @@ -2,6 +2,6 @@ ## Overview -* FeatureView - When the `features` parameter is left out of the feature view definition, upon a `feast apply` call, Feast will automatically consider every column in the data source as a feature to be registered other than the specific timestamp columns associated with the underlying data source definition (e.g. event_timestamp_column) and the columns associated with the feature view's entities. -* DataSource - When the `event_timestamp_column` parameter is left out of the data source definition, upon a 'feast apply' call, Feast will automatically find the sole timestamp column in the table underlying the data source and use that as the `event_timestamp_column`. If there are no columns of timestamp type or multiple columns of timestamp type, `feast apply` will throw an exception. +* FeatureView - When the `features` parameter is left out of the feature view definition, upon a `feast apply` call, Feast will automatically consider every column in the data source as a feature to be registered other than the specific timestamp columns associated with the underlying data source definition (e.g. timestamp_field) and the columns associated with the feature view's entities. +* DataSource - When the `timestamp_field` parameter is left out of the data source definition, upon a 'feast apply' call, Feast will automatically find the sole timestamp column in the table underlying the data source and use that as the `timestamp_field`. If there are no columns of timestamp type or multiple columns of timestamp type, `feast apply` will throw an exception. * Entity - When the `value_type` parameter is left out of the entity definition, upon a `feast apply` call, Feast will automatically find the column corresponding with the entity's `join_key` and take that column's data type to be the `value_type`. If the column doesn't exist, `feast apply` will throw an exception. diff --git a/docs/reference/feature-servers/go-feature-retrieval.md b/docs/reference/feature-servers/go-feature-retrieval.md new file mode 100644 index 00000000000..999a142c07d --- /dev/null +++ b/docs/reference/feature-servers/go-feature-retrieval.md @@ -0,0 +1,38 @@ +# Go-based Feature Retrieval + +## Overview + +The Go Feature Retrieval component is a Go implementation of the core feature serving logic, embedded in the Python SDK. It supports retrieval of feature references, feature services, and on demand feature views, and can be used either through the Python SDK or the [Python feature server](local-feature-server.md). + +Currently, this component only supports online serving and does not have an offline component including APIs to create feast feature repositories or apply configuration to the registry to facilitate online materialization. It also does not expose its own dedicated cli to perform feast actions. Furthermore, this component is only meant to expose an online serving API that can be called through the python SDK to facilitate faster online feature retrieval. + +The Go Feature Retrieval component currently only supports Redis and Sqlite as online stores; support for other online stores will be added soon. Initial benchmarks indicate that it is significantly faster than the Python feature server for online feature retrieval. We plan to release a more comprehensive set of benchmarks. For more details, see the [RFC](https://docs.google.com/document/d/1Lgqv6eWYFJgQ7LA_jNeTh8NzOPhqI9kGTeyESRpNHnE). + +## Installation + +As long as you are running macOS or linux x86 with python version 3.7-3.10, the go component comes pre-compiled when you run install feast. + +For developers, if you want to build from source, run `make compile-go-lib` to build and compile the go server. + +## Usage + +To enable the Go online feature retrieval component, set `go_feature_retrieval: True` in your `feature_store.yaml`. This will direct all online feature retrieval to Go instead of Python. This flag will be enabled by default in the future. + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: redis + connection_string: "localhost:6379" +go_feature_retrieval: True +``` +{% endcode %} + +## Future/Current Work + +The Go feature retrieval online feature logging for Data Quality Monitoring is currently in development. More information can be found [here](https://docs.google.com/document/d/110F72d4NTv80p35wDSONxhhPBqWRwbZXG4f9mNEMd98/edit#heading=h.9gaqqtox9jg6). + +We also plan on adding support for the Java feature server (e.g. the capability to call into the Go component and execute Java UDFs). + diff --git a/docs/reference/online-stores/dynamodb.md b/docs/reference/online-stores/dynamodb.md index 2f260b042d9..2af7e422d6e 100644 --- a/docs/reference/online-stores/dynamodb.md +++ b/docs/reference/online-stores/dynamodb.md @@ -27,7 +27,7 @@ Feast requires the following permissions in order to execute commands for Dynamo | ----------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------- | | **Apply** |

dynamodb:CreateTable

dynamodb:DescribeTable

dynamodb:DeleteTable

| arn:aws:dynamodb:\:\:table/\* | | **Materialize** | dynamodb.BatchWriteItem | arn:aws:dynamodb:\:\:table/\* | -| **Get Online Features** | dynamodb.GetItem | arn:aws:dynamodb:\:\:table/\* | +| **Get Online Features** | dynamodb.BatchGetItem | arn:aws:dynamodb:\:\:table/\* | The following inline policy can be used to grant Feast the necessary permissions: @@ -40,7 +40,7 @@ The following inline policy can be used to grant Feast the necessary permissions "dynamodb:DescribeTable", "dynamodb:DeleteTable", "dynamodb:BatchWriteItem", - "dynamodb:GetItem" + "dynamodb:BatchGetItem" ], "Effect": "Allow", "Resource": [ diff --git a/docs/roadmap.md b/docs/roadmap.md index daec463dbdf..080cf16c02f 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -15,8 +15,8 @@ The list below contains the functionality that contributors are planning to deve * [x] [Synapse source (community plugin)](https://github.com/Azure/feast-azure) * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) - * [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) - * [x] Kafka source (with [push support into the online store](https://docs.feast.dev/reference/alpha-stream-ingestion)) + * [x] [Spark (community plugin)](https://docs.feast.dev/reference/data-sources/spark) + * [x] Kafka / Kinesis sources (via [push support into the online store](https://docs.feast.dev/reference/data-sources/push) * [ ] HTTP source * **Offline Stores** * [x] [Snowflake](https://docs.feast.dev/reference/offline-stores/snowflake) @@ -26,7 +26,7 @@ The list below contains the functionality that contributors are planning to deve * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (community plugin)](https://github.com/nossrannug/feast-postgres) * [x] [Trino (community plugin)](https://github.com/Shopify/feast-trino) - * [x] [Spark (community plugin)](https://github.com/Adyen/feast-spark-offline-store) + * [x] [Spark (community plugin)](https://docs.feast.dev/reference/offline-stores/spark) * [x] [In-memory / Pandas](https://docs.feast.dev/reference/offline-stores/file) * [x] [Custom offline store support](https://docs.feast.dev/how-to-guides/adding-a-new-offline-store) * **Online Stores** @@ -41,12 +41,12 @@ The list below contains the functionality that contributors are planning to deve * [ ] Cassandra * **Streaming** * [x] [Custom streaming ingestion job support](https://docs.feast.dev/how-to-guides/creating-a-custom-provider) - * [x] [Push based streaming data ingestion](reference/alpha-stream-ingestion.md) + * [x] [Push based streaming data ingestion](https://docs.feast.dev/reference/data-sources/push.md) * [ ] Streaming ingestion on AWS * [ ] Streaming ingestion on GCP * **Feature Engineering** * [x] On-demand Transformations (Alpha release. See [RFC](https://docs.google.com/document/d/1lgfIw0Drc65LpaxbUu49RCeJgMew547meSJttnUqz7c/edit#)) - * [ ] Batch transformation (SQL. In progress. See [RFC](https://docs.google.com/document/d/1964OkzuBljifDvkV-0fakp2uaijnVzdwWNGdz7Vz50A/edit)) + * [ ] Batch transformation (In progress. See [RFC](https://docs.google.com/document/d/1964OkzuBljifDvkV-0fakp2uaijnVzdwWNGdz7Vz50A/edit)) * [ ] Streaming transformation * **Deployments** * [x] AWS Lambda (Alpha release. See [RFC](https://docs.google.com/document/d/1eZWKWzfBif66LDN32IajpaG-j82LSHCCOzY6R7Ax7MI/edit)) @@ -72,6 +72,6 @@ The list below contains the functionality that contributors are planning to deve * [x] CLI for browsing feature registry * [x] Model-centric feature tracking (feature services) * [x] Amundsen integration (see [Feast extractor](https://github.com/amundsen-io/amundsen/blob/main/databuilder/databuilder/extractor/feast_extractor.py)) - * [ ] Feast Web UI (in progress) + * [x] Feast Web UI (alpha) * [ ] REST API for browsing feature registry * [ ] Feature versioning diff --git a/docs/specs/datastore_online_example (1) (1).png b/docs/specs/datastore_online_example (1) (1).png new file mode 100644 index 00000000000..9c9b644d668 Binary files /dev/null and b/docs/specs/datastore_online_example (1) (1).png differ diff --git a/docs/specs/redis_online_example (1) (1).png b/docs/specs/redis_online_example (1) (1).png new file mode 100644 index 00000000000..ac426770bad Binary files /dev/null and b/docs/specs/redis_online_example (1) (1).png differ diff --git a/docs/tutorials/driver-stats-on-snowflake.md b/docs/tutorials/driver-stats-on-snowflake.md index 94ac109c942..01b158cb1a1 100644 --- a/docs/tutorials/driver-stats-on-snowflake.md +++ b/docs/tutorials/driver-stats-on-snowflake.md @@ -124,7 +124,12 @@ fs.materialize_incremental(end_date=datetime.now()) {% code title="test.py" %} ```python online_features = fs.get_online_features( - features=features, entity_rows=[{"driver_id": 1001}, {"driver_id": 1002}], + features=features, + entity_rows=[ + # {join_key: entity_value} + {"driver_id": 1001}, + {"driver_id": 1002} + ], ).to_dict() ``` {% endcode %} diff --git a/docs/tutorials/validating-historical-features.md b/docs/tutorials/validating-historical-features.md index 19ae4ef434c..5f85e66c946 100644 --- a/docs/tutorials/validating-historical-features.md +++ b/docs/tutorials/validating-historical-features.md @@ -1,12 +1,12 @@ # Validating historical features with Great Expectations -In this tutorial, we will use the public dataset of Chicago taxi trips to present data validation capabilities of Feast. -- The original dataset is stored in BigQuery and consists of raw data for each taxi trip (one row per trip) since 2013. +In this tutorial, we will use the public dataset of Chicago taxi trips to present data validation capabilities of Feast. +- The original dataset is stored in BigQuery and consists of raw data for each taxi trip (one row per trip) since 2013. - We will generate several training datasets (aka historical features in Feast) for different periods and evaluate expectations made on one dataset against another. Types of features we're ingesting and generating: -- Features that aggregate raw data with daily intervals (eg, trips per day, average fare or speed for a specific day, etc.). -- Features using SQL while pulling data from BigQuery (like total trips time or total miles travelled). +- Features that aggregate raw data with daily intervals (eg, trips per day, average fare or speed for a specific day, etc.). +- Features using SQL while pulling data from BigQuery (like total trips time or total miles travelled). - Features calculated on the fly when requested using Feast's on-demand transformations Our plan: @@ -31,7 +31,7 @@ Install Feast Python SDK and great expectations: ``` -### 1. Dataset preparation (Optional) +### 1. Dataset preparation (Optional) **You can skip this step if you don't have GCP account. Please use parquet files that are coming with this tutorial instead** @@ -56,15 +56,15 @@ Running some basic aggregations while pulling data from BigQuery. Grouping by ta ```python -data_query = """SELECT +data_query = """SELECT taxi_id, TIMESTAMP_TRUNC(trip_start_timestamp, DAY) as day, SUM(trip_miles) as total_miles_travelled, SUM(trip_seconds) as total_trip_seconds, SUM(fare) as total_earned, COUNT(*) as trip_count -FROM `bigquery-public-data.chicago_taxi_trips.taxi_trips` -WHERE +FROM `bigquery-public-data.chicago_taxi_trips.taxi_trips` +WHERE trip_miles > 0 AND trip_seconds > 60 AND trip_start_timestamp BETWEEN '2019-01-01' and '2020-12-31' AND trip_total < 1000 @@ -84,7 +84,7 @@ pyarrow.parquet.write_table(driver_stats_table, "trips_stats.parquet") def entities_query(year): return f"""SELECT distinct taxi_id -FROM `bigquery-public-data.chicago_taxi_trips.taxi_trips` +FROM `bigquery-public-data.chicago_taxi_trips.taxi_trips` WHERE trip_miles > 0 AND trip_seconds > 0 AND trip_start_timestamp BETWEEN '{year}-01-01' and '{year}-12-31' @@ -107,20 +107,21 @@ pyarrow.parquet.write_table(entities_2019_table, "entities.parquet") import pyarrow.parquet import pandas as pd -from feast import Feature, FeatureView, Entity, FeatureStore +from feast import FeatureView, Entity, FeatureStore, Field +from feast.types import Float64, Int64 from feast.value_type import ValueType from feast.data_format import ParquetFormat from feast.on_demand_feature_view import on_demand_feature_view from feast.infra.offline_stores.file_source import FileSource from feast.infra.offline_stores.file import SavedDatasetFileStorage +from datetime import timedelta -from google.protobuf.duration_pb2 import Duration ``` ```python batch_source = FileSource( - event_timestamp_column="day", + timestamp_field="day", path="trips_stats.parquet", # using parquet file that we created on previous step file_format=ParquetFormat() ) @@ -137,14 +138,14 @@ trips_stats_fv = FeatureView( name='trip_stats', entities=['taxi'], features=[ - Feature("total_miles_travelled", ValueType.DOUBLE), - Feature("total_trip_seconds", ValueType.DOUBLE), - Feature("total_earned", ValueType.DOUBLE), - Feature("trip_count", ValueType.INT64), - + Field(name="total_miles_travelled", dtype=Float64), + Field(name="total_trip_seconds", dtype=Float64), + Field(name="total_earned", dtype=Float64), + Field(name="trip_count", dtype=Int64), + ], - ttl=Duration(seconds=86400), - batch_source=batch_source, + ttl=timedelta(seconds=86400), + source=batch_source, ) ``` @@ -153,13 +154,13 @@ trips_stats_fv = FeatureView( ```python @on_demand_feature_view( - features=[ - Feature("avg_fare", ValueType.DOUBLE), - Feature("avg_speed", ValueType.DOUBLE), - Feature("avg_trip_seconds", ValueType.DOUBLE), - Feature("earned_per_hour", ValueType.DOUBLE), + schema=[ + Field("avg_fare", Float64), + Field("avg_speed", Float64), + Field("avg_trip_seconds", Float64), + Field("earned_per_hour", Float64), ], - inputs={ + sources={ "stats": trips_stats_fv } ) @@ -317,8 +318,8 @@ store.create_saved_dataset( Dataset profiler is a function that accepts dataset and generates set of its characteristics. This charasteristics will be then used to evaluate (validate) next datasets. -**Important: datasets are not compared to each other! -Feast use a reference dataset and a profiler function to generate a reference profile. +**Important: datasets are not compared to each other! +Feast use a reference dataset and a profiler function to generate a reference profile. This profile will be then used during validation of the tested dataset.** @@ -523,37 +524,37 @@ def stats_profiler(ds: PandasDataset) -> ExpectationSuite: max_value=60, mostly=0.99 # allow some outliers ) - + ds.expect_column_values_to_be_between( "total_miles_travelled", min_value=0, max_value=500, mostly=0.99 # allow some outliers ) - + # expectation of means based on observed values observed_mean = ds.trip_count.mean() ds.expect_column_mean_to_be_between("trip_count", min_value=observed_mean * (1 - DELTA), max_value=observed_mean * (1 + DELTA)) - + observed_mean = ds.earned_per_hour.mean() ds.expect_column_mean_to_be_between("earned_per_hour", min_value=observed_mean * (1 - DELTA), max_value=observed_mean * (1 + DELTA)) - - + + # expectation of quantiles qs = [0.5, 0.75, 0.9, 0.95] observed_quantiles = ds.avg_fare.quantile(qs) - + ds.expect_column_quantile_values_to_be_between( "avg_fare", quantile_ranges={ "quantiles": qs, "value_ranges": [[None, max_value] for max_value in observed_quantiles] - }) - + }) + return ds.get_expectation_suite() ``` @@ -663,7 +664,7 @@ _ = job.to_df(validation_reference=validation_reference) Validation successfully passed as no exception were raised. -### 5. Validating new historical retrieval +### 5. Validating new historical retrieval Creating new timestamps for Dec 2020: diff --git a/examples/java-demo/feature_repo/driver_repo.py b/examples/java-demo/feature_repo/driver_repo.py index 233593ff02a..ce9469647f6 100644 --- a/examples/java-demo/feature_repo/driver_repo.py +++ b/examples/java-demo/feature_repo/driver_repo.py @@ -1,13 +1,17 @@ import pandas as pd -from feast import Entity, Feature, FeatureView, FileSource, ValueType -from feast.data_source import RequestDataSource +from feast.data_source import RequestSource +from feast.field import Field from feast.on_demand_feature_view import on_demand_feature_view from feast.request_feature_view import RequestFeatureView +from feast.types import Float32, Float64, Int64, String from google.protobuf.duration_pb2 import Duration +from feast.field import Field + +from feast import Entity, Feature, FeatureView, FileSource, ValueType driver_hourly_stats = FileSource( path="data/driver_stats_with_string.parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",) @@ -15,11 +19,11 @@ name="driver_hourly_stats", entities=["driver_id"], ttl=Duration(seconds=86400000), - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), - Feature(name="string_feature", dtype=ValueType.STRING), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), + Field(name="string_feature", dtype=String), ], online=True, batch_source=driver_hourly_stats, @@ -28,21 +32,24 @@ # Define a request data source which encodes features / information only # available at request time (e.g. part of the user initiated HTTP request) -input_request = RequestDataSource( +input_request = RequestSource( name="vals_to_add", - schema={"val_to_add": ValueType.INT64, "val_to_add_2": ValueType.INT64}, + schema=[ + Field(name="val_to_add", dtype=Int64), + Field(name="val_to_add_2", dtype=Int64), + ], ) # Define an on demand feature view which can generate new features based on -# existing feature views and RequestDataSource features +# existing feature views and RequestSource features @on_demand_feature_view( inputs={ "driver_hourly_stats": driver_hourly_stats_view, "vals_to_add": input_request, }, - features=[ - Feature(name="conv_rate_plus_val1", dtype=ValueType.DOUBLE), - Feature(name="conv_rate_plus_val2", dtype=ValueType.DOUBLE), + schema=[ + Field(name="conv_rate_plus_val1", dtype=Float64), + Field(name="conv_rate_plus_val2", dtype=Float64), ], ) def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: @@ -55,7 +62,10 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: # Define request feature view driver_age_request_fv = RequestFeatureView( name="driver_age", - request_data_source=RequestDataSource( - name="driver_age", schema={"driver_age": ValueType.INT64,} + request_data_source=RequestSource( + name="driver_age", + schema=[ + Field(name="driver_age", dtype=Int64), + ], ), ) diff --git a/go.mod b/go.mod index 109666b7622..4fb5ef83004 100644 --- a/go.mod +++ b/go.mod @@ -1,39 +1,53 @@ module github.com/feast-dev/feast +go 1.17 + require ( - github.com/Masterminds/goutils v1.1.0 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/feast-dev/feast/sdk/go v0.0.0-20200516052424-09ff3dda724c // indirect + github.com/apache/arrow/go/v8 v8.0.0-20220408212425-58fe60f59289 github.com/ghodss/yaml v1.0.0 - github.com/gogo/protobuf v1.3.1 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/golang/mock v1.2.0 + github.com/go-python/gopy v0.4.0 + github.com/go-redis/redis/v8 v8.11.4 github.com/golang/protobuf v1.5.2 - github.com/google/go-cmp v0.5.5 - github.com/huandu/xstrings v1.2.0 // indirect - github.com/lyft/protoc-gen-validate v0.1.0 // indirect - github.com/mitchellh/copystructure v1.0.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 - github.com/mwitkow/go-proto-validators v0.2.0 // indirect - github.com/pseudomuto/protoc-gen-doc v1.3.0 // indirect - github.com/pseudomuto/protokit v0.2.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/spf13/cobra v0.0.4 - github.com/spf13/viper v1.4.0 - github.com/woop/protoc-gen-doc v1.3.0 // indirect - go.opencensus.io v0.22.3 // indirect - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect - golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f - golang.org/x/tools v0.1.8 // indirect - google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect - google.golang.org/grpc v1.29.1 - google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/russross/blackfriday.v2 v2.0.0 // indirect - gopkg.in/yaml.v2 v2.2.4 - istio.io/gogo-genproto v0.0.0-20191212213402-78a529a42cd8 // indirect - istio.io/tools v0.0.0-20191228030621-c4eb6a11039c // indirect + github.com/google/uuid v1.3.0 + github.com/mattn/go-sqlite3 v1.14.12 + github.com/spaolacci/murmur3 v1.1.0 + github.com/stretchr/testify v1.7.0 + google.golang.org/grpc v1.45.0 + google.golang.org/protobuf v1.28.0 +) + +require ( + github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect + github.com/andybalholm/brotli v1.0.4 // indirect + github.com/apache/thrift v0.15.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/goccy/go-json v0.9.6 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gonuts/commander v0.1.0 // indirect + github.com/gonuts/flag v0.1.0 // indirect + github.com/google/flatbuffers v2.0.6+incompatible // indirect + github.com/klauspost/asmfmt v1.3.2 // indirect + github.com/klauspost/compress v1.15.1 // indirect + github.com/klauspost/cpuid/v2 v2.0.12 // indirect + github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect + github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect + github.com/pierrec/lz4/v4 v4.1.14 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/zeebo/xxh3 v1.0.2 // indirect + golang.org/x/exp v0.0.0-20220407100705-7b9b53b0aca4 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect + golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 // indirect + golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/tools v0.1.10 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) -go 1.13 +replace github.com/go-python/gopy v0.4.0 => github.com/feast-dev/gopy v0.4.1-0.20220329011409-d705e6cd1d9b diff --git a/go.sum b/go.sum index 8b0c2677f3c..ef9a0c6989b 100644 --- a/go.sum +++ b/go.sum @@ -1,482 +1,536 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cuelang.org/go v0.0.14/go.mod h1:gehQASsTv+lFZknWIG0hANGVSBiHD7HyKWmAdEZL3No= -fortio.org/fortio v1.3.1/go.mod h1:Go0fRqoPJ1xy5JOWcS23jyF58byVZxFyEePYsGmCR0k= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= -github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v8 v8.0.0-20220408212425-58fe60f59289 h1:nzLohtTu6I/mbr7xjFrMKDk88mkL/Lcp8kVcIITGjaE= +github.com/apache/arrow/go/v8 v8.0.0-20220408212425-58fe60f59289/go.mod h1:UUe+gJaMnuFD6icfGSJxUjG/tX/POUbPS/wE+EFyncM= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.15.0 h1:aGvdaR0v1t9XLgjtBYwxcBvBOTMqClzwE26CHOgjW1Y= +github.com/apache/thrift v0.15.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/client9/gospell v0.0.0-20160306015952-90dfc71015df h1:XXCjxndsxMyNjoZtyuyDnzSck+h681QN7vKkK0EIVq0= -github.com/client9/gospell v0.0.0-20160306015952-90dfc71015df/go.mod h1:X4IDm8zK6KavjWkfKQCet43DKeLii9nJhUK/seHoSbA= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/apd/v2 v2.0.1/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= -github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc v0.0.0-20180117170138-065b426bd416/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.0.0-20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/proto v1.6.15/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/feast-dev/feast/sdk/go v0.0.0-20200516052424-09ff3dda724c h1:jltCNN1tpaFxCslQtHUfU5u5qodH/D8rqPmxvRWGNWM= -github.com/feast-dev/feast/sdk/go v0.0.0-20200516052424-09ff3dda724c/go.mod h1:F3sMDmJ9hxjlh0Z7fM6/atvMJd8moahKxUF1LCzVthQ= -github.com/feast-dev/feast/sdk/go v0.5.0 h1:h4UiFgqeWrw9voPqigwiSYWl/vjUn2mgoUAFIa29s3A= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/feast-dev/gopy v0.4.1-0.20220329011409-d705e6cd1d9b h1:C/oK6gi12Q7fiiVCI3e62tqWCSXqsTz9OpyK249XI84= +github.com/feast-dev/gopy v0.4.1-0.20220329011409-d705e6cd1d9b/go.mod h1:ZO6vpitQ61NVoQP/2yOubPS6ET5pP3CAWCiMYn5eqCc= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/getkin/kin-openapi v0.1.1-0.20190507152207-d3180292eead/go.mod h1:V1z9xl9oF5Wt7v32ne4FmiF1alpS4dM6mNzoywPOXlk= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= -github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.17.2/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.17.2/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.17.2/go.mod h1:QO936ZXeisByFmZEO1IS1Dqhtf4QV1sYYFtIq6Ld86Q= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.17.2/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg= +github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/goccy/go-json v0.7.10/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.6 h1:5/4CtRQdtsX0sal8fdVhTaiMN01Ri8BExZZ8iRmHQ6E= +github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gonuts/commander v0.1.0 h1:EcDTiVw9oAVORFjQOEOuHQqcl6OXMyTgELocTq6zJ0I= +github.com/gonuts/commander v0.1.0/go.mod h1:qkb5mSlcWodYgo7vs8ulLnXhfinhZsZcm6+H/z1JjgY= +github.com/gonuts/flag v0.1.0 h1:fqMv/MZ+oNGu0i9gp0/IQ/ZaPIDoAZBOBaJoV7viCWM= +github.com/gonuts/flag v0.1.0/go.mod h1:ZTmTGtrSPejTo/SRNhCqwLTmiAgyBdCkLYhHrAoBdz4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/flatbuffers v2.0.5+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v2.0.6+incompatible h1:XHFReMv7nFFusa+CEokzWbzaYocKXI6C7hdU5Kgh9Lw= +github.com/google/flatbuffers v2.0.6+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= -github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= -github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= -github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0= -github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.0.0-20141017032234-72f9bd7c4e0c/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/asmfmt v1.3.1/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lyft/protoc-gen-validate v0.1.0 h1:NytKd9K7UW7Szxn+9PYNsaJ/98TL/WsDq4ro4ZVuh5o= -github.com/lyft/protoc-gen-validate v0.1.0/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0= +github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-proto-validators v0.2.0 h1:F6LFfmgVnfULfaRsQWBbe7F7ocuHCr9+7m+GAeDzNbQ= -github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.12/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= +github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/pseudomuto/protoc-gen-doc v1.3.0 h1:wpwmaSCWY2lGwkzAxAaqYcGyoklZjZmeXrJ/X7IskJM= -github.com/pseudomuto/protoc-gen-doc v1.3.0/go.mod h1:fwtQAY9erXp3mC92O8OTECnDlJT2r0Ff4KSEKbGEmy0= -github.com/pseudomuto/protokit v0.2.0 h1:hlnBDcy3YEDXH7kc9gV+NLaN0cDzhDvD1s7Y6FZ8RpM= -github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= -github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/testscript v1.1.0/go.mod h1:lzMlnW8LS56mcdJoQYkrlzqOoTFCOemzt5LusJ93bDM= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.0-20180319062004-c439c4fa0937/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.4/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/woop/protoc-gen-doc v1.3.0 h1:adA9nDOuhsubIi7HaY7Bl+jn/r5OHP6KG+On3OzI13s= -github.com/woop/protoc-gen-doc v1.3.0/go.mod h1:/cPn1JCjHFIrRBAffIVBmWjOO/h+K5IYON1RjrWDdZw= -github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.1/go.mod h1:8VHV24/3AZLn3b6Mlp/KuC33LWH687Wq6EnziEB+rsA= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20211216164055-b2b84827b756/go.mod h1:b9TAUYHmRtqA6klRHApnXMnj+OyLce4yF5cZCUbk2ps= +golang.org/x/exp v0.0.0-20220407100705-7b9b53b0aca4 h1:K3x+yU+fbot38x5bQbU2QqUAVyYLEktdNH2GxZLnM3U= +golang.org/x/exp v0.0.0-20220407100705-7b9b53b0aca4/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg= -golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 h1:EN5+DfgmRMvRUrMGERW2gQl3Vc+Z7ZMnI/xdEpPSf0c= +golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae h1:3tcmuaB7wwSZtelmiv479UjUB+vviwABz7a133ZwOKQ= -golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 h1:YTzHMGlqJu67/uEo1lBv0n3wBXhXNeUbB1XfN2vmTm0= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 h1:QyVthZKMsyaQwBTJE04jdNN0Pp5Fn9Qga0mrgxyERQM= +golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -485,175 +539,104 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59 h1:QjA/9ArTfVTLfEhClDCG7SGrZkZixxWpwNCDiwJfh88= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200321014904-268ba720d32c h1:Qp5jXmUCqMiVq4676uW7bY2oskIR1ivTboSMn8qgeX0= -golang.org/x/tools v0.0.0-20200321014904-268ba720d32c/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200321224714-0d839f3cf2ed h1:OCZDlBlLYiUK6T33/8+3BnojrS2W+Dg1rKYJhR89xGE= -golang.org/x/tools v0.0.0-20200321224714-0d839f3cf2ed/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3 h1:Z68UA+HA9shnGhQbAFXKqL1Rk/tfiTHJ57bNm/MUL/A= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200504022951-6b6965ac5dd1 h1:C8rdnd6KieI73Z2Av0sS0t4kW+geIH/M8kNX8Hmvn9E= -golang.org/x/tools v0.0.0-20200504022951-6b6965ac5dd1/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53 h1:vmsb6v0zUdmUlXfwKaYrHPPRCV0lHq/IwNIf0ASGjyQ= -golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200519205726-57a9e4404bf7 h1:nm4zDh9WvH4jiuUpMY5RUsvOwrtTVVAsUaCdLW71hfY= -golang.org/x/tools v0.0.0-20200519205726-57a9e4404bf7/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc h1:6m2YO+AmBApbUOmhsghW+IfRyZOY4My4UYvQQrEpHfY= -golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200604042327-9b20fe4cabe8 h1:8Xr1qwxn90MXYKftwNxIO2g4J+26naghxFS5rYiTZww= -golang.org/x/tools v0.0.0-20200604042327-9b20fe4cabe8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa h1:mMXQKlWCw9mIWgVLLfiycDZjMHMMYqiuakI4E/l2xcA= -golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200923182640-463111b69878 h1:VUw1+Jf6KJPf82mbTQMia6HCnNMv2BbAipkEZ4KTcqQ= -golang.org/x/tools v0.0.0-20200923182640-463111b69878/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346 h1:hzJjkvxUIF3bSt+v8N5tBQNx/605vszZJ+3XsIamzZo= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20200928201943-a0ef9b62deab h1:CyH2SDm5ATQiX9gtbMYfvNNed97A9v+TJFnUX/fTaJY= -golang.org/x/tools v0.0.0-20200928201943-a0ef9b62deab/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20200929223013-bf155c11ec6f h1:7+Nz9MyPqt2qMCTvNiRy1G0zYfkB7UCa+ayT6uVvbyI= -golang.org/x/tools v0.0.0-20200929223013-bf155c11ec6f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201001230009-b5b87423c93b h1:07IVqnnzaip3TGyl/cy32V5YP3FguWG4BybYDTBNpm0= -golang.org/x/tools v0.0.0-20201001230009-b5b87423c93b/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201011145850-ed2f50202694 h1:BANdcOVw3KTuUiyfDp7wrzCpkCe8UP3lowugJngxBTg= -golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201013053347-2db1cd791039 h1:kLBxO4OPBgPwjg8Vvu+/0DCHIfDwYIGNFcD66NU9kpo= -golang.org/x/tools v0.0.0-20201013053347-2db1cd791039/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201015182029-a5d9e455e9c4 h1:rQWkJiVIyJ3PgiSHL+RXc8xbrK8duU6jG5eeZ9G7nk8= -golang.org/x/tools v0.0.0-20201015182029-a5d9e455e9c4/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201017001424-6003fad69a88 h1:ZB1XYzdDo7c/O48jzjMkvIjnC120Z9/CwgDWhePjQdQ= -golang.org/x/tools v0.0.0-20201017001424-6003fad69a88/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201124005743-911501bfb504 h1:jOKV2ysikH1GANB7t2LotmhyvkkPvl7HQoEXkV6slJA= -golang.org/x/tools v0.0.0-20201124005743-911501bfb504/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3 h1:DnoIG+QAMaF5NvxnGe/oKsgKcAc6PcUyl8q0VetfQ8s= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7 h1:ZUjXAXmrAyrmmCPHgCA/vChHcpsX27MZ3yBonD/z1KE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c h1:5aI3/f/3eCZps9xwoEnmgfDJDhMbnJpfqeGpjVNgVEI= -google.golang.org/genproto v0.0.0-20200319113533-08878b785e9c/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587 h1:1Ym+vvUpq1ZHvxzn34gENJX8U4aKO+vhy2P/2+Xl6qQ= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac h1:qSNTkEN+L2mvWcLgJOR+8bdHX9rN/IdU3A1Ghpfb1Rg= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM= -google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/russross/blackfriday.v2 v2.0.0 h1:+FlnIV8DSQnT7NZ43hcVKcdJdzZoeCmJj4Ql8gq5keA= -gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI= -gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -istio.io/gogo-genproto v0.0.0-20191009201739-17d570f95998 h1:uvW88tRzT6wjR+SdqPoDjR0jjKTYWmjOp2Z1jXs1ZJQ= -istio.io/gogo-genproto v0.0.0-20191009201739-17d570f95998/go.mod h1:OzpAts7jljZceG4Vqi5/zXy/pOg1b209T3jb7Nv5wIs= -istio.io/gogo-genproto v0.0.0-20191212213402-78a529a42cd8 h1:vcvyAXMWwGwTlFdFT36QlzYg5Ggm9p9/FYcMjf2vZnQ= -istio.io/gogo-genproto v0.0.0-20191212213402-78a529a42cd8/go.mod h1:OzpAts7jljZceG4Vqi5/zXy/pOg1b209T3jb7Nv5wIs= -istio.io/tools v0.0.0-20191228030621-c4eb6a11039c h1:PvYMeezZgkWY/17LYGSI5Xog/7IGk9FGXu6QHgn2mVg= -istio.io/tools v0.0.0-20191228030621-c4eb6a11039c/go.mod h1:6u5K87o8AZvfCdPhr0M60yuZR5/4pPCOCiokv7P+I+0= -k8s.io/api v0.0.0-20191004120003-3a12735a829a/go.mod h1:ceHJE/vDjU8jKnRV6Vqn/+vyZmC6NvOluInN+RhQkIs= -k8s.io/api v0.0.0-20191016110408-35e52d86657a/go.mod h1:/L5qH+AD540e7Cetbui1tuJeXdmNhO8jM6VkXeDdDhQ= -k8s.io/apiextensions-apiserver v0.0.0-20191011152811-a1d7614a8e0f/go.mod h1:ANlyWoQfvraFQiqL/eCLO0r19z0pA0J7eXfRx94lj9Y= -k8s.io/apimachinery v0.0.0-20191004115701-31ade1b30762/go.mod h1:Xc10RHc1U+F/e9GCloJ8QAeCGevSVP5xhOhqlE+e1kM= -k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= -k8s.io/apiserver v0.0.0-20191004121824-7b46ba88e365/go.mod h1:EB3CoZ8WNX95G9ftm5Wc/qdc9qqbxgyYHIVJtmiOLUs= -k8s.io/client-go v0.0.0-20191004120415-b2f42092e376/go.mod h1:ksVkYlACXo9hR9AV+cYyCkuWL1xnWcGtAFxsfqMcozg= -k8s.io/client-go v0.0.0-20191016111102-bec269661e48/go.mod h1:hrwktSwYGI4JK+TJA3dMaFyyvHVi/aLarVHpbs8bgCU= -k8s.io/code-generator v0.0.0-20190612205613-18da4a14b22b/go.mod h1:G8bQwmHm2eafm5bgtX67XDZQ8CWKSGu9DekI+yN4Y5I= -k8s.io/component-base v0.0.0-20191004121406-d5138742ad72/go.mod h1:zT8T6A3K4wLlbQkLUC62skjmWoiNJ9B8WUQj3KIvcrQ= -k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/helm v2.12.0+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= -k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= -k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= -k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= -k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= -modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= -modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= -modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= -sigs.k8s.io/structured-merge-diff v0.0.0-20190302045857-e85c7b244fd2/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/sdk/python/feast/protos/__init__.py b/go/cmd/server/logging/feature_repo/__init__.py similarity index 100% rename from sdk/python/feast/protos/__init__.py rename to go/cmd/server/logging/feature_repo/__init__.py diff --git a/go/cmd/server/logging/feature_repo/data/online_store.db b/go/cmd/server/logging/feature_repo/data/online_store.db new file mode 100644 index 00000000000..b6ccea139e5 Binary files /dev/null and b/go/cmd/server/logging/feature_repo/data/online_store.db differ diff --git a/go/cmd/server/logging/feature_repo/driver_stats.parquet b/go/cmd/server/logging/feature_repo/driver_stats.parquet new file mode 100644 index 00000000000..a1e196df26e Binary files /dev/null and b/go/cmd/server/logging/feature_repo/driver_stats.parquet differ diff --git a/go/cmd/server/logging/feature_repo/example.py b/go/cmd/server/logging/feature_repo/example.py new file mode 100644 index 00000000000..f3ca6123083 --- /dev/null +++ b/go/cmd/server/logging/feature_repo/example.py @@ -0,0 +1,40 @@ +# This is an example feature definition file + +from google.protobuf.duration_pb2 import Duration + +from feast import Entity, Feature, FeatureView, FileSource, ValueType, FeatureService + +# Read data from parquet files. Parquet is convenient for local development mode. For +# production, you can use your favorite DWH, such as BigQuery. See Feast documentation +# for more info. +driver_hourly_stats = FileSource( + path="driver_stats.parquet", + event_timestamp_column="event_timestamp", + created_timestamp_column="created", +) + +# Define an entity for the driver. You can think of entity as a primary key used to +# fetch features. +driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",) + +# Our parquet files contain sample data that includes a driver_id column, timestamps and +# three feature column. Here we define a Feature View that will allow us to serve this +# data to our model online. +driver_hourly_stats_view = FeatureView( + name="driver_hourly_stats", + entities=["driver_id"], + ttl=Duration(seconds=86400 * 365 * 10), + features=[ + Feature(name="conv_rate", dtype=ValueType.FLOAT), + Feature(name="acc_rate", dtype=ValueType.FLOAT), + Feature(name="avg_daily_trips", dtype=ValueType.INT64), + ], + online=True, + batch_source=driver_hourly_stats, + tags={}, +) + +driver_stats_fs = FeatureService( + name="test_service", + features=[driver_hourly_stats_view] +) \ No newline at end of file diff --git a/go/cmd/server/logging/feature_repo/feature_store.yaml b/go/cmd/server/logging/feature_repo/feature_store.yaml new file mode 100644 index 00000000000..3b48f432875 --- /dev/null +++ b/go/cmd/server/logging/feature_repo/feature_store.yaml @@ -0,0 +1,5 @@ +project: feature_repo +registry: data/registry.db +provider: local +online_store: + path: data/online_store.db \ No newline at end of file diff --git a/go/cmd/server/logging/filelogstorage.go b/go/cmd/server/logging/filelogstorage.go new file mode 100644 index 00000000000..19e9569e69d --- /dev/null +++ b/go/cmd/server/logging/filelogstorage.go @@ -0,0 +1,86 @@ +package logging + +import ( + "errors" + "fmt" + "io" + "os" + "path/filepath" + + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/apache/arrow/go/v8/parquet" + "github.com/apache/arrow/go/v8/parquet/pqarrow" + "github.com/feast-dev/feast/go/internal/feast/registry" +) + +type FileLogStorage struct { + // Feast project name + project string + path string +} + +func GetFileConfig(config *registry.RepoConfig) (*OfflineLogStoreConfig, error) { + fileConfig := OfflineLogStoreConfig{ + storeType: "file", + } + if onlineStorePath, ok := config.OfflineStore["path"]; ok { + path, success := onlineStorePath.(string) + if !success { + return &fileConfig, fmt.Errorf("path, %s, cannot be converted to string", path) + } + fileConfig.path = path + } else { + return nil, errors.New("need path for file log storage") + } + return &fileConfig, nil +} + +// This offline store is currently only used for testing. It will be instantiated during go unit tests to log to file +// and the parquet files will be cleaned up after the test is run. +func NewFileOfflineStore(project string, offlineStoreConfig *OfflineLogStoreConfig) (*FileLogStorage, error) { + store := FileLogStorage{project: project} + var absPath string + var err error + // TODO(kevjumba) remove this default catch. + if offlineStoreConfig.path != "" { + absPath, err = filepath.Abs(offlineStoreConfig.path) + } else { + return nil, errors.New("need path for file log storage") + } + if err != nil { + return nil, err + } + store.path = absPath + return &store, nil +} + +func openLogFile(absPath string) (*os.File, error) { + var _, err = os.Stat(absPath) + + // create file if not exists + if os.IsNotExist(err) { + var file, err = os.Create(absPath) + if err != nil { + return nil, err + } + return file, nil + } else { + return nil, fmt.Errorf("path %s already exists", absPath) + } +} + +func (f *FileLogStorage) FlushToStorage(tbl array.Table) error { + w, err := openLogFile(f.path) + var writer io.Writer = w + if err != nil { + return err + } + props := parquet.NewWriterProperties(parquet.WithDictionaryDefault(false)) + arrProps := pqarrow.DefaultWriterProps() + err = pqarrow.WriteTable(tbl, writer, 100, props, arrProps) + if err != nil { + return err + } + return nil + +} diff --git a/go/cmd/server/logging/filelogstorage_test.go b/go/cmd/server/logging/filelogstorage_test.go new file mode 100644 index 00000000000..1da7dd38ad2 --- /dev/null +++ b/go/cmd/server/logging/filelogstorage_test.go @@ -0,0 +1,70 @@ +package logging + +import ( + "context" + "path/filepath" + + "testing" + + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/apache/arrow/go/v8/parquet/file" + "github.com/apache/arrow/go/v8/parquet/pqarrow" + "github.com/feast-dev/feast/go/internal/test" + "github.com/stretchr/testify/assert" +) + +func TestFlushToStorage(t *testing.T) { + ctx := context.Background() + table, expectedSchema, expectedColumns, err := GetTestArrowTableAndExpectedResults() + defer table.Release() + assert.Nil(t, err) + offlineStoreConfig := OfflineLogStoreConfig{ + storeType: "file", + path: "./log.parquet", + } + fileStore, err := NewFileOfflineStore("test", &offlineStoreConfig) + assert.Nil(t, err) + err = fileStore.FlushToStorage(array.Table(table)) + assert.Nil(t, err) + logPath, err := filepath.Abs(offlineStoreConfig.path) + assert.Nil(t, err) + pf, err := file.OpenParquetFile(logPath, false) + assert.Nil(t, err) + + reader, err := pqarrow.NewFileReader(pf, pqarrow.ArrowReadProperties{}, memory.DefaultAllocator) + assert.Nil(t, err) + + tbl, err := reader.ReadTable(ctx) + assert.Nil(t, err) + tr := array.NewTableReader(tbl, -1) + defer tbl.Release() + + defer tr.Release() + for tr.Next() { + rec := tr.Record() + assert.NotNil(t, rec) + for _, field := range rec.Schema().Fields() { + assert.Contains(t, expectedSchema, field.Name) + assert.Equal(t, field.Type, expectedSchema[field.Name]) + } + values, err := test.GetProtoFromRecord(rec) + + assert.Nil(t, err) + for name, val := range values { + if name == "RequestId" { + // Ensure there are request ids in record. + assert.Greater(t, len(val.Val), 0) + } else { + assert.Equal(t, len(val.Val), len(expectedColumns[name].Val)) + for idx, featureVal := range val.Val { + assert.Equal(t, featureVal.Val, expectedColumns[name].Val[idx].Val) + } + } + } + } + + err = test.CleanUpFile(logPath) + assert.Nil(t, err) + +} diff --git a/go/cmd/server/logging/logging.go b/go/cmd/server/logging/logging.go new file mode 100644 index 00000000000..010644709ae --- /dev/null +++ b/go/cmd/server/logging/logging.go @@ -0,0 +1,392 @@ +package logging + +import ( + "errors" + "fmt" + "log" + "time" + + "github.com/apache/arrow/go/v8/arrow" + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/feast-dev/feast/go/internal/feast" + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/protos/feast/serving" + "github.com/feast-dev/feast/go/protos/feast/types" + gotypes "github.com/feast-dev/feast/go/types" + "google.golang.org/protobuf/types/known/timestamppb" +) + +const DEFAULT_LOG_FLUSH_INTERVAL = 100 * time.Millisecond +const DEFAULT_LOG_INSERT_TIMEOUT = 20 * time.Millisecond + +type Log struct { + // Example: val{int64_val: 5017}, val{int64_val: 1003} + EntityValue []*types.Value + + FeatureValues []*types.Value + FeatureStatuses []serving.FieldStatus + EventTimestamps []*timestamppb.Timestamp + RequestContext map[string]*types.Value + RequestId string +} + +type MemoryBuffer struct { + featureService *model.FeatureService + logs []*Log +} + +type LoggingService struct { + memoryBuffer *MemoryBuffer + logChannel chan *Log + fs *feast.FeatureStore + offlineLogStorage OfflineLogStorage + logInsertTTl time.Duration + logFlushInterval time.Duration +} + +func NewLoggingService(fs *feast.FeatureStore, logChannelCapacity int, featureServiceName string, enableLogProcessing bool) (*LoggingService, error) { + var featureService *model.FeatureService = nil + var err error + if fs != nil { + featureService, err = fs.GetFeatureService(featureServiceName) + if err != nil { + return nil, err + } + + } + + loggingService := &LoggingService{ + logChannel: make(chan *Log, logChannelCapacity), + memoryBuffer: &MemoryBuffer{ + logs: make([]*Log, 0), + featureService: featureService, + }, + fs: fs, + logInsertTTl: DEFAULT_LOG_INSERT_TIMEOUT, + logFlushInterval: DEFAULT_LOG_FLUSH_INTERVAL, + } + + if fs != nil { + offlineLogStorage, err := NewOfflineStore(fs.GetRepoConfig()) + loggingService.offlineLogStorage = offlineLogStorage + if err != nil { + return nil, err + } + } + + // Start goroutine to process logs + if enableLogProcessing { + go loggingService.processLogs() + + } + return loggingService, nil +} + +func (s *LoggingService) EmitLog(l *Log) error { + select { + case s.logChannel <- l: + return nil + case <-time.After(s.logInsertTTl): + return fmt.Errorf("could not add to log channel with capacity %d. Operation timed out. Current log channel length is %d", cap(s.logChannel), len(s.logChannel)) + } +} + +func (s *LoggingService) processLogs() { + // start a periodic flush + // TODO(kevjumba): set param so users can configure flushing duration + ticker := time.NewTicker(s.logFlushInterval) + defer ticker.Stop() + + for { + s.PerformPeriodicAppendToMemoryBufferAndLogFlush(ticker) + } +} + +// Select that either ingests new logs that are added to the logging channel, one at a time to add +// to the in-memory buffer or flushes all of them synchronously to the OfflineStorage on a time interval. +func (s *LoggingService) PerformPeriodicAppendToMemoryBufferAndLogFlush(t *time.Ticker) { + select { + case t := <-t.C: + s.flushLogsToOfflineStorage(t) + case new_log := <-s.logChannel: + log.Printf("Adding %s to memory.\n", new_log.FeatureValues) + s.memoryBuffer.logs = append(s.memoryBuffer.logs, new_log) + } +} + +// Acquires the logging schema from the feature service, converts the memory buffer array of rows of logs and flushes +// them to the offline storage. +func (s *LoggingService) flushLogsToOfflineStorage(t time.Time) error { + offlineStoreType, ok := getOfflineStoreType(s.fs.GetRepoConfig().OfflineStore) + if !ok { + return fmt.Errorf("could not get offline storage type for config: %s", s.fs.GetRepoConfig().OfflineStore) + } + if offlineStoreType == "file" { + entityMap, featureViews, odfvs, err := s.GetFcos() + if err != nil { + return err + } + schema, err := GetSchemaFromFeatureService(s.memoryBuffer.featureService, entityMap, featureViews, odfvs) + if err != nil { + return err + } + table, err := ConvertMemoryBufferToArrowTable(s.memoryBuffer, schema) + if err != nil { + return err + } + s.offlineLogStorage.FlushToStorage(table) + if err != nil { + return err + } + s.memoryBuffer.logs = s.memoryBuffer.logs[:0] + } else { + // Currently don't support any other offline flushing. + return errors.New("currently only file type is supported for offline log storage") + } + return nil +} + +// Takes memory buffer of logs in array row and converts them to columnar with generated fcoschema generated by GetFcoSchema +// and writes them to arrow table. +// Returns arrow table that contains all of the logs in columnar format. +func ConvertMemoryBufferToArrowTable(memoryBuffer *MemoryBuffer, fcoSchema *Schema) (array.Table, error) { + arrowMemory := memory.NewGoAllocator() + + columnNameToProtoValueArray := make(map[string][]*types.Value) + columnNameToStatus := make(map[string][]int32) + columnNameToTimestamp := make(map[string][]int64) + entityNameToEntityValues := make(map[string][]*types.Value) + + strBuilder := array.NewStringBuilder(arrowMemory) + + for _, l := range memoryBuffer.logs { + // EntityTypes maps an entity name to the specific type and also which index in the entityValues array it is + // e.g if an Entity Key is {driver_id, customer_id}, then the driver_id entitytype would be dtype=int64, index=0. + // It's in the order of the entities as given by the schema. + for idx, joinKey := range fcoSchema.Entities { + if _, ok := entityNameToEntityValues[joinKey]; !ok { + entityNameToEntityValues[joinKey] = make([]*types.Value, 0) + } + entityNameToEntityValues[joinKey] = append(entityNameToEntityValues[joinKey], l.EntityValue[idx]) + } + + // Contains both fv and odfv feature value types => they are processed in order of how the appear in the featureService + for idx, featureName := range fcoSchema.Features { + // populate the proto value arrays with values from memory buffer in separate columns one for each feature name + if _, ok := columnNameToProtoValueArray[featureName]; !ok { + columnNameToProtoValueArray[featureName] = make([]*types.Value, 0) + columnNameToStatus[featureName] = make([]int32, 0) + columnNameToTimestamp[featureName] = make([]int64, 0) + } + columnNameToProtoValueArray[featureName] = append(columnNameToProtoValueArray[featureName], l.FeatureValues[idx]) + columnNameToStatus[featureName] = append(columnNameToStatus[featureName], int32(l.FeatureStatuses[idx])) + columnNameToTimestamp[featureName] = append(columnNameToTimestamp[featureName], l.EventTimestamps[idx].AsTime().UnixNano()/int64(time.Millisecond)) + } + strBuilder.Append(l.RequestId) + } + + fields := make([]arrow.Field, 0) + columns := make([]array.Interface, 0) + for _, entityName := range fcoSchema.Entities { + protoArr := entityNameToEntityValues[entityName] + if len(protoArr) == 0 { + break + } + valArrowArray, err := gotypes.ProtoValuesToArrowArray(protoArr, arrowMemory, len(columnNameToProtoValueArray)) + if err != nil { + return nil, err + } + arrowType, err := gotypes.ValueTypeEnumToArrowType(fcoSchema.EntityTypes[entityName]) + if err != nil { + return nil, err + } + fields = append(fields, arrow.Field{ + Name: entityName, + Type: arrowType, + }) + columns = append(columns, valArrowArray) + } + + for _, featureName := range fcoSchema.Features { + + protoArr := columnNameToProtoValueArray[featureName] + if len(protoArr) == 0 { + break + } + arrowArray, err := gotypes.ProtoValuesToArrowArray(protoArr, arrowMemory, len(columnNameToProtoValueArray)) + if err != nil { + return nil, err + } + + arrowType, err := gotypes.ValueTypeEnumToArrowType(fcoSchema.FeaturesTypes[featureName]) + + if err != nil { + return nil, err + } + fields = append(fields, arrow.Field{ + Name: featureName, + Type: arrowType, + }) + columns = append(columns, arrowArray) + } + fields = append(fields, arrow.Field{ + Name: "RequestId", + Type: &arrow.StringType{}, + }) + + columns = append(columns, strBuilder.NewArray()) + schema := arrow.NewSchema( + fields, + nil, + ) + + result := array.Record(array.NewRecord(schema, columns, int64(len(memoryBuffer.logs)))) + + tbl := array.NewTableFromRecords(schema, []array.Record{result}) + return array.Table(tbl), nil +} + +type Schema struct { + Entities []string + Features []string + EntityTypes map[string]types.ValueType_Enum + FeaturesTypes map[string]types.ValueType_Enum +} + +func GetSchemaFromFeatureService(featureService *model.FeatureService, entityMap map[string]*model.Entity, featureViews []*model.FeatureView, onDemandFeatureViews []*model.OnDemandFeatureView) (*Schema, error) { + fvs := make(map[string]*model.FeatureView) + odFvs := make(map[string]*model.OnDemandFeatureView) + + joinKeys := make([]string, 0) + // All joinkeys in the featureService are put in here + joinKeysSet := make(map[string]interface{}) + entityJoinKeyToType := make(map[string]types.ValueType_Enum) + var entities []string + for _, featureView := range featureViews { + fvs[featureView.Base.Name] = featureView + entities = featureView.Entities + } + + for _, onDemandFeatureView := range onDemandFeatureViews { + odFvs[onDemandFeatureView.Base.Name] = onDemandFeatureView + } + + allFeatureTypes := make(map[string]types.ValueType_Enum) + features := make([]string, 0) + for _, featureProjection := range featureService.Projections { + // Create copies of FeatureView that may contains the same *FeatureView but + // each differentiated by a *FeatureViewProjection + featureViewName := featureProjection.Name + if fv, ok := fvs[featureViewName]; ok { + for _, f := range featureProjection.Features { + features = append(features, GetFullFeatureName(featureViewName, f.Name)) + allFeatureTypes[GetFullFeatureName(featureViewName, f.Name)] = f.Dtype + } + for _, entityName := range fv.Entities { + entity := entityMap[entityName] + if joinKeyAlias, ok := featureProjection.JoinKeyMap[entity.JoinKey]; ok { + joinKeysSet[joinKeyAlias] = nil + } else { + joinKeysSet[entity.JoinKey] = nil + } + } + } else if _, ok := odFvs[featureViewName]; ok { + for _, f := range featureProjection.Features { + // TODO(kevjumba) check in test here. + features = append(features, GetFullFeatureName(featureViewName, f.Name)) + allFeatureTypes[GetFullFeatureName(featureViewName, f.Name)] = f.Dtype + } + } else { + return nil, fmt.Errorf("no such feature view found in feature service %s", featureViewName) + } + } + + // Only get entities in the current feature service. + for _, entity := range entities { + if _, ok := joinKeysSet[entity]; ok { + joinKeys = append(joinKeys, entityMap[entity].JoinKey) + entityJoinKeyToType[entityMap[entity].JoinKey] = entityMap[entity].ValueType + } + } + + schema := &Schema{ + Entities: joinKeys, + Features: features, + EntityTypes: entityJoinKeyToType, + FeaturesTypes: allFeatureTypes, + } + return schema, nil +} + +func GetFullFeatureName(featureViewName string, featureName string) string { + return fmt.Sprintf("%s__%s", featureViewName, featureName) +} + +func (s *LoggingService) GetFcos() (map[string]*model.Entity, []*model.FeatureView, []*model.OnDemandFeatureView, error) { + odfvs, err := s.fs.ListOnDemandFeatureViews() + if err != nil { + return nil, nil, nil, err + } + fvs, err := s.fs.ListFeatureViews() + if err != nil { + return nil, nil, nil, err + } + entities, err := s.fs.ListEntities(true) + if err != nil { + return nil, nil, nil, err + } + entityMap := make(map[string]*model.Entity) + for _, entity := range entities { + entityMap[entity.Name] = entity + } + return entityMap, fvs, odfvs, nil +} + +func (l *LoggingService) GenerateLogs(featureService *model.FeatureService, joinKeyToEntityValues map[string][]*types.Value, features []*serving.GetOnlineFeaturesResponse_FeatureVector, requestData map[string]*types.RepeatedValue, requestId string) error { + if len(features) <= 0 { + return nil + } + + entitySet, featureViews, odfvs, err := l.GetFcos() + if err != nil { + return err + } + schema, err := GetSchemaFromFeatureService(featureService, entitySet, featureViews, odfvs) + + if err != nil { + return err + } + + numFeatures := len(schema.Features) + // Should be equivalent to how many entities there are(each feature row has (entity) number of features) + numRows := len(features[0].Values) + + for row_idx := 0; row_idx < numRows; row_idx++ { + featureValueLogRow := make([]*types.Value, numFeatures) + featureStatusLogRow := make([]serving.FieldStatus, numFeatures) + eventTimestampLogRow := make([]*timestamppb.Timestamp, numFeatures) + for idx := 0; idx < len(features); idx++ { + featureValueLogRow[idx] = features[idx].Values[row_idx] + featureStatusLogRow[idx] = features[idx].Statuses[row_idx] + eventTimestampLogRow[idx] = features[idx].EventTimestamps[row_idx] + } + valuesPerEntityRow := make([]*types.Value, 0) + // ensure that the entity values are in the order that the schema defines which is the order that ListEntities returns the entities + for _, joinKey := range schema.Entities { + valuesPerEntityRow = append(valuesPerEntityRow, joinKeyToEntityValues[joinKey][row_idx]) + } + newLog := Log{ + EntityValue: valuesPerEntityRow, + FeatureValues: featureValueLogRow, + FeatureStatuses: featureStatusLogRow, + EventTimestamps: eventTimestampLogRow, + RequestId: requestId, + } + err := l.EmitLog(&newLog) + if err != nil { + return err + } + } + return nil +} diff --git a/go/cmd/server/logging/logging_test.go b/go/cmd/server/logging/logging_test.go new file mode 100644 index 00000000000..68da0bf498f --- /dev/null +++ b/go/cmd/server/logging/logging_test.go @@ -0,0 +1,402 @@ +package logging + +import ( + "math/rand" + "reflect" + "testing" + "time" + + "github.com/apache/arrow/go/v8/arrow" + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/internal/test" + "github.com/feast-dev/feast/go/protos/feast/serving" + "github.com/feast-dev/feast/go/protos/feast/types" + gotypes "github.com/feast-dev/feast/go/types" + "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestLoggingChannelTimeout(t *testing.T) { + // Pregenerated using `feast init`. + loggingService, err := NewLoggingService(nil, 1, "", false) + assert.Nil(t, err) + assert.Empty(t, loggingService.memoryBuffer.logs) + ts := timestamppb.New(time.Now()) + newLog := Log{ + FeatureStatuses: []serving.FieldStatus{serving.FieldStatus_PRESENT}, + EventTimestamps: []*timestamppb.Timestamp{ts, ts}, + } + loggingService.EmitLog(&newLog) + newTs := timestamppb.New(time.Now()) + + newLog2 := Log{ + FeatureStatuses: []serving.FieldStatus{serving.FieldStatus_PRESENT}, + EventTimestamps: []*timestamppb.Timestamp{newTs, newTs}, + } + err = loggingService.EmitLog(&newLog2) + // The channel times out and doesn't hang. + assert.NotNil(t, err) +} + +func TestSchemaTypeRetrieval(t *testing.T) { + featureService, entities, featureViews, odfvs := InitializeFeatureRepoVariablesForTest() + entityMap := make(map[string]*model.Entity) + expectedEntityNames := make([]string, 0) + expectedFeatureNames := make([]string, 0) + for _, entity := range entities { + entityMap[entity.Name] = entity + expectedEntityNames = append(expectedEntityNames, entity.Name) + } + for _, featureView := range featureViews { + for _, f := range featureView.Base.Features { + expectedFeatureNames = append(expectedFeatureNames, GetFullFeatureName(featureView.Base.Name, f.Name)) + } + } + for _, featureView := range odfvs { + for _, f := range featureView.Base.Features { + expectedFeatureNames = append(expectedFeatureNames, GetFullFeatureName(featureView.Base.Name, f.Name)) + } + } + + schema, err := GetSchemaFromFeatureService(featureService, entityMap, featureViews, odfvs) + assert.Nil(t, err) + + assert.Equal(t, expectedFeatureNames, schema.Features) + assert.Equal(t, expectedEntityNames, schema.Entities) + for _, entityName := range expectedEntityNames { + assert.Contains(t, schema.EntityTypes, entityName) + } + assert.True(t, reflect.DeepEqual(schema.EntityTypes["driver_id"], types.ValueType_INT64)) + + types := []types.ValueType_Enum{*types.ValueType_INT64.Enum(), *types.ValueType_FLOAT.Enum(), *types.ValueType_INT32.Enum(), *types.ValueType_DOUBLE.Enum(), *types.ValueType_INT32.Enum(), *types.ValueType_DOUBLE.Enum()} + for idx, featureName := range expectedFeatureNames { + assert.Contains(t, schema.FeaturesTypes, featureName) + assert.Equal(t, schema.FeaturesTypes[featureName], types[idx]) + } +} + +func TestSchemaRetrievalIgnoresEntitiesNotInFeatureService(t *testing.T) { + featureService, entities, featureViews, odfvs := InitializeFeatureRepoVariablesForTest() + //Remove entities in featureservice + for _, featureView := range featureViews { + featureView.Entities = []string{} + } + entityMap := make(map[string]*model.Entity) + for _, entity := range entities { + entityMap[entity.Name] = entity + } + schema, err := GetSchemaFromFeatureService(featureService, entityMap, featureViews, odfvs) + assert.Nil(t, err) + assert.Empty(t, schema.EntityTypes) +} + +func TestSchemaUsesOrderInFeatureService(t *testing.T) { + featureService, entities, featureViews, odfvs := InitializeFeatureRepoVariablesForTest() + expectedEntityNames := make([]string, 0) + expectedFeatureNames := make([]string, 0) + entityMap := make(map[string]*model.Entity) + for _, entity := range entities { + entityMap[entity.Name] = entity + } + for _, entity := range entities { + entityMap[entity.Name] = entity + expectedEntityNames = append(expectedEntityNames, entity.Name) + } + // Source of truth for order of featureNames + for _, featureView := range featureViews { + for _, f := range featureView.Base.Features { + expectedFeatureNames = append(expectedFeatureNames, GetFullFeatureName(featureView.Base.Name, f.Name)) + } + } + for _, featureView := range odfvs { + for _, f := range featureView.Base.Features { + expectedFeatureNames = append(expectedFeatureNames, GetFullFeatureName(featureView.Base.Name, f.Name)) + } + } + + rand.Seed(time.Now().UnixNano()) + // Shuffle the featureNames in incorrect order + for _, featureView := range featureViews { + rand.Shuffle(len(featureView.Base.Features), func(i, j int) { + featureView.Base.Features[i], featureView.Base.Features[j] = featureView.Base.Features[j], featureView.Base.Features[i] + }) + } + for _, featureView := range odfvs { + rand.Shuffle(len(featureView.Base.Features), func(i, j int) { + featureView.Base.Features[i], featureView.Base.Features[j] = featureView.Base.Features[j], featureView.Base.Features[i] + }) + } + + schema, err := GetSchemaFromFeatureService(featureService, entityMap, featureViews, odfvs) + assert.Nil(t, err) + + // Ensure the same results + assert.Equal(t, expectedFeatureNames, schema.Features) + assert.Equal(t, expectedEntityNames, schema.Entities) + for _, entityName := range expectedEntityNames { + assert.Contains(t, schema.EntityTypes, entityName) + } + assert.True(t, reflect.DeepEqual(schema.EntityTypes["driver_id"], types.ValueType_INT64)) + + types := []types.ValueType_Enum{*types.ValueType_INT64.Enum(), *types.ValueType_FLOAT.Enum(), *types.ValueType_INT32.Enum(), *types.ValueType_DOUBLE.Enum(), *types.ValueType_INT32.Enum(), *types.ValueType_DOUBLE.Enum()} + for idx, featureName := range expectedFeatureNames { + assert.Contains(t, schema.FeaturesTypes, featureName) + assert.Equal(t, schema.FeaturesTypes[featureName], types[idx]) + } +} + +func TestSerializeToArrowTable(t *testing.T) { + table, expectedSchema, expectedColumns, err := GetTestArrowTableAndExpectedResults() + assert.Nil(t, err) + defer table.Release() + tr := array.NewTableReader(table, -1) + + defer tr.Release() + for tr.Next() { + rec := tr.Record() + assert.NotNil(t, rec) + for _, field := range rec.Schema().Fields() { + assert.Contains(t, expectedSchema, field.Name) + assert.Equal(t, field.Type, expectedSchema[field.Name]) + } + values, err := test.GetProtoFromRecord(rec) + + assert.Nil(t, err) + for name, val := range values { + if name == "RequestId" { + continue + } + assert.Equal(t, len(val.Val), len(expectedColumns[name].Val)) + for idx, featureVal := range val.Val { + assert.Equal(t, featureVal.Val, expectedColumns[name].Val[idx].Val) + } + } + } +} + +// Initialize all dummy featureservice, entities and featureviews/on demand featureviews for testing. +func InitializeFeatureRepoVariablesForTest() (*model.FeatureService, []*model.Entity, []*model.FeatureView, []*model.OnDemandFeatureView) { + f1 := test.CreateNewFeature( + "int64", + types.ValueType_INT64, + ) + f2 := test.CreateNewFeature( + "float32", + types.ValueType_FLOAT, + ) + projection1 := test.CreateNewFeatureViewProjection( + "featureView1", + "", + []*model.Feature{f1, f2}, + map[string]string{}, + ) + baseFeatureView1 := test.CreateBaseFeatureView( + "featureView1", + []*model.Feature{f1, f2}, + projection1, + ) + featureView1 := test.CreateFeatureView(baseFeatureView1, nil, []string{"driver_id"}) + entity1 := test.CreateNewEntity("driver_id", types.ValueType_INT64, "driver_id") + f3 := test.CreateNewFeature( + "int32", + types.ValueType_INT32, + ) + f4 := test.CreateNewFeature( + "double", + types.ValueType_DOUBLE, + ) + projection2 := test.CreateNewFeatureViewProjection( + "featureView2", + "", + []*model.Feature{f3, f4}, + map[string]string{}, + ) + baseFeatureView2 := test.CreateBaseFeatureView( + "featureView2", + []*model.Feature{f3, f4}, + projection2, + ) + featureView2 := test.CreateFeatureView(baseFeatureView2, nil, []string{"driver_id"}) + + f5 := test.CreateNewFeature( + "odfv_f1", + types.ValueType_INT32, + ) + f6 := test.CreateNewFeature( + "odfv_f2", + types.ValueType_DOUBLE, + ) + projection3 := test.CreateNewFeatureViewProjection( + "od_bf1", + "", + []*model.Feature{f5, f6}, + map[string]string{}, + ) + od_bf1 := test.CreateBaseFeatureView( + "od_bf1", + []*model.Feature{f5, f6}, + projection3, + ) + odfv := model.NewOnDemandFeatureViewFromBase(od_bf1) + featureService := test.CreateNewFeatureService( + "test_service", + "test_project", + nil, + nil, + []*model.FeatureViewProjection{projection1, projection2, projection3}, + ) + return featureService, []*model.Entity{entity1}, []*model.FeatureView{featureView1, featureView2}, []*model.OnDemandFeatureView{odfv} +} + +// Create dummy FeatureService, Entities, and FeatureViews add them to the logger and convert the logs to Arrow table. +// Returns arrow table, expected test schema, and expected columns. +func GetTestArrowTableAndExpectedResults() (array.Table, map[string]arrow.DataType, map[string]*types.RepeatedValue, error) { + featureService, entities, featureViews, odfvs := InitializeFeatureRepoVariablesForTest() + entityMap := make(map[string]*model.Entity) + for _, entity := range entities { + entityMap[entity.Name] = entity + } + schema, err := GetSchemaFromFeatureService(featureService, entityMap, featureViews, odfvs) + if err != nil { + return nil, nil, nil, err + } + + ts := timestamppb.New(time.Now()) + log1 := Log{ + EntityValue: []*types.Value{ + {Val: &types.Value_Int64Val{Int64Val: 1001}}, + }, + FeatureValues: []*types.Value{ + /* normal feature values */ + {Val: &types.Value_Int64Val{Int64Val: rand.Int63()}}, + {Val: &types.Value_FloatVal{FloatVal: rand.Float32()}}, + {Val: &types.Value_Int32Val{Int32Val: rand.Int31()}}, + {Val: &types.Value_DoubleVal{DoubleVal: rand.Float64()}}, + /* odfv values */ + {Val: &types.Value_Int32Val{Int32Val: rand.Int31()}}, + {Val: &types.Value_DoubleVal{DoubleVal: rand.Float64()}}, + }, + FeatureStatuses: []serving.FieldStatus{ + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + }, + EventTimestamps: []*timestamppb.Timestamp{ + ts, ts, ts, ts, ts, ts, + }, + } + log2 := Log{ + EntityValue: []*types.Value{ + {Val: &types.Value_Int64Val{Int64Val: 1003}}, + }, + FeatureValues: []*types.Value{ + /* normal feature values */ + {Val: &types.Value_Int64Val{Int64Val: rand.Int63()}}, + {Val: &types.Value_FloatVal{FloatVal: rand.Float32()}}, + {Val: &types.Value_Int32Val{Int32Val: rand.Int31()}}, + {Val: &types.Value_DoubleVal{DoubleVal: rand.Float64()}}, + /* odfv values */ + {Val: &types.Value_Int32Val{Int32Val: rand.Int31()}}, + {Val: &types.Value_DoubleVal{DoubleVal: rand.Float64()}}, + }, + FeatureStatuses: []serving.FieldStatus{ + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + serving.FieldStatus_PRESENT, + }, + EventTimestamps: []*timestamppb.Timestamp{ + ts, ts, ts, ts, ts, ts, + }, + } + + expectedSchema := make(map[string]arrow.DataType) + for joinKey, entityType := range schema.EntityTypes { + arrowType, err := gotypes.ValueTypeEnumToArrowType(entityType) + if err != nil { + return nil, nil, nil, err + } + expectedSchema[joinKey] = arrowType + } + expectedSchema["RequestId"] = arrow.BinaryTypes.String + for featureName, featureType := range schema.FeaturesTypes { + arrowType, err := gotypes.ValueTypeEnumToArrowType(featureType) + if err != nil { + return nil, nil, nil, err + } + expectedSchema[featureName] = arrowType + } + + expectedColumns := map[string]*types.RepeatedValue{ + "driver_id": { + Val: []*types.Value{ + log1.EntityValue[0], + log2.EntityValue[0]}, + }, + "featureView1__int64": { + Val: []*types.Value{ + log1.FeatureValues[0], + log2.FeatureValues[0]}, + }, + "featureView1__float32": { + Val: []*types.Value{ + log1.FeatureValues[1], + log2.FeatureValues[1]}, + }, + "featureView2__int32": { + Val: []*types.Value{ + log1.FeatureValues[2], + log2.FeatureValues[2]}, + }, + "featureView2__double": { + Val: []*types.Value{ + log1.FeatureValues[3], + log2.FeatureValues[3]}, + }, + "od_bf1__odfv_f1": { + Val: []*types.Value{ + log1.FeatureValues[4], + log2.FeatureValues[4]}, + }, + "od_bf1__odfv_f2": { + Val: []*types.Value{ + log1.FeatureValues[5], + log2.FeatureValues[5]}, + }, + } + loggingService, err := SetupLoggingServiceWithLogs([]*Log{&log1, &log2}) + if err != nil { + return nil, nil, nil, err + } + + table, err := ConvertMemoryBufferToArrowTable(loggingService.memoryBuffer, schema) + + if err != nil { + return nil, nil, nil, err + } + return table, expectedSchema, expectedColumns, nil +} + +func SetupLoggingServiceWithLogs(logs []*Log) (*LoggingService, error) { + loggingService, err := NewLoggingService(nil, len(logs), "", false) + if err != nil { + return nil, err + } + dummyTicker := time.NewTicker(10 * time.Second) + // stop the ticker so that the logs are not flushed to offline storage + dummyTicker.Stop() + for _, log := range logs { + loggingService.EmitLog(log) + } + // manually handle flushing logs + for i := 0; i < len(logs); i++ { + loggingService.PerformPeriodicAppendToMemoryBufferAndLogFlush(dummyTicker) + } + return loggingService, nil +} diff --git a/go/cmd/server/logging/offlinelogstorage.go b/go/cmd/server/logging/offlinelogstorage.go new file mode 100644 index 00000000000..1a0f4142554 --- /dev/null +++ b/go/cmd/server/logging/offlinelogstorage.go @@ -0,0 +1,46 @@ +package logging + +import ( + "errors" + + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/feast-dev/feast/go/internal/feast/registry" +) + +type OfflineLogStoreConfig struct { + storeType string + project string + path string +} + +type OfflineLogStorage interface { + // Todo: Maybe we can add a must implement function that retrieves the correct config based on type + FlushToStorage(array.Table) error +} + +func getOfflineStoreType(offlineStoreConfig map[string]interface{}) (string, bool) { + if onlineStoreType, ok := offlineStoreConfig["storeType"]; !ok { + // Assume file for case of no specified. + return "", true + } else { + result, ok := onlineStoreType.(string) + return result, ok + } +} + +func NewOfflineStore(config *registry.RepoConfig) (OfflineLogStorage, error) { + offlineStoreType, _ := getOfflineStoreType(config.OfflineStore) + if offlineStoreType == "" { + // No offline store specified. + return nil, nil + } else if offlineStoreType == "file" { + fileConfig, err := GetFileConfig(config) + if err != nil { + return nil, err + } + offlineStore, err := NewFileOfflineStore(config.Project, fileConfig) + return offlineStore, err + } else { + return nil, errors.New("no offline storage besides file is currently supported") + } +} diff --git a/go/cmd/server/main.go b/go/cmd/server/main.go new file mode 100644 index 00000000000..33d56e0a7a2 --- /dev/null +++ b/go/cmd/server/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "fmt" + "log" + "net" + "os" + + "github.com/feast-dev/feast/go/cmd/server/logging" + "github.com/feast-dev/feast/go/internal/feast" + "github.com/feast-dev/feast/go/internal/feast/registry" + "github.com/feast-dev/feast/go/protos/feast/serving" + "google.golang.org/grpc" +) + +const ( + flagFeastRepoPath = "FEAST_REPO_PATH" + flagFeastRepoConfig = "FEAST_REPO_CONFIG" + flagFeastSockFile = "FEAST_GRPC_SOCK_FILE" + feastServerVersion = "0.18.0" +) + +// TODO: Add a proper logging library such as https://github.com/Sirupsen/logrus +func main() { + repoPath := os.Getenv(flagFeastRepoPath) + repoConfigJSON := os.Getenv(flagFeastRepoConfig) + sockFile := os.Getenv(flagFeastSockFile) + if repoPath == "" && repoConfigJSON == "" { + log.Fatalln(fmt.Sprintf("One of %s of %s environment variables must be set", flagFeastRepoPath, flagFeastRepoConfig)) + } + + var repoConfig *registry.RepoConfig + var err error + if repoConfigJSON != "" { + repoConfig, err = registry.NewRepoConfigFromJSON(repoPath, repoConfigJSON) + if err != nil { + log.Fatalln(err) + } + } else { + repoConfig, err = registry.NewRepoConfigFromFile(repoPath) + if err != nil { + log.Fatalln(err) + } + } + + log.Println("Initializing feature store...") + fs, err := feast.NewFeatureStore(repoConfig, nil) + if err != nil { + log.Fatalln(err) + } + // Disable logging for now + loggingService, err := logging.NewLoggingService(fs, 1000, "", false) + if err != nil { + log.Fatalln(err) + } + defer fs.DestructOnlineStore() + startGrpcServer(fs, loggingService, sockFile) +} + +func startGrpcServer(fs *feast.FeatureStore, loggingService *logging.LoggingService, sockFile string) { + server := newServingServiceServer(fs, loggingService) + log.Printf("Starting a gRPC server listening on %s\n", sockFile) + lis, err := net.Listen("unix", sockFile) + if err != nil { + log.Fatalln(err) + } + grpcServer := grpc.NewServer() + defer grpcServer.Stop() + serving.RegisterServingServiceServer(grpcServer, server) + err = grpcServer.Serve(lis) + if err != nil { + log.Fatalln(err) + } +} diff --git a/go/cmd/server/server.go b/go/cmd/server/server.go new file mode 100644 index 00000000000..3708689268b --- /dev/null +++ b/go/cmd/server/server.go @@ -0,0 +1,86 @@ +package main + +import ( + "context" + + "github.com/feast-dev/feast/go/cmd/server/logging" + "github.com/feast-dev/feast/go/internal/feast" + "github.com/feast-dev/feast/go/protos/feast/serving" + prototypes "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/feast-dev/feast/go/types" + "github.com/google/uuid" +) + +type servingServiceServer struct { + fs *feast.FeatureStore + loggingService *logging.LoggingService + serving.UnimplementedServingServiceServer +} + +func newServingServiceServer(fs *feast.FeatureStore, loggingService *logging.LoggingService) *servingServiceServer { + return &servingServiceServer{fs: fs, loggingService: loggingService} +} + +func (s *servingServiceServer) GetFeastServingInfo(ctx context.Context, request *serving.GetFeastServingInfoRequest) (*serving.GetFeastServingInfoResponse, error) { + return &serving.GetFeastServingInfoResponse{ + Version: feastServerVersion, + }, nil +} + +// Returns an object containing the response to GetOnlineFeatures. +// Metadata contains featurenames that corresponds to the number of rows in response.Results. +// Results contains values including the value of the feature, the event timestamp, and feature status in a columnar format. +func (s *servingServiceServer) GetOnlineFeatures(ctx context.Context, request *serving.GetOnlineFeaturesRequest) (*serving.GetOnlineFeaturesResponse, error) { + requestId := GenerateRequestId() + featuresOrService, err := s.fs.ParseFeatures(request.GetKind()) + if err != nil { + return nil, err + } + featureVectors, err := s.fs.GetOnlineFeatures( + ctx, + featuresOrService.FeaturesRefs, + featuresOrService.FeatureService, + request.GetEntities(), + request.GetRequestContext(), + request.GetFullFeatureNames()) + if err != nil { + return nil, err + } + + resp := &serving.GetOnlineFeaturesResponse{ + Results: make([]*serving.GetOnlineFeaturesResponse_FeatureVector, 0), + Metadata: &serving.GetOnlineFeaturesResponseMetadata{ + FeatureNames: &serving.FeatureList{Val: make([]string, 0)}, + }, + } + // Entities are currently part of the features as a value and the order that we add it to the resp MetaData + // Need to figure out a way to map the correct entities to the correct ordering + entityValuesMap := make(map[string][]*prototypes.Value, 0) + featureNames := make([]string, len(featureVectors)) + for idx, vector := range featureVectors { + resp.Metadata.FeatureNames.Val = append(resp.Metadata.FeatureNames.Val, vector.Name) + featureNames[idx] = vector.Name + values, err := types.ArrowValuesToProtoValues(vector.Values) + if err != nil { + return nil, err + } + if _, ok := request.Entities[vector.Name]; ok { + entityValuesMap[vector.Name] = values + } + + resp.Results = append(resp.Results, &serving.GetOnlineFeaturesResponse_FeatureVector{ + Values: values, + Statuses: vector.Statuses, + EventTimestamps: vector.Timestamps, + }) + } + if featuresOrService.FeatureService != nil { + go s.loggingService.GenerateLogs(featuresOrService.FeatureService, entityValuesMap, resp.Results[len(request.Entities):], request.RequestContext, requestId) + } + return resp, nil +} + +func GenerateRequestId() string { + id := uuid.New() + return id.String() +} diff --git a/go/cmd/server/server_test.go b/go/cmd/server/server_test.go new file mode 100644 index 00000000000..9d4ffb50bf8 --- /dev/null +++ b/go/cmd/server/server_test.go @@ -0,0 +1,279 @@ +package main + +import ( + "context" + "net" + "os" + "path/filepath" + "reflect" + "runtime" + "testing" + "time" + + "github.com/feast-dev/feast/go/internal/feast/registry" + + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/apache/arrow/go/v8/parquet/file" + "github.com/apache/arrow/go/v8/parquet/pqarrow" + "github.com/feast-dev/feast/go/cmd/server/logging" + "github.com/feast-dev/feast/go/internal/feast" + "github.com/feast-dev/feast/go/internal/test" + "github.com/feast-dev/feast/go/protos/feast/serving" + "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/stretchr/testify/assert" + "google.golang.org/grpc" + "google.golang.org/grpc/test/bufconn" +) + +// Return absolute path to the test_repo directory regardless of the working directory +func getRepoPath(basePath string) string { + // Get the file path of this source file, regardless of the working directory + if basePath == "" { + _, filename, _, ok := runtime.Caller(0) + if !ok { + panic("couldn't find file path of the test file") + } + return filepath.Join(filename, "..", "..", "feature_repo") + } else { + return filepath.Join(basePath, "feature_repo") + } +} + +// Starts a new grpc server, registers the serving service and returns a client. +func getClient(ctx context.Context, offlineStoreType string, basePath string, enableLogging bool) (serving.ServingServiceClient, func()) { + buffer := 1024 * 1024 + listener := bufconn.Listen(buffer) + + server := grpc.NewServer() + config, err := registry.NewRepoConfigFromFile(getRepoPath(basePath)) + + // TODO(kevjumba): either add this officially or talk in design review about what the correct solution for what do with path. + // Currently in python we use the path in FileSource but it is not specified in configuration unless it is using file_url? + if enableLogging { + if config.OfflineStore == nil { + config.OfflineStore = map[string]interface{}{} + } + absPath, err := filepath.Abs(filepath.Join(getRepoPath(basePath), "log.parquet")) + if err != nil { + panic(err) + } + config.OfflineStore["path"] = absPath + config.OfflineStore["storeType"] = offlineStoreType + } + + if err != nil { + panic(err) + } + fs, err := feast.NewFeatureStore(config, nil) + if err != nil { + panic(err) + } + loggingService, err := logging.NewLoggingService(fs, 1000, "test_service", enableLogging) + if err != nil { + panic(err) + } + servingServiceServer := newServingServiceServer(fs, loggingService) + + serving.RegisterServingServiceServer(server, servingServiceServer) + go func() { + if err := server.Serve(listener); err != nil { + panic(err) + } + }() + + conn, _ := grpc.DialContext(ctx, "", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { + return listener.Dial() + }), grpc.WithInsecure()) + + closer := func() { + listener.Close() + server.Stop() + } + + client := serving.NewServingServiceClient(conn) + + return client, closer +} + +func TestGetFeastServingInfo(t *testing.T) { + ctx := context.Background() + // Pregenerated using `feast init`. + dir := "logging/" + err := test.SetupInitializedRepo(dir) + assert.Nil(t, err) + defer test.CleanUpInitializedRepo(dir) + + client, closer := getClient(ctx, "", dir, false) + defer closer() + response, err := client.GetFeastServingInfo(ctx, &serving.GetFeastServingInfoRequest{}) + assert.Nil(t, err) + assert.Equal(t, feastServerVersion, response.Version) +} + +func TestGetOnlineFeaturesSqlite(t *testing.T) { + ctx := context.Background() + // Pregenerated using `feast init`. + dir := "logging/" + err := test.SetupInitializedRepo(dir) + assert.Nil(t, err) + defer test.CleanUpInitializedRepo(dir) + + client, closer := getClient(ctx, "", dir, false) + defer closer() + entities := make(map[string]*types.RepeatedValue) + entities["driver_id"] = &types.RepeatedValue{ + Val: []*types.Value{ + {Val: &types.Value_Int64Val{Int64Val: 1001}}, + {Val: &types.Value_Int64Val{Int64Val: 1003}}, + {Val: &types.Value_Int64Val{Int64Val: 1005}}, + }, + } + request := &serving.GetOnlineFeaturesRequest{ + Kind: &serving.GetOnlineFeaturesRequest_Features{ + Features: &serving.FeatureList{ + Val: []string{"driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate", "driver_hourly_stats:avg_daily_trips"}, + }, + }, + Entities: entities, + } + response, err := client.GetOnlineFeatures(ctx, request) + assert.Nil(t, err) + assert.NotNil(t, response) + expectedEntityValuesResp := []*types.Value{ + {Val: &types.Value_Int64Val{Int64Val: 1001}}, + {Val: &types.Value_Int64Val{Int64Val: 1003}}, + {Val: &types.Value_Int64Val{Int64Val: 1005}}, + } + expectedFeatureNamesResp := []string{"driver_id", "conv_rate", "acc_rate", "avg_daily_trips"} + rows, err := test.ReadParquet(filepath.Join(dir, "feature_repo", "driver_stats.parquet")) + assert.Nil(t, err) + entityKeys := map[int64]bool{1001: true, 1003: true, 1005: true} + correctFeatures := test.GetLatestFeatures(rows, entityKeys) + expectedConvRateValues := []*types.Value{} + expectedAccRateValues := []*types.Value{} + expectedAvgDailyTripsValues := []*types.Value{} + + for _, key := range []int64{1001, 1003, 1005} { + expectedConvRateValues = append(expectedConvRateValues, &types.Value{Val: &types.Value_FloatVal{FloatVal: correctFeatures[key].ConvRate}}) + expectedAccRateValues = append(expectedAccRateValues, &types.Value{Val: &types.Value_FloatVal{FloatVal: correctFeatures[key].AccRate}}) + expectedAvgDailyTripsValues = append(expectedAvgDailyTripsValues, &types.Value{Val: &types.Value_Int64Val{Int64Val: int64(correctFeatures[key].AvgDailyTrips)}}) + } + // Columnar so get in column format row by row should have column names of all features + assert.Equal(t, len(response.Results), 4) + + assert.True(t, reflect.DeepEqual(response.Results[0].Values, expectedEntityValuesResp)) + assert.True(t, reflect.DeepEqual(response.Results[1].Values, expectedConvRateValues)) + assert.True(t, reflect.DeepEqual(response.Results[2].Values, expectedAccRateValues)) + assert.True(t, reflect.DeepEqual(response.Results[3].Values, expectedAvgDailyTripsValues)) + + assert.True(t, reflect.DeepEqual(response.Metadata.FeatureNames.Val, expectedFeatureNamesResp)) +} + +func TestGetOnlineFeaturesSqliteWithLogging(t *testing.T) { + ctx := context.Background() + // Pregenerated using `feast init`. + dir := "logging/" + err := test.SetupInitializedRepo(dir) + assert.Nil(t, err) + defer test.CleanUpInitializedRepo(dir) + + client, closer := getClient(ctx, "file", dir, true) + defer closer() + entities := make(map[string]*types.RepeatedValue) + entities["driver_id"] = &types.RepeatedValue{ + Val: []*types.Value{ + {Val: &types.Value_Int64Val{Int64Val: 1001}}, + {Val: &types.Value_Int64Val{Int64Val: 1003}}, + {Val: &types.Value_Int64Val{Int64Val: 1005}}, + }, + } + + request := &serving.GetOnlineFeaturesRequest{ + Kind: &serving.GetOnlineFeaturesRequest_FeatureService{ + FeatureService: "test_service", + }, + Entities: entities, + FullFeatureNames: true, + } + response, err := client.GetOnlineFeatures(ctx, request) + + assert.Nil(t, err) + assert.NotNil(t, response) + + // Get the featurenames without the entity names that are appended at the front. + featureNames := response.Metadata.FeatureNames.Val[len(request.Entities):] + // Generated expected log rows and values + // TODO(kevjumba): implement for timestamp and status + expectedLogValues, _, _ := GetExpectedLogRows(featureNames, response.Results[len(request.Entities):]) + expectedLogValues["driver_id"] = entities["driver_id"] + logPath, err := filepath.Abs(filepath.Join(dir, "feature_repo", "log.parquet")) + // Wait for logger to flush. + assert.Eventually(t, func() bool { + var _, err = os.Stat(logPath) + if os.IsNotExist(err) { + return false + } else { + return true + } + }, 1*time.Second, logging.DEFAULT_LOG_FLUSH_INTERVAL) + assert.Nil(t, err) + pf, err := file.OpenParquetFile(logPath, false) + assert.Nil(t, err) + + reader, err := pqarrow.NewFileReader(pf, pqarrow.ArrowReadProperties{}, memory.DefaultAllocator) + assert.Nil(t, err) + + tbl, err := reader.ReadTable(ctx) + assert.Nil(t, err) + tr := array.NewTableReader(tbl, -1) + defer tbl.Release() + defer tr.Release() + for tr.Next() { + rec := tr.Record() + assert.NotNil(t, rec) + values, err := test.GetProtoFromRecord(rec) + + assert.Nil(t, err) + assert.Equal(t, len(values)-1 /*request id column not counted*/, len(expectedLogValues)) + // Need to iterate through and compare because certain values in types.RepeatedValues aren't accurately being compared. + for name, val := range values { + if name == "RequestId" { + // Ensure there are request ids for each entity. + assert.Equal(t, len(val.Val), len(response.Results[0].Values)) + } else { + assert.Equal(t, len(val.Val), len(expectedLogValues[name].Val)) + for idx, featureVal := range val.Val { + assert.Equal(t, featureVal.Val, expectedLogValues[name].Val[idx].Val) + } + } + + } + } + err = test.CleanUpFile(logPath) + assert.Nil(t, err) +} + +// Generate the expected log rows based on the resulting feature vector returned from GetOnlineFeatures. +func GetExpectedLogRows(featureNames []string, results []*serving.GetOnlineFeaturesResponse_FeatureVector) (map[string]*types.RepeatedValue, [][]int32, [][]int64) { + numFeatures := len(featureNames) + numRows := len(results[0].Values) + featureValueLogRows := make(map[string]*types.RepeatedValue) + featureStatusLogRows := make([][]int32, numRows) + eventTimestampLogRows := make([][]int64, numRows) + for idx := 0; idx < len(results); idx++ { + valArray := make([]*types.Value, 0) + for row_idx := 0; row_idx < numRows; row_idx++ { + featureStatusLogRows[row_idx] = make([]int32, numFeatures) + eventTimestampLogRows[row_idx] = make([]int64, numFeatures) + valArray = append(valArray, results[idx].Values[row_idx]) + featureStatusLogRows[row_idx][idx] = int32(serving.FieldStatus_PRESENT) + eventTimestampLogRows[row_idx][idx] = results[idx].EventTimestamps[row_idx].AsTime().UnixNano() / int64(time.Millisecond) + + } + featureValueLogRows[featureNames[idx]] = &types.RepeatedValue{ + Val: valArray, + } + } + return featureValueLogRows, featureStatusLogRows, eventTimestampLogRows +} diff --git a/go/embedded/online_features.go b/go/embedded/online_features.go new file mode 100644 index 00000000000..24a54894306 --- /dev/null +++ b/go/embedded/online_features.go @@ -0,0 +1,227 @@ +package embedded + +import ( + "context" + "fmt" + "log" + + "github.com/apache/arrow/go/v8/arrow" + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/apache/arrow/go/v8/arrow/cdata" + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/feast-dev/feast/go/internal/feast" + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/internal/feast/onlineserving" + "github.com/feast-dev/feast/go/internal/feast/registry" + "github.com/feast-dev/feast/go/internal/feast/transformation" + prototypes "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/feast-dev/feast/go/types" +) + +type OnlineFeatureService struct { + fs *feast.FeatureStore +} + +type OnlineFeatureServiceConfig struct { + RepoPath string + RepoConfig string +} + +type DataTable struct { + DataPtr uintptr + SchemaPtr uintptr +} + +func NewOnlineFeatureService(conf *OnlineFeatureServiceConfig, transformationCallback transformation.TransformationCallback) *OnlineFeatureService { + repoConfig, err := registry.NewRepoConfigFromJSON(conf.RepoPath, conf.RepoConfig) + if err != nil { + log.Fatalln(err) + } + + fs, err := feast.NewFeatureStore(repoConfig, transformationCallback) + if err != nil { + log.Fatalln(err) + } + + return &OnlineFeatureService{fs: fs} +} + +func (s *OnlineFeatureService) GetEntityTypesMap(featureRefs []string) (map[string]int32, error) { + viewNames := make(map[string]interface{}) + for _, featureRef := range featureRefs { + viewName, _, err := onlineserving.ParseFeatureReference(featureRef) + if err != nil { + return nil, err + } + viewNames[viewName] = nil + } + + entities, _ := s.fs.ListEntities(true) + entitiesByName := make(map[string]*model.Entity) + for _, entity := range entities { + entitiesByName[entity.Name] = entity + } + + joinKeyTypes := make(map[string]int32) + + for viewName := range viewNames { + view, err := s.fs.GetFeatureView(viewName, true) + if err != nil { + // skip on demand feature views + continue + } + for _, entityName := range view.Entities { + entity := entitiesByName[entityName] + joinKeyTypes[entity.JoinKey] = int32(entity.ValueType.Number()) + } + } + + return joinKeyTypes, nil +} + +func (s *OnlineFeatureService) GetEntityTypesMapByFeatureService(featureServiceName string) (map[string]int32, error) { + featureService, err := s.fs.GetFeatureService(featureServiceName) + if err != nil { + return nil, err + } + + joinKeyTypes := make(map[string]int32) + + entities, _ := s.fs.ListEntities(true) + entitiesByName := make(map[string]*model.Entity) + for _, entity := range entities { + entitiesByName[entity.Name] = entity + } + + for _, projection := range featureService.Projections { + view, err := s.fs.GetFeatureView(projection.Name, true) + if err != nil { + // skip on demand feature views + continue + } + for _, entityName := range view.Entities { + entity := entitiesByName[entityName] + joinKeyTypes[entity.JoinKey] = int32(entity.ValueType.Number()) + } + } + + return joinKeyTypes, nil +} + +func (s *OnlineFeatureService) GetOnlineFeatures( + featureRefs []string, + featureServiceName string, + entities DataTable, + requestData DataTable, + fullFeatureNames bool, + output DataTable) error { + + entitiesRecord, err := readArrowRecord(entities) + if err != nil { + return err + } + + numRows := entitiesRecord.Column(0).Len() + + entitiesProto, err := recordToProto(entitiesRecord) + if err != nil { + return err + } + + requestDataRecords, err := readArrowRecord(requestData) + if err != nil { + return err + } + + requestDataProto, err := recordToProto(requestDataRecords) + if err != nil { + return err + } + + var featureService *model.FeatureService + if featureServiceName != "" { + featureService, err = s.fs.GetFeatureService(featureServiceName) + } + + resp, err := s.fs.GetOnlineFeatures( + context.Background(), + featureRefs, + featureService, + entitiesProto, + requestDataProto, + fullFeatureNames) + + if err != nil { + return err + } + + outputFields := make([]arrow.Field, 0) + outputColumns := make([]arrow.Array, 0) + pool := memory.NewGoAllocator() + for _, featureVector := range resp { + outputFields = append(outputFields, + arrow.Field{ + Name: featureVector.Name, + Type: featureVector.Values.DataType()}) + outputFields = append(outputFields, + arrow.Field{ + Name: fmt.Sprintf("%s__status", featureVector.Name), + Type: arrow.PrimitiveTypes.Int32}) + outputFields = append(outputFields, + arrow.Field{ + Name: fmt.Sprintf("%s__timestamp", featureVector.Name), + Type: arrow.PrimitiveTypes.Int64}) + + outputColumns = append(outputColumns, featureVector.Values) + + statusColumnBuilder := array.NewInt32Builder(pool) + for _, status := range featureVector.Statuses { + statusColumnBuilder.Append(int32(status)) + } + statusColumn := statusColumnBuilder.NewArray() + outputColumns = append(outputColumns, statusColumn) + + tsColumnBuilder := array.NewInt64Builder(pool) + for _, ts := range featureVector.Timestamps { + tsColumnBuilder.Append(ts.GetSeconds()) + } + tsColumn := tsColumnBuilder.NewArray() + outputColumns = append(outputColumns, tsColumn) + } + + result := array.NewRecord(arrow.NewSchema(outputFields, nil), outputColumns, int64(numRows)) + + cdata.ExportArrowRecordBatch(result, + cdata.ArrayFromPtr(output.DataPtr), + cdata.SchemaFromPtr(output.SchemaPtr)) + + return nil +} + +/* + Read Record Batch from memory managed by Python caller. + Python part uses C ABI interface to export this record into C Data Interface, + and then it provides pointers (dataPtr & schemaPtr) to the Go part. + Here we import this data from given pointers and wrap the underlying values + into Go Arrow Interface (array.Record). + See export code here https://github.com/feast-dev/feast/blob/master/sdk/python/feast/embedded_go/online_features_service.py +*/ +func readArrowRecord(data DataTable) (array.Record, error) { + return cdata.ImportCRecordBatch( + cdata.ArrayFromPtr(data.DataPtr), + cdata.SchemaFromPtr(data.SchemaPtr)) +} + +func recordToProto(rec array.Record) (map[string]*prototypes.RepeatedValue, error) { + r := make(map[string]*prototypes.RepeatedValue) + schema := rec.Schema() + for idx, column := range rec.Columns() { + field := schema.Field(idx) + values, err := types.ArrowValuesToProtoValues(column) + if err != nil { + return nil, err + } + r[field.Name] = &prototypes.RepeatedValue{Val: values} + } + return r, nil +} diff --git a/go/internal/feast/featurestore.go b/go/internal/feast/featurestore.go new file mode 100644 index 00000000000..5e10f4978e0 --- /dev/null +++ b/go/internal/feast/featurestore.go @@ -0,0 +1,289 @@ +package feast + +import ( + "context" + "errors" + + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/internal/feast/onlineserving" + "github.com/feast-dev/feast/go/internal/feast/onlinestore" + "github.com/feast-dev/feast/go/internal/feast/registry" + "github.com/feast-dev/feast/go/internal/feast/transformation" + "github.com/feast-dev/feast/go/protos/feast/serving" + prototypes "github.com/feast-dev/feast/go/protos/feast/types" +) + +type FeatureStore struct { + config *registry.RepoConfig + registry *registry.Registry + onlineStore onlinestore.OnlineStore + transformationCallback transformation.TransformationCallback +} + +// A Features struct specifies a list of features to be retrieved from the online store. These features +// can be specified either as a list of string feature references or as a feature service. String +// feature references must have format "feature_view:feature", e.g. "customer_fv:daily_transactions". +type Features struct { + FeaturesRefs []string + FeatureService *model.FeatureService +} + +func (fs *FeatureStore) Registry() *registry.Registry { + return fs.registry +} + +func (fs *FeatureStore) GetRepoConfig() *registry.RepoConfig { + return fs.config +} + +// NewFeatureStore constructs a feature store fat client using the +// repo config (contents of feature_store.yaml converted to JSON map). +func NewFeatureStore(config *registry.RepoConfig, callback transformation.TransformationCallback) (*FeatureStore, error) { + onlineStore, err := onlinestore.NewOnlineStore(config) + if err != nil { + return nil, err + } + + registry, err := registry.NewRegistry(config.GetRegistryConfig(), config.RepoPath) + if err != nil { + return nil, err + } + registry.InitializeRegistry() + + return &FeatureStore{ + config: config, + registry: registry, + onlineStore: onlineStore, + transformationCallback: callback, + }, nil +} + +// TODO: Review all functions that use ODFV and Request FV since these have not been tested +// ToDo: Split GetOnlineFeatures interface into two: GetOnlinFeaturesByFeatureService and GetOnlineFeaturesByFeatureRefs +func (fs *FeatureStore) GetOnlineFeatures( + ctx context.Context, + featureRefs []string, + featureService *model.FeatureService, + joinKeyToEntityValues map[string]*prototypes.RepeatedValue, + requestData map[string]*prototypes.RepeatedValue, + fullFeatureNames bool) ([]*onlineserving.FeatureVector, error) { + fvs, odFvs, err := fs.listAllViews() + if err != nil { + return nil, err + } + + entities, err := fs.ListEntities(false) + if err != nil { + return nil, err + } + + var requestedFeatureViews []*onlineserving.FeatureViewAndRefs + var requestedOnDemandFeatureViews []*model.OnDemandFeatureView + if featureService != nil { + requestedFeatureViews, requestedOnDemandFeatureViews, err = + onlineserving.GetFeatureViewsToUseByService(featureService, fvs, odFvs) + } else { + requestedFeatureViews, requestedOnDemandFeatureViews, err = + onlineserving.GetFeatureViewsToUseByFeatureRefs(featureRefs, fvs, odFvs) + } + if err != nil { + return nil, err + } + + entityNameToJoinKeyMap, expectedJoinKeysSet, err := onlineserving.GetEntityMaps(requestedFeatureViews, entities) + if err != nil { + return nil, err + } + + err = onlineserving.ValidateFeatureRefs(requestedFeatureViews, fullFeatureNames) + if err != nil { + return nil, err + } + + numRows, err := onlineserving.ValidateEntityValues(joinKeyToEntityValues, requestData, expectedJoinKeysSet) + if err != nil { + return nil, err + } + + err = transformation.EnsureRequestedDataExist(requestedOnDemandFeatureViews, requestData) + if err != nil { + return nil, err + } + + result := make([]*onlineserving.FeatureVector, 0) + arrowMemory := memory.NewGoAllocator() + featureViews := make([]*model.FeatureView, len(requestedFeatureViews)) + index := 0 + for _, featuresAndView := range requestedFeatureViews { + featureViews[index] = featuresAndView.View + index += 1 + } + + entitylessCase := false + for _, featureView := range featureViews { + if featureView.HasEntity(model.DUMMY_ENTITY_NAME) { + entitylessCase = true + break + } + } + + if entitylessCase { + dummyEntityColumn := &prototypes.RepeatedValue{Val: make([]*prototypes.Value, numRows)} + for index := 0; index < numRows; index++ { + dummyEntityColumn.Val[index] = &model.DUMMY_ENTITY + } + joinKeyToEntityValues[model.DUMMY_ENTITY_ID] = dummyEntityColumn + } + + groupedRefs, err := onlineserving.GroupFeatureRefs(requestedFeatureViews, joinKeyToEntityValues, entityNameToJoinKeyMap, fullFeatureNames) + if err != nil { + return nil, err + } + + for _, groupRef := range groupedRefs { + featureData, err := fs.readFromOnlineStore(ctx, groupRef.EntityKeys, groupRef.FeatureViewNames, groupRef.FeatureNames) + if err != nil { + return nil, err + } + + vectors, err := onlineserving.TransposeFeatureRowsIntoColumns( + featureData, + groupRef, + requestedFeatureViews, + arrowMemory, + numRows, + ) + if err != nil { + return nil, err + } + result = append(result, vectors...) + } + + if fs.transformationCallback != nil { + onDemandFeatures, err := transformation.AugmentResponseWithOnDemandTransforms( + requestedOnDemandFeatureViews, + requestData, + joinKeyToEntityValues, + result, + fs.transformationCallback, + arrowMemory, + numRows, + fullFeatureNames, + ) + if err != nil { + return nil, err + } + result = append(result, onDemandFeatures...) + } + + result, err = onlineserving.KeepOnlyRequestedFeatures(result, featureRefs, featureService, fullFeatureNames) + if err != nil { + return nil, err + } + + entityColumns, err := onlineserving.EntitiesToFeatureVectors(joinKeyToEntityValues, arrowMemory, numRows) + result = append(entityColumns, result...) + return result, nil +} + +func (fs *FeatureStore) DestructOnlineStore() { + fs.onlineStore.Destruct() +} + +// ParseFeatures parses the kind field of a GetOnlineFeaturesRequest protobuf message +// and populates a Features struct with the result. +func (fs *FeatureStore) ParseFeatures(kind interface{}) (*Features, error) { + if featureList, ok := kind.(*serving.GetOnlineFeaturesRequest_Features); ok { + return &Features{FeaturesRefs: featureList.Features.GetVal(), FeatureService: nil}, nil + } + if featureServiceRequest, ok := kind.(*serving.GetOnlineFeaturesRequest_FeatureService); ok { + featureService, err := fs.registry.GetFeatureService(fs.config.Project, featureServiceRequest.FeatureService) + if err != nil { + return nil, err + } + return &Features{FeaturesRefs: nil, FeatureService: featureService}, nil + } + return nil, errors.New("cannot parse kind from GetOnlineFeaturesRequest") +} + +func (fs *FeatureStore) GetFeatureService(name string) (*model.FeatureService, error) { + return fs.registry.GetFeatureService(fs.config.Project, name) +} + +func (fs *FeatureStore) listAllViews() (map[string]*model.FeatureView, map[string]*model.OnDemandFeatureView, error) { + fvs := make(map[string]*model.FeatureView) + odFvs := make(map[string]*model.OnDemandFeatureView) + + featureViews, err := fs.ListFeatureViews() + if err != nil { + return nil, nil, err + } + for _, featureView := range featureViews { + fvs[featureView.Base.Name] = featureView + } + + onDemandFeatureViews, err := fs.registry.ListOnDemandFeatureViews(fs.config.Project) + if err != nil { + return nil, nil, err + } + for _, onDemandFeatureView := range onDemandFeatureViews { + odFvs[onDemandFeatureView.Base.Name] = onDemandFeatureView + } + return fvs, odFvs, nil +} + +func (fs *FeatureStore) ListFeatureViews() ([]*model.FeatureView, error) { + featureViews, err := fs.registry.ListFeatureViews(fs.config.Project) + if err != nil { + return featureViews, err + } + return featureViews, nil +} + +func (fs *FeatureStore) ListEntities(hideDummyEntity bool) ([]*model.Entity, error) { + + allEntities, err := fs.registry.ListEntities(fs.config.Project) + if err != nil { + return allEntities, err + } + entities := make([]*model.Entity, 0) + for _, entity := range allEntities { + if entity.Name != model.DUMMY_ENTITY_NAME || !hideDummyEntity { + entities = append(entities, entity) + } + } + return entities, nil +} + +func (fs *FeatureStore) ListOnDemandFeatureViews() ([]*model.OnDemandFeatureView, error) { + return fs.registry.ListOnDemandFeatureViews(fs.config.Project) +} + +/* +Group feature views that share the same set of join keys. For each group, we store only unique rows and save indices to retrieve those +rows for each requested feature +*/ + +func (fs *FeatureStore) GetFeatureView(featureViewName string, hideDummyEntity bool) (*model.FeatureView, error) { + fv, err := fs.registry.GetFeatureView(fs.config.Project, featureViewName) + if err != nil { + return nil, err + } + if fv.HasEntity(model.DUMMY_ENTITY_NAME) && hideDummyEntity { + fv.Entities = []string{} + } + return fv, nil +} + +func (fs *FeatureStore) readFromOnlineStore(ctx context.Context, entityRows []*prototypes.EntityKey, + requestedFeatureViewNames []string, + requestedFeatureNames []string, +) ([][]onlinestore.FeatureData, error) { + numRows := len(entityRows) + entityRowsValue := make([]*prototypes.EntityKey, numRows) + for index, entityKey := range entityRows { + entityRowsValue[index] = &prototypes.EntityKey{JoinKeys: entityKey.JoinKeys, EntityValues: entityKey.EntityValues} + } + return fs.onlineStore.OnlineRead(ctx, entityRowsValue, requestedFeatureViewNames, requestedFeatureNames) +} diff --git a/go/internal/feast/featurestore_test.go b/go/internal/feast/featurestore_test.go new file mode 100644 index 00000000000..c8f9049c4a5 --- /dev/null +++ b/go/internal/feast/featurestore_test.go @@ -0,0 +1,71 @@ +package feast + +import ( + "context" + "path/filepath" + "runtime" + "testing" + + "github.com/feast-dev/feast/go/internal/feast/onlinestore" + "github.com/feast-dev/feast/go/internal/feast/registry" + "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/stretchr/testify/assert" +) + +// Return absolute path to the test_repo registry regardless of the working directory +func getRegistryPath() map[string]interface{} { + // Get the file path of this source file, regardless of the working directory + _, filename, _, ok := runtime.Caller(0) + if !ok { + panic("couldn't find file path of the test file") + } + registry := map[string]interface{}{ + "path": filepath.Join(filename, "..", "..", "..", "feature_repo/data/registry.db"), + } + return registry +} + +func TestNewFeatureStore(t *testing.T) { + t.Skip("@todo(achals): feature_repo isn't checked in yet") + config := registry.RepoConfig{ + Project: "feature_repo", + Registry: getRegistryPath(), + Provider: "local", + OnlineStore: map[string]interface{}{ + "type": "redis", + }, + } + fs, err := NewFeatureStore(&config, nil) + assert.Nil(t, err) + assert.IsType(t, &onlinestore.RedisOnlineStore{}, fs.onlineStore) +} + +func TestGetOnlineFeaturesRedis(t *testing.T) { + t.Skip("@todo(achals): feature_repo isn't checked in yet") + config := registry.RepoConfig{ + Project: "feature_repo", + Registry: getRegistryPath(), + Provider: "local", + OnlineStore: map[string]interface{}{ + "type": "redis", + "connection_string": "localhost:6379", + }, + } + + featureNames := []string{"driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + } + entities := map[string]*types.RepeatedValue{"driver_id": {Val: []*types.Value{{Val: &types.Value_Int64Val{Int64Val: 1001}}, + {Val: &types.Value_Int64Val{Int64Val: 1002}}, + {Val: &types.Value_Int64Val{Int64Val: 1003}}}}, + } + + fs, err := NewFeatureStore(&config, nil) + assert.Nil(t, err) + ctx := context.Background() + response, err := fs.GetOnlineFeatures( + ctx, featureNames, nil, entities, map[string]*types.RepeatedValue{}, true) + assert.Nil(t, err) + assert.Len(t, response, 4) // 3 Features + 1 entity = 4 columns (feature vectors) in response +} diff --git a/go/internal/feast/model/basefeatureview.go b/go/internal/feast/model/basefeatureview.go new file mode 100644 index 00000000000..28ef7231fd5 --- /dev/null +++ b/go/internal/feast/model/basefeatureview.go @@ -0,0 +1,59 @@ +package model + +import ( + "fmt" + + "github.com/feast-dev/feast/go/protos/feast/core" +) + +type BaseFeatureView struct { + Name string + Features []*Feature + Projection *FeatureViewProjection +} + +func NewBaseFeatureView(name string, featureProtos []*core.FeatureSpecV2) *BaseFeatureView { + base := &BaseFeatureView{Name: name} + features := make([]*Feature, len(featureProtos)) + for index, featureSpecV2 := range featureProtos { + features[index] = NewFeatureFromProto(featureSpecV2) + } + base.Features = features + base.Projection = NewFeatureViewProjectionFromDefinition(base) + return base +} + +func (fv *BaseFeatureView) WithProjection(projection *FeatureViewProjection) (*BaseFeatureView, error) { + if projection.Name != fv.Name { + return nil, fmt.Errorf("the projection for the %s FeatureView cannot be applied because it differs "+ + "in Name; the projection is named %s and the Name indicates which "+ + "FeatureView the projection is for", fv.Name, projection.Name) + } + features := make(map[string]bool) + for _, feature := range fv.Features { + features[feature.Name] = true + } + for _, feature := range projection.Features { + if _, ok := features[feature.Name]; !ok { + return nil, fmt.Errorf("the projection for %s cannot be applied because it contains %s which the "+ + "FeatureView doesn't have", projection.Name, feature.Name) + } + } + return &BaseFeatureView{Name: fv.Name, Features: fv.Features, Projection: projection}, nil +} + +func (fv *BaseFeatureView) ProjectWithFeatures(featureNames []string) *FeatureViewProjection { + features := make([]*Feature, 0) + for _, feature := range fv.Features { + for _, allowedFeatureName := range featureNames { + if feature.Name == allowedFeatureName { + features = append(features, feature) + } + } + } + + return &FeatureViewProjection{ + Name: fv.Name, + Features: features, + } +} diff --git a/go/internal/feast/model/entity.go b/go/internal/feast/model/entity.go new file mode 100644 index 00000000000..ac3a5d5f26e --- /dev/null +++ b/go/internal/feast/model/entity.go @@ -0,0 +1,19 @@ +package model + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" + "github.com/feast-dev/feast/go/protos/feast/types" +) + +type Entity struct { + Name string + ValueType types.ValueType_Enum + JoinKey string +} + +func NewEntityFromProto(proto *core.Entity) *Entity { + return &Entity{Name: proto.Spec.Name, + ValueType: proto.Spec.ValueType, + JoinKey: proto.Spec.JoinKey, + } +} diff --git a/go/internal/feast/model/feature.go b/go/internal/feast/model/feature.go new file mode 100644 index 00000000000..d833a8901b5 --- /dev/null +++ b/go/internal/feast/model/feature.go @@ -0,0 +1,17 @@ +package model + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" + "github.com/feast-dev/feast/go/protos/feast/types" +) + +type Feature struct { + Name string + Dtype types.ValueType_Enum +} + +func NewFeatureFromProto(proto *core.FeatureSpecV2) *Feature { + return &Feature{Name: proto.Name, + Dtype: proto.ValueType, + } +} diff --git a/go/internal/feast/model/featureservice.go b/go/internal/feast/model/featureservice.go new file mode 100644 index 00000000000..5619dd90426 --- /dev/null +++ b/go/internal/feast/model/featureservice.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +type FeatureService struct { + Name string + Project string + CreatedTimestamp *timestamppb.Timestamp + LastUpdatedTimestamp *timestamppb.Timestamp + Projections []*FeatureViewProjection +} + +func NewFeatureServiceFromProto(proto *core.FeatureService) *FeatureService { + projections := make([]*FeatureViewProjection, len(proto.Spec.Features)) + for index, projectionProto := range proto.Spec.Features { + projections[index] = NewFeatureViewProjectionFromProto(projectionProto) + } + return &FeatureService{Name: proto.Spec.Name, + Project: proto.Spec.Project, + CreatedTimestamp: proto.Meta.CreatedTimestamp, + LastUpdatedTimestamp: proto.Meta.LastUpdatedTimestamp, + Projections: projections, + } +} diff --git a/go/internal/feast/model/featureview.go b/go/internal/feast/model/featureview.go new file mode 100644 index 00000000000..85fc7a60eeb --- /dev/null +++ b/go/internal/feast/model/featureview.go @@ -0,0 +1,51 @@ +package model + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" + "github.com/feast-dev/feast/go/protos/feast/types" + durationpb "google.golang.org/protobuf/types/known/durationpb" +) + +const ( + DUMMY_ENTITY_ID = "__dummy_id" + DUMMY_ENTITY_NAME = "__dummy" + DUMMY_ENTITY_VAL = "" +) + +var DUMMY_ENTITY types.Value = types.Value{Val: &types.Value_StringVal{StringVal: DUMMY_ENTITY_VAL}} + +type FeatureView struct { + Base *BaseFeatureView + Ttl *durationpb.Duration + Entities []string +} + +func NewFeatureViewFromProto(proto *core.FeatureView) *FeatureView { + featureView := &FeatureView{Base: NewBaseFeatureView(proto.Spec.Name, proto.Spec.Features), + Ttl: &(*proto.Spec.Ttl), + } + if len(proto.Spec.Entities) == 0 { + featureView.Entities = []string{DUMMY_ENTITY_NAME} + } else { + featureView.Entities = proto.Spec.Entities + } + return featureView +} + +func (fs *FeatureView) NewFeatureViewFromBase(base *BaseFeatureView) *FeatureView { + ttl := durationpb.Duration{Seconds: fs.Ttl.Seconds, Nanos: fs.Ttl.Nanos} + featureView := &FeatureView{Base: base, + Ttl: &ttl, + Entities: fs.Entities, + } + return featureView +} + +func (fs *FeatureView) HasEntity(lookup string) bool { + for _, entityName := range fs.Entities { + if entityName == lookup { + return true + } + } + return false +} diff --git a/go/internal/feast/model/featureviewprojection.go b/go/internal/feast/model/featureviewprojection.go new file mode 100644 index 00000000000..e80e8844ed2 --- /dev/null +++ b/go/internal/feast/model/featureviewprojection.go @@ -0,0 +1,41 @@ +package model + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" +) + +type FeatureViewProjection struct { + Name string + NameAlias string + Features []*Feature + JoinKeyMap map[string]string +} + +func (fv *FeatureViewProjection) NameToUse() string { + if len(fv.NameAlias) == 0 { + return fv.Name + } + return fv.NameAlias +} + +func NewFeatureViewProjectionFromProto(proto *core.FeatureViewProjection) *FeatureViewProjection { + featureProjection := &FeatureViewProjection{Name: proto.FeatureViewName, + NameAlias: proto.FeatureViewNameAlias, + JoinKeyMap: proto.JoinKeyMap, + } + + features := make([]*Feature, len(proto.FeatureColumns)) + for index, featureSpecV2 := range proto.FeatureColumns { + features[index] = NewFeatureFromProto(featureSpecV2) + } + featureProjection.Features = features + return featureProjection +} + +func NewFeatureViewProjectionFromDefinition(base *BaseFeatureView) *FeatureViewProjection { + return &FeatureViewProjection{Name: base.Name, + NameAlias: "", + Features: base.Features, + JoinKeyMap: make(map[string]string), + } +} diff --git a/go/internal/feast/model/ondemandfeatureview.go b/go/internal/feast/model/ondemandfeatureview.go new file mode 100644 index 00000000000..b7a352cc205 --- /dev/null +++ b/go/internal/feast/model/ondemandfeatureview.go @@ -0,0 +1,69 @@ +package model + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" + "github.com/feast-dev/feast/go/protos/feast/types" +) + +type OnDemandFeatureView struct { + Base *BaseFeatureView + SourceFeatureViewProjections map[string]*FeatureViewProjection + SourceRequestDataSources map[string]*core.DataSource_RequestDataOptions +} + +func NewOnDemandFeatureViewFromProto(proto *core.OnDemandFeatureView) *OnDemandFeatureView { + onDemandFeatureView := &OnDemandFeatureView{Base: NewBaseFeatureView(proto.Spec.Name, proto.Spec.Features), + SourceFeatureViewProjections: make(map[string]*FeatureViewProjection), + SourceRequestDataSources: make(map[string]*core.DataSource_RequestDataOptions), + } + for sourceName, onDemandSource := range proto.Spec.Sources { + if onDemandSourceFeatureView, ok := onDemandSource.Source.(*core.OnDemandSource_FeatureView); ok { + featureViewProto := onDemandSourceFeatureView.FeatureView + featureView := NewFeatureViewFromProto(featureViewProto) + onDemandFeatureView.SourceFeatureViewProjections[sourceName] = featureView.Base.Projection + } else if onDemandSourceFeatureViewProjection, ok := onDemandSource.Source.(*core.OnDemandSource_FeatureViewProjection); ok { + featureProjectionProto := onDemandSourceFeatureViewProjection.FeatureViewProjection + onDemandFeatureView.SourceFeatureViewProjections[sourceName] = NewFeatureViewProjectionFromProto(featureProjectionProto) + } else if onDemandSourceRequestFeatureView, ok := onDemandSource.Source.(*core.OnDemandSource_RequestDataSource); ok { + + if dataSourceRequestOptions, ok := onDemandSourceRequestFeatureView.RequestDataSource.Options.(*core.DataSource_RequestDataOptions_); ok { + onDemandFeatureView.SourceRequestDataSources[sourceName] = dataSourceRequestOptions.RequestDataOptions + } + } + } + + return onDemandFeatureView +} + +func (fs *OnDemandFeatureView) NewWithProjection(projection *FeatureViewProjection) (*OnDemandFeatureView, error) { + projectedBase, err := fs.Base.WithProjection(projection) + if err != nil { + return nil, err + } + featureView := &OnDemandFeatureView{ + Base: projectedBase, + SourceFeatureViewProjections: fs.SourceFeatureViewProjections, + SourceRequestDataSources: fs.SourceRequestDataSources, + } + return featureView, nil +} + +func NewOnDemandFeatureViewFromBase(base *BaseFeatureView) *OnDemandFeatureView { + + featureView := &OnDemandFeatureView{Base: base} + return featureView +} + +func (fs *OnDemandFeatureView) ProjectWithFeatures(featureNames []string) (*OnDemandFeatureView, error) { + return fs.NewWithProjection(fs.Base.ProjectWithFeatures(featureNames)) +} + +func (fs *OnDemandFeatureView) GetRequestDataSchema() map[string]types.ValueType_Enum { + schema := make(map[string]types.ValueType_Enum) + for _, requestDataSource := range fs.SourceRequestDataSources { + for _, featureSpec := range requestDataSource.Schema { + schema[featureSpec.Name] = featureSpec.ValueType + } + } + return schema +} diff --git a/go/internal/feast/onlineserving/serving.go b/go/internal/feast/onlineserving/serving.go new file mode 100644 index 00000000000..381ba5f0f2f --- /dev/null +++ b/go/internal/feast/onlineserving/serving.go @@ -0,0 +1,640 @@ +package onlineserving + +import ( + "crypto/sha256" + "errors" + "fmt" + "sort" + "strings" + + "github.com/apache/arrow/go/v8/arrow" + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/internal/feast/onlinestore" + "github.com/feast-dev/feast/go/protos/feast/serving" + prototypes "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/feast-dev/feast/go/types" + "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" +) + +/* + FeatureVector type represent result of retrieving single feature for multiple rows. + It can be imagined as a column in output dataframe / table. + It contains of feature name, list of values (across all rows), + list of statuses and list of timestamp. All these lists have equal length. + And this length is also equal to number of entity rows received in request. +*/ +type FeatureVector struct { + Name string + Values arrow.Array + Statuses []serving.FieldStatus + Timestamps []*timestamppb.Timestamp +} + +type FeatureViewAndRefs struct { + View *model.FeatureView + FeatureRefs []string +} + +/* + We group all features from a single request by entities they attached to. + Thus, we will be able to call online retrieval per entity and not per each feature View. + In this struct we collect all features and views that belongs to a group. + We also store here projected entity keys (only ones that needed to retrieve these features) + and indexes to map result of retrieval into output response. +*/ +type GroupedFeaturesPerEntitySet struct { + // A list of requested feature references of the form featureViewName:featureName that share this entity set + FeatureNames []string + FeatureViewNames []string + // full feature references as they supposed to appear in response + AliasedFeatureNames []string + // Entity set as a list of EntityKeys to pass to OnlineRead + EntityKeys []*prototypes.EntityKey + // Reversed mapping to project result of retrieval from storage to response + Indices [][]int +} + +/* + Return + (1) requested feature views and features grouped per View + (2) requested on demand feature views + existed in the registry + +*/ +func GetFeatureViewsToUseByService( + featureService *model.FeatureService, + featureViews map[string]*model.FeatureView, + onDemandFeatureViews map[string]*model.OnDemandFeatureView) ([]*FeatureViewAndRefs, []*model.OnDemandFeatureView, error) { + + viewNameToViewAndRefs := make(map[string]*FeatureViewAndRefs) + odFvsToUse := make([]*model.OnDemandFeatureView, 0) + + for _, featureProjection := range featureService.Projections { + // Create copies of FeatureView that may contains the same *FeatureView but + // each differentiated by a *FeatureViewProjection + featureViewName := featureProjection.Name + if fv, ok := featureViews[featureViewName]; ok { + base, err := fv.Base.WithProjection(featureProjection) + if err != nil { + return nil, nil, err + } + if _, ok := viewNameToViewAndRefs[featureProjection.NameToUse()]; !ok { + viewNameToViewAndRefs[featureProjection.NameToUse()] = &FeatureViewAndRefs{ + View: fv.NewFeatureViewFromBase(base), + FeatureRefs: []string{}, + } + } + + for _, feature := range featureProjection.Features { + viewNameToViewAndRefs[featureProjection.NameToUse()].FeatureRefs = + addStringIfNotContains(viewNameToViewAndRefs[featureProjection.NameToUse()].FeatureRefs, + feature.Name) + } + + } else if odFv, ok := onDemandFeatureViews[featureViewName]; ok { + projectedOdFv, err := odFv.NewWithProjection(featureProjection) + if err != nil { + return nil, nil, err + } + odFvsToUse = append(odFvsToUse, projectedOdFv) + err = extractOdFvDependencies( + projectedOdFv, + featureViews, + viewNameToViewAndRefs) + if err != nil { + return nil, nil, err + } + } else { + return nil, nil, fmt.Errorf("the provided feature service %s contains a reference to a feature View"+ + "%s which doesn't exist, please make sure that you have created the feature View"+ + "%s and that you have registered it by running \"apply\"", featureService.Name, featureViewName, featureViewName) + } + } + + fvsToUse := make([]*FeatureViewAndRefs, 0) + for _, viewAndRef := range viewNameToViewAndRefs { + fvsToUse = append(fvsToUse, viewAndRef) + } + + return fvsToUse, odFvsToUse, nil +} + +/* + Return + (1) requested feature views and features grouped per View + (2) requested on demand feature views + existed in the registry +*/ +func GetFeatureViewsToUseByFeatureRefs( + features []string, + featureViews map[string]*model.FeatureView, + onDemandFeatureViews map[string]*model.OnDemandFeatureView) ([]*FeatureViewAndRefs, []*model.OnDemandFeatureView, error) { + viewNameToViewAndRefs := make(map[string]*FeatureViewAndRefs) + odFvToFeatures := make(map[string][]string) + + for _, featureRef := range features { + featureViewName, featureName, err := ParseFeatureReference(featureRef) + if err != nil { + return nil, nil, err + } + if fv, ok := featureViews[featureViewName]; ok { + if viewAndRef, ok := viewNameToViewAndRefs[fv.Base.Name]; ok { + viewAndRef.FeatureRefs = addStringIfNotContains(viewAndRef.FeatureRefs, featureName) + } else { + viewNameToViewAndRefs[fv.Base.Name] = &FeatureViewAndRefs{ + View: fv, + FeatureRefs: []string{featureName}, + } + } + } else if odfv, ok := onDemandFeatureViews[featureViewName]; ok { + if _, ok := odFvToFeatures[odfv.Base.Name]; !ok { + odFvToFeatures[odfv.Base.Name] = []string{featureName} + } else { + odFvToFeatures[odfv.Base.Name] = append( + odFvToFeatures[odfv.Base.Name], featureName) + } + } else { + return nil, nil, fmt.Errorf("feature View %s doesn't exist, please make sure that you have created the"+ + " feature View %s and that you have registered it by running \"apply\"", featureViewName, featureViewName) + } + } + + odFvsToUse := make([]*model.OnDemandFeatureView, 0) + + for odFvName, featureNames := range odFvToFeatures { + projectedOdFv, err := onDemandFeatureViews[odFvName].ProjectWithFeatures(featureNames) + if err != nil { + return nil, nil, err + } + + err = extractOdFvDependencies( + projectedOdFv, + featureViews, + viewNameToViewAndRefs) + if err != nil { + return nil, nil, err + } + odFvsToUse = append(odFvsToUse, projectedOdFv) + } + + fvsToUse := make([]*FeatureViewAndRefs, 0) + for _, viewAndRefs := range viewNameToViewAndRefs { + fvsToUse = append(fvsToUse, viewAndRefs) + } + + return fvsToUse, odFvsToUse, nil +} + +func extractOdFvDependencies( + odFv *model.OnDemandFeatureView, + sourceFvs map[string]*model.FeatureView, + requestedFeatures map[string]*FeatureViewAndRefs, +) error { + + for _, sourceFvProjection := range odFv.SourceFeatureViewProjections { + fv := sourceFvs[sourceFvProjection.Name] + base, err := fv.Base.WithProjection(sourceFvProjection) + if err != nil { + return err + } + newFv := fv.NewFeatureViewFromBase(base) + + if _, ok := requestedFeatures[sourceFvProjection.NameToUse()]; !ok { + requestedFeatures[sourceFvProjection.NameToUse()] = &FeatureViewAndRefs{ + View: newFv, + FeatureRefs: []string{}, + } + } + + for _, feature := range sourceFvProjection.Features { + requestedFeatures[sourceFvProjection.NameToUse()].FeatureRefs = addStringIfNotContains( + requestedFeatures[sourceFvProjection.NameToUse()].FeatureRefs, feature.Name) + } + } + + return nil +} + +func addStringIfNotContains(slice []string, element string) []string { + found := false + for _, item := range slice { + if element == item { + found = true + } + } + if !found { + slice = append(slice, element) + } + return slice +} + +func GetEntityMaps(requestedFeatureViews []*FeatureViewAndRefs, entities []*model.Entity) (map[string]string, map[string]interface{}, error) { + entityNameToJoinKeyMap := make(map[string]string) + expectedJoinKeysSet := make(map[string]interface{}) + + entitiesByName := make(map[string]*model.Entity) + + for _, entity := range entities { + entitiesByName[entity.Name] = entity + } + + for _, featuresAndView := range requestedFeatureViews { + featureView := featuresAndView.View + var joinKeyToAliasMap map[string]string + if featureView.Base.Projection != nil && featureView.Base.Projection.JoinKeyMap != nil { + joinKeyToAliasMap = featureView.Base.Projection.JoinKeyMap + } else { + joinKeyToAliasMap = map[string]string{} + } + + for _, entityName := range featureView.Entities { + joinKey := entitiesByName[entityName].JoinKey + entityNameToJoinKeyMap[entityName] = joinKey + + if alias, ok := joinKeyToAliasMap[joinKey]; ok { + expectedJoinKeysSet[alias] = nil + } else { + expectedJoinKeysSet[joinKey] = nil + } + } + } + return entityNameToJoinKeyMap, expectedJoinKeysSet, nil +} + +func ValidateEntityValues(joinKeyValues map[string]*prototypes.RepeatedValue, + requestData map[string]*prototypes.RepeatedValue, + expectedJoinKeysSet map[string]interface{}) (int, error) { + numRows := -1 + + for joinKey, values := range joinKeyValues { + if _, ok := expectedJoinKeysSet[joinKey]; !ok { + requestData[joinKey] = values + delete(joinKeyValues, joinKey) + // ToDo: when request data will be passed correctly (not as part of entity rows) + // ToDo: throw this error instead + // return 0, fmt.Errorf("JoinKey is not expected in this request: %s\n%v", JoinKey, expectedJoinKeysSet) + } else { + if numRows < 0 { + numRows = len(values.Val) + } else if len(values.Val) != numRows { + return -1, errors.New("valueError: All entity rows must have the same columns") + } + + } + } + + return numRows, nil +} + +func ValidateFeatureRefs(requestedFeatures []*FeatureViewAndRefs, fullFeatureNames bool) error { + featureRefCounter := make(map[string]int) + featureRefs := make([]string, 0) + for _, viewAndFeatures := range requestedFeatures { + for _, feature := range viewAndFeatures.FeatureRefs { + projectedViewName := viewAndFeatures.View.Base.Name + if viewAndFeatures.View.Base.Projection != nil { + projectedViewName = viewAndFeatures.View.Base.Projection.NameToUse() + } + + featureRefs = append(featureRefs, + fmt.Sprintf("%s:%s", projectedViewName, feature)) + } + } + + for _, featureRef := range featureRefs { + if fullFeatureNames { + featureRefCounter[featureRef]++ + } else { + _, featureName, _ := ParseFeatureReference(featureRef) + featureRefCounter[featureName]++ + } + + } + for featureName, occurrences := range featureRefCounter { + if occurrences == 1 { + delete(featureRefCounter, featureName) + } + } + if len(featureRefCounter) >= 1 { + collidedFeatureRefs := make([]string, 0) + for collidedFeatureRef := range featureRefCounter { + if fullFeatureNames { + collidedFeatureRefs = append(collidedFeatureRefs, collidedFeatureRef) + } else { + for _, featureRef := range featureRefs { + _, featureName, _ := ParseFeatureReference(featureRef) + if featureName == collidedFeatureRef { + collidedFeatureRefs = append(collidedFeatureRefs, featureRef) + } + } + } + } + return featureNameCollisionError{collidedFeatureRefs, fullFeatureNames} + } + + return nil +} + +func TransposeFeatureRowsIntoColumns(featureData2D [][]onlinestore.FeatureData, + groupRef *GroupedFeaturesPerEntitySet, + requestedFeatureViews []*FeatureViewAndRefs, + arrowAllocator memory.Allocator, + numRows int) ([]*FeatureVector, error) { + + numFeatures := len(groupRef.AliasedFeatureNames) + fvs := make(map[string]*model.FeatureView) + for _, viewAndRefs := range requestedFeatureViews { + fvs[viewAndRefs.View.Base.Name] = viewAndRefs.View + } + + var value *prototypes.Value + var status serving.FieldStatus + var eventTimeStamp *timestamppb.Timestamp + var featureData *onlinestore.FeatureData + var fv *model.FeatureView + var featureViewName string + + vectors := make([]*FeatureVector, 0) + + for featureIndex := 0; featureIndex < numFeatures; featureIndex++ { + currentVector := &FeatureVector{ + Name: groupRef.AliasedFeatureNames[featureIndex], + Statuses: make([]serving.FieldStatus, numRows), + Timestamps: make([]*timestamppb.Timestamp, numRows), + } + vectors = append(vectors, currentVector) + protoValues := make([]*prototypes.Value, numRows) + + for rowEntityIndex, outputIndexes := range groupRef.Indices { + if featureData2D[rowEntityIndex] == nil { + value = nil + status = serving.FieldStatus_NOT_FOUND + eventTimeStamp = ×tamppb.Timestamp{} + } else { + featureData = &featureData2D[rowEntityIndex][featureIndex] + eventTimeStamp = ×tamppb.Timestamp{Seconds: featureData.Timestamp.Seconds, Nanos: featureData.Timestamp.Nanos} + featureViewName = featureData.Reference.FeatureViewName + fv = fvs[featureViewName] + if _, ok := featureData.Value.Val.(*prototypes.Value_NullVal); ok { + value = nil + status = serving.FieldStatus_NOT_FOUND + } else if checkOutsideTtl(eventTimeStamp, timestamppb.Now(), fv.Ttl) { + value = &prototypes.Value{Val: featureData.Value.Val} + status = serving.FieldStatus_OUTSIDE_MAX_AGE + } else { + value = &prototypes.Value{Val: featureData.Value.Val} + status = serving.FieldStatus_PRESENT + } + } + for _, rowIndex := range outputIndexes { + protoValues[rowIndex] = value + currentVector.Statuses[rowIndex] = status + currentVector.Timestamps[rowIndex] = eventTimeStamp + } + } + arrowValues, err := types.ProtoValuesToArrowArray(protoValues, arrowAllocator, numRows) + if err != nil { + return nil, err + } + currentVector.Values = arrowValues + } + + return vectors, nil + +} + +func KeepOnlyRequestedFeatures( + vectors []*FeatureVector, + requestedFeatureRefs []string, + featureService *model.FeatureService, + fullFeatureNames bool) ([]*FeatureVector, error) { + vectorsByName := make(map[string]*FeatureVector) + expectedVectors := make([]*FeatureVector, 0) + + for _, vector := range vectors { + vectorsByName[vector.Name] = vector + } + + if featureService != nil { + for _, projection := range featureService.Projections { + for _, f := range projection.Features { + requestedFeatureRefs = append(requestedFeatureRefs, + fmt.Sprintf("%s:%s", projection.NameToUse(), f.Name)) + } + } + } + + for _, featureRef := range requestedFeatureRefs { + viewName, featureName, err := ParseFeatureReference(featureRef) + if err != nil { + return nil, err + } + qualifiedName := getQualifiedFeatureName(viewName, featureName, fullFeatureNames) + if _, ok := vectorsByName[qualifiedName]; !ok { + return nil, fmt.Errorf("requested feature %s can't be retrieved", featureRef) + } + expectedVectors = append(expectedVectors, vectorsByName[qualifiedName]) + } + + return expectedVectors, nil +} + +func EntitiesToFeatureVectors(entityColumns map[string]*prototypes.RepeatedValue, arrowAllocator memory.Allocator, numRows int) ([]*FeatureVector, error) { + vectors := make([]*FeatureVector, 0) + presentVector := make([]serving.FieldStatus, numRows) + timestampVector := make([]*timestamppb.Timestamp, numRows) + for idx := 0; idx < numRows; idx++ { + presentVector[idx] = serving.FieldStatus_PRESENT + timestampVector[idx] = timestamppb.Now() + } + for entityName, values := range entityColumns { + arrowColumn, err := types.ProtoValuesToArrowArray(values.Val, arrowAllocator, numRows) + if err != nil { + return nil, err + } + vectors = append(vectors, &FeatureVector{ + Name: entityName, + Values: arrowColumn, + Statuses: presentVector, + Timestamps: timestampVector, + }) + } + return vectors, nil +} + +func ParseFeatureReference(featureRef string) (featureViewName, featureName string, e error) { + parsedFeatureName := strings.Split(featureRef, ":") + + if len(parsedFeatureName) == 0 { + e = errors.New("featureReference should be in the format: 'FeatureViewName:FeatureName'") + } else if len(parsedFeatureName) == 1 { + featureName = parsedFeatureName[0] + } else { + featureViewName = parsedFeatureName[0] + featureName = parsedFeatureName[1] + } + return +} + +func entityKeysToProtos(joinKeyValues map[string]*prototypes.RepeatedValue) []*prototypes.EntityKey { + keys := make([]string, len(joinKeyValues)) + index := 0 + var numRows int + for k, v := range joinKeyValues { + keys[index] = k + index += 1 + numRows = len(v.Val) + } + sort.Strings(keys) + entityKeys := make([]*prototypes.EntityKey, numRows) + numJoinKeys := len(keys) + // Construct each EntityKey object + for index = 0; index < numRows; index++ { + entityKeys[index] = &prototypes.EntityKey{JoinKeys: keys, EntityValues: make([]*prototypes.Value, numJoinKeys)} + } + + for colIndex, key := range keys { + for index, value := range joinKeyValues[key].GetVal() { + entityKeys[index].EntityValues[colIndex] = value + } + } + return entityKeys +} + +func GroupFeatureRefs(requestedFeatureViews []*FeatureViewAndRefs, + joinKeyValues map[string]*prototypes.RepeatedValue, + entityNameToJoinKeyMap map[string]string, + fullFeatureNames bool, +) (map[string]*GroupedFeaturesPerEntitySet, + error, +) { + groups := make(map[string]*GroupedFeaturesPerEntitySet) + + for _, featuresAndView := range requestedFeatureViews { + joinKeys := make([]string, 0) + fv := featuresAndView.View + featureNames := featuresAndView.FeatureRefs + for _, entityName := range fv.Entities { + joinKeys = append(joinKeys, entityNameToJoinKeyMap[entityName]) + } + + groupKeyBuilder := make([]string, 0) + joinKeysValuesProjection := make(map[string]*prototypes.RepeatedValue) + + joinKeyToAliasMap := make(map[string]string) + if fv.Base.Projection != nil && fv.Base.Projection.JoinKeyMap != nil { + joinKeyToAliasMap = fv.Base.Projection.JoinKeyMap + } + + for _, joinKey := range joinKeys { + var joinKeyOrAlias string + + if alias, ok := joinKeyToAliasMap[joinKey]; ok { + groupKeyBuilder = append(groupKeyBuilder, fmt.Sprintf("%s[%s]", joinKey, alias)) + joinKeyOrAlias = alias + } else { + groupKeyBuilder = append(groupKeyBuilder, joinKey) + joinKeyOrAlias = joinKey + } + + if _, ok := joinKeyValues[joinKeyOrAlias]; !ok { + return nil, fmt.Errorf("key %s is missing in provided entity rows", joinKey) + } + joinKeysValuesProjection[joinKey] = joinKeyValues[joinKeyOrAlias] + } + + sort.Strings(groupKeyBuilder) + groupKey := strings.Join(groupKeyBuilder, ",") + + aliasedFeatureNames := make([]string, 0) + featureViewNames := make([]string, 0) + var viewNameToUse string + if fv.Base.Projection != nil { + viewNameToUse = fv.Base.Projection.NameToUse() + } else { + viewNameToUse = fv.Base.Name + } + + for _, featureName := range featureNames { + aliasedFeatureNames = append(aliasedFeatureNames, + getQualifiedFeatureName(viewNameToUse, featureName, fullFeatureNames)) + featureViewNames = append(featureViewNames, fv.Base.Name) + } + + if _, ok := groups[groupKey]; !ok { + joinKeysProto := entityKeysToProtos(joinKeysValuesProjection) + uniqueEntityRows, mappingIndices, err := getUniqueEntityRows(joinKeysProto) + if err != nil { + return nil, err + } + + groups[groupKey] = &GroupedFeaturesPerEntitySet{ + FeatureNames: featureNames, + FeatureViewNames: featureViewNames, + AliasedFeatureNames: aliasedFeatureNames, + Indices: mappingIndices, + EntityKeys: uniqueEntityRows, + } + + } else { + groups[groupKey].FeatureNames = append(groups[groupKey].FeatureNames, featureNames...) + groups[groupKey].AliasedFeatureNames = append(groups[groupKey].AliasedFeatureNames, aliasedFeatureNames...) + groups[groupKey].FeatureViewNames = append(groups[groupKey].FeatureViewNames, featureViewNames...) + } + } + return groups, nil +} + +func getUniqueEntityRows(joinKeysProto []*prototypes.EntityKey) ([]*prototypes.EntityKey, [][]int, error) { + uniqueValues := make(map[[sha256.Size]byte]*prototypes.EntityKey, 0) + positions := make(map[[sha256.Size]byte][]int, 0) + + for index, entityKey := range joinKeysProto { + serializedRow, err := proto.Marshal(entityKey) + if err != nil { + return nil, nil, err + } + + rowHash := sha256.Sum256(serializedRow) + if _, ok := uniqueValues[rowHash]; !ok { + uniqueValues[rowHash] = entityKey + positions[rowHash] = []int{index} + } else { + positions[rowHash] = append(positions[rowHash], index) + } + } + + mappingIndices := make([][]int, len(uniqueValues)) + uniqueEntityRows := make([]*prototypes.EntityKey, 0) + for rowHash, row := range uniqueValues { + nextIdx := len(uniqueEntityRows) + + mappingIndices[nextIdx] = positions[rowHash] + uniqueEntityRows = append(uniqueEntityRows, row) + } + return uniqueEntityRows, mappingIndices, nil +} + +func checkOutsideTtl(featureTimestamp *timestamppb.Timestamp, currentTimestamp *timestamppb.Timestamp, ttl *durationpb.Duration) bool { + return currentTimestamp.GetSeconds()-featureTimestamp.GetSeconds() > ttl.Seconds +} + +func getQualifiedFeatureName(viewName string, featureName string, fullFeatureNames bool) string { + if fullFeatureNames { + return fmt.Sprintf("%s__%s", viewName, featureName) + } else { + return featureName + } +} + +type featureNameCollisionError struct { + featureRefCollisions []string + fullFeatureNames bool +} + +func (e featureNameCollisionError) Error() string { + return fmt.Sprintf("featureNameCollisionError: %s; %t", strings.Join(e.featureRefCollisions, ", "), e.fullFeatureNames) +} diff --git a/go/internal/feast/onlineserving/serving_test.go b/go/internal/feast/onlineserving/serving_test.go new file mode 100644 index 00000000000..2f4cf8eabaa --- /dev/null +++ b/go/internal/feast/onlineserving/serving_test.go @@ -0,0 +1,333 @@ +package onlineserving + +import ( + "testing" + + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/protos/feast/core" + "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestGroupingFeatureRefs(t *testing.T) { + viewA := &model.FeatureView{ + Base: &model.BaseFeatureView{ + Name: "viewA", + Projection: &model.FeatureViewProjection{ + NameAlias: "aliasViewA", + }, + }, + Entities: []string{"driver", "customer"}, + } + viewB := &model.FeatureView{ + Base: &model.BaseFeatureView{Name: "viewB"}, + Entities: []string{"driver", "customer"}, + } + viewC := &model.FeatureView{ + Base: &model.BaseFeatureView{Name: "viewC"}, + Entities: []string{"driver"}, + } + viewD := &model.FeatureView{ + Base: &model.BaseFeatureView{Name: "viewD"}, + Entities: []string{"customer"}, + } + refGroups, _ := GroupFeatureRefs( + []*FeatureViewAndRefs{ + {View: viewA, FeatureRefs: []string{"featureA", "featureB"}}, + {View: viewB, FeatureRefs: []string{"featureC", "featureD"}}, + {View: viewC, FeatureRefs: []string{"featureE"}}, + {View: viewD, FeatureRefs: []string{"featureF"}}, + }, + map[string]*types.RepeatedValue{ + "driver_id": {Val: []*types.Value{ + {Val: &types.Value_Int32Val{Int32Val: 0}}, + {Val: &types.Value_Int32Val{Int32Val: 0}}, + {Val: &types.Value_Int32Val{Int32Val: 1}}, + {Val: &types.Value_Int32Val{Int32Val: 1}}, + {Val: &types.Value_Int32Val{Int32Val: 1}}, + }}, + "customer_id": {Val: []*types.Value{ + {Val: &types.Value_Int32Val{Int32Val: 1}}, + {Val: &types.Value_Int32Val{Int32Val: 2}}, + {Val: &types.Value_Int32Val{Int32Val: 3}}, + {Val: &types.Value_Int32Val{Int32Val: 3}}, + {Val: &types.Value_Int32Val{Int32Val: 4}}, + }}, + }, + map[string]string{ + "driver": "driver_id", + "customer": "customer_id", + }, + true, + ) + + assert.Len(t, refGroups, 3) + + // Group 1 + assert.Equal(t, []string{"featureA", "featureB", "featureC", "featureD"}, + refGroups["customer_id,driver_id"].FeatureNames) + assert.Equal(t, []string{"viewA", "viewA", "viewB", "viewB"}, + refGroups["customer_id,driver_id"].FeatureViewNames) + assert.Equal(t, []string{ + "aliasViewA__featureA", "aliasViewA__featureB", + "viewB__featureC", "viewB__featureD"}, + refGroups["customer_id,driver_id"].AliasedFeatureNames) + for _, group := range [][]int{{0}, {1}, {2, 3}, {4}} { + assert.Contains(t, refGroups["customer_id,driver_id"].Indices, group) + } + + // Group2 + assert.Equal(t, []string{"featureE"}, + refGroups["driver_id"].FeatureNames) + for _, group := range [][]int{{0, 1}, {2, 3, 4}} { + assert.Contains(t, refGroups["driver_id"].Indices, group) + } + + // Group3 + assert.Equal(t, []string{"featureF"}, + refGroups["customer_id"].FeatureNames) + + for _, group := range [][]int{{0}, {1}, {2, 3}, {4}} { + assert.Contains(t, refGroups["customer_id"].Indices, group) + } + +} + +func TestGroupingFeatureRefsWithJoinKeyAliases(t *testing.T) { + viewA := &model.FeatureView{ + Base: &model.BaseFeatureView{ + Name: "viewA", + Projection: &model.FeatureViewProjection{ + Name: "viewA", + JoinKeyMap: map[string]string{"location_id": "destination_id"}, + }, + }, + Entities: []string{"location"}, + } + viewB := &model.FeatureView{ + Base: &model.BaseFeatureView{Name: "viewB"}, + Entities: []string{"location"}, + } + + refGroups, _ := GroupFeatureRefs( + []*FeatureViewAndRefs{ + {View: viewA, FeatureRefs: []string{"featureA", "featureB"}}, + {View: viewB, FeatureRefs: []string{"featureC", "featureD"}}, + }, + map[string]*types.RepeatedValue{ + "location_id": {Val: []*types.Value{ + {Val: &types.Value_Int32Val{Int32Val: 0}}, + {Val: &types.Value_Int32Val{Int32Val: 0}}, + {Val: &types.Value_Int32Val{Int32Val: 1}}, + {Val: &types.Value_Int32Val{Int32Val: 1}}, + {Val: &types.Value_Int32Val{Int32Val: 1}}, + }}, + "destination_id": {Val: []*types.Value{ + {Val: &types.Value_Int32Val{Int32Val: 1}}, + {Val: &types.Value_Int32Val{Int32Val: 2}}, + {Val: &types.Value_Int32Val{Int32Val: 3}}, + {Val: &types.Value_Int32Val{Int32Val: 3}}, + {Val: &types.Value_Int32Val{Int32Val: 4}}, + }}, + }, + map[string]string{ + "location": "location_id", + }, + true, + ) + + assert.Len(t, refGroups, 2) + + assert.Equal(t, []string{"featureA", "featureB"}, + refGroups["location_id[destination_id]"].FeatureNames) + for _, group := range [][]int{{0}, {1}, {2, 3}, {4}} { + assert.Contains(t, refGroups["location_id[destination_id]"].Indices, group) + } + + assert.Equal(t, []string{"featureC", "featureD"}, + refGroups["location_id"].FeatureNames) + for _, group := range [][]int{{0, 1}, {2, 3, 4}} { + assert.Contains(t, refGroups["location_id"].Indices, group) + } + +} + +func TestGroupingFeatureRefsWithMissingKey(t *testing.T) { + viewA := &model.FeatureView{ + Base: &model.BaseFeatureView{ + Name: "viewA", + Projection: &model.FeatureViewProjection{ + Name: "viewA", + JoinKeyMap: map[string]string{"location_id": "destination_id"}, + }, + }, + Entities: []string{"location"}, + } + + _, err := GroupFeatureRefs( + []*FeatureViewAndRefs{ + {View: viewA, FeatureRefs: []string{"featureA", "featureB"}}, + }, + map[string]*types.RepeatedValue{ + "location_id": {Val: []*types.Value{ + {Val: &types.Value_Int32Val{Int32Val: 0}}, + }}, + }, + map[string]string{ + "location": "location_id", + }, + true, + ) + assert.Errorf(t, err, "key destination_id is missing in provided entity rows") +} + +func createFeature(name string, valueType types.ValueType_Enum) *core.FeatureSpecV2 { + return &core.FeatureSpecV2{ + Name: name, + ValueType: valueType, + } +} + +func createFeatureView(name string, entities []string, features ...*core.FeatureSpecV2) *model.FeatureView { + viewProto := core.FeatureView{ + Spec: &core.FeatureViewSpec{ + Name: name, + Entities: entities, + Features: features, + Ttl: &durationpb.Duration{}, + }, + } + return model.NewFeatureViewFromProto(&viewProto) +} + +func createFeatureService(viewProjections map[string][]*core.FeatureSpecV2) *model.FeatureService { + projections := make([]*core.FeatureViewProjection, 0) + for name, features := range viewProjections { + projections = append(projections, &core.FeatureViewProjection{ + FeatureViewName: name, + FeatureColumns: features, + JoinKeyMap: map[string]string{}, + }) + } + + fsProto := core.FeatureService{ + Spec: &core.FeatureServiceSpec{ + Features: projections, + }, + Meta: &core.FeatureServiceMeta{ + LastUpdatedTimestamp: timestamppb.Now(), + CreatedTimestamp: timestamppb.Now(), + }, + } + + return model.NewFeatureServiceFromProto(&fsProto) +} + +func createOnDemandFeatureView(name string, featureSources map[string][]*core.FeatureSpecV2, features ...*core.FeatureSpecV2) *model.OnDemandFeatureView { + sources := make(map[string]*core.OnDemandSource) + for viewName, features := range featureSources { + sources[viewName] = &core.OnDemandSource{ + Source: &core.OnDemandSource_FeatureViewProjection{ + FeatureViewProjection: &core.FeatureViewProjection{ + FeatureViewName: viewName, + FeatureColumns: features, + JoinKeyMap: map[string]string{}, + }, + }, + } + } + + proto := &core.OnDemandFeatureView{ + Spec: &core.OnDemandFeatureViewSpec{ + Name: name, + Sources: sources, + Features: features, + }, + } + return model.NewOnDemandFeatureViewFromProto(proto) +} + +func TestUnpackFeatureService(t *testing.T) { + featASpec := createFeature("featA", types.ValueType_INT32) + featBSpec := createFeature("featB", types.ValueType_INT32) + featCSpec := createFeature("featC", types.ValueType_INT32) + featDSpec := createFeature("featD", types.ValueType_INT32) + featESpec := createFeature("featE", types.ValueType_FLOAT) + onDemandFeature1 := createFeature("featF", types.ValueType_FLOAT) + onDemandFeature2 := createFeature("featG", types.ValueType_FLOAT) + + viewA := createFeatureView("viewA", []string{"entity"}, featASpec, featBSpec) + viewB := createFeatureView("viewB", []string{"entity"}, featCSpec, featDSpec) + viewC := createFeatureView("viewC", []string{"entity"}, featESpec) + onDemandView := createOnDemandFeatureView( + "odfv", + map[string][]*core.FeatureSpecV2{"viewB": {featCSpec}, "viewC": {featESpec}}, + onDemandFeature1, onDemandFeature2) + + fs := createFeatureService(map[string][]*core.FeatureSpecV2{ + "viewA": {featASpec, featBSpec}, + "viewB": {featCSpec}, + "odfv": {onDemandFeature2}, + }) + + fvs, odfvs, err := GetFeatureViewsToUseByService( + fs, + map[string]*model.FeatureView{"viewA": viewA, "viewB": viewB, "viewC": viewC}, + map[string]*model.OnDemandFeatureView{"odfv": onDemandView}) + + assertCorrectUnpacking(t, fvs, odfvs, err) +} + +func assertCorrectUnpacking(t *testing.T, fvs []*FeatureViewAndRefs, odfvs []*model.OnDemandFeatureView, err error) { + assert.Nil(t, err) + assert.Len(t, fvs, 3) + assert.Len(t, odfvs, 1) + + fvsByName := make(map[string]*FeatureViewAndRefs) + for _, fv := range fvs { + fvsByName[fv.View.Base.Name] = fv + } + + // feature views and features as declared in service + assert.Equal(t, []string{"featA", "featB"}, fvsByName["viewA"].FeatureRefs) + assert.Equal(t, []string{"featC"}, fvsByName["viewB"].FeatureRefs) + + // dependency of the on demand feature view + assert.Equal(t, []string{"featE"}, fvsByName["viewC"].FeatureRefs) + + // only requested features projected + assert.Len(t, odfvs[0].Base.Projection.Features, 1) + assert.Equal(t, "featG", odfvs[0].Base.Projection.Features[0].Name) +} + +func TestUnpackFeatureViewsByReferences(t *testing.T) { + featASpec := createFeature("featA", types.ValueType_INT32) + featBSpec := createFeature("featB", types.ValueType_INT32) + featCSpec := createFeature("featC", types.ValueType_INT32) + featDSpec := createFeature("featD", types.ValueType_INT32) + featESpec := createFeature("featE", types.ValueType_FLOAT) + onDemandFeature1 := createFeature("featF", types.ValueType_FLOAT) + onDemandFeature2 := createFeature("featG", types.ValueType_FLOAT) + + viewA := createFeatureView("viewA", []string{"entity"}, featASpec, featBSpec) + viewB := createFeatureView("viewB", []string{"entity"}, featCSpec, featDSpec) + viewC := createFeatureView("viewC", []string{"entity"}, featESpec) + onDemandView := createOnDemandFeatureView( + "odfv", + map[string][]*core.FeatureSpecV2{"viewB": {featCSpec}, "viewC": {featESpec}}, + onDemandFeature1, onDemandFeature2) + + fvs, odfvs, err := GetFeatureViewsToUseByFeatureRefs( + []string{ + "viewA:featA", + "viewA:featB", + "viewB:featC", + "odfv:featG", + }, + map[string]*model.FeatureView{"viewA": viewA, "viewB": viewB, "viewC": viewC}, + map[string]*model.OnDemandFeatureView{"odfv": onDemandView}) + + assertCorrectUnpacking(t, fvs, odfvs, err) +} diff --git a/go/internal/feast/onlinestore/onlinestore.go b/go/internal/feast/onlinestore/onlinestore.go new file mode 100644 index 00000000000..b4a25714808 --- /dev/null +++ b/go/internal/feast/onlinestore/onlinestore.go @@ -0,0 +1,65 @@ +package onlinestore + +import ( + "context" + "fmt" + "github.com/feast-dev/feast/go/internal/feast/registry" + + "github.com/feast-dev/feast/go/protos/feast/serving" + "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/golang/protobuf/ptypes/timestamp" +) + +type FeatureData struct { + Reference serving.FeatureReferenceV2 + Timestamp timestamp.Timestamp + Value types.Value +} + +type OnlineStore interface { + // OnlineRead reads multiple features (specified in featureReferences) for multiple + // entity keys (specified in entityKeys) and returns an array of array of features, + // where each feature contains 3 fields: + // 1. feature Reference + // 2. feature event timestamp + // 3. feature value + // The inner array will have the same size as featureReferences, + // while the outer array will have the same size as entityKeys. + + // TODO: Can we return [][]FeatureData, []timstamps, error + // instead and remove timestamp from FeatureData struct to mimic Python's code + // and reduces repeated memory storage for the same timstamp (which is stored as value and not as a pointer). + // Should each attribute in FeatureData be stored as a pointer instead since the current + // design forces value copied in OnlineRead + GetOnlineFeatures + // (array is destructed so we cannot use the same fields in each + // Feature object as pointers in GetOnlineFeaturesResponse) + // => allocate memory for each field once in OnlineRead + // and reuse them in GetOnlineFeaturesResponse? + OnlineRead(ctx context.Context, entityKeys []*types.EntityKey, featureViewNames []string, featureNames []string) ([][]FeatureData, error) + // Destruct must be call once user is done using OnlineStore + // This is to comply with the Connector since we have to close the plugin + Destruct() +} + +func getOnlineStoreType(onlineStoreConfig map[string]interface{}) (string, bool) { + if onlineStoreType, ok := onlineStoreConfig["type"]; !ok { + return "", false + } else { + result, ok := onlineStoreType.(string) + return result, ok + } +} + +func NewOnlineStore(config *registry.RepoConfig) (OnlineStore, error) { + onlineStoreType, ok := getOnlineStoreType(config.OnlineStore) + if !ok { + onlineStore, err := NewSqliteOnlineStore(config.Project, config, config.OnlineStore) + return onlineStore, err + } + if onlineStoreType == "redis" { + onlineStore, err := NewRedisOnlineStore(config.Project, config.OnlineStore) + return onlineStore, err + } else { + return nil, fmt.Errorf("%s online store type is currently not supported; only redis and sqlite are supported", onlineStoreType) + } +} diff --git a/go/internal/feast/onlinestore/redisonlinestore.go b/go/internal/feast/onlinestore/redisonlinestore.go new file mode 100644 index 00000000000..9049eae1033 --- /dev/null +++ b/go/internal/feast/onlinestore/redisonlinestore.go @@ -0,0 +1,358 @@ +package onlinestore + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "sort" + "strconv" + "strings" + + "github.com/feast-dev/feast/go/protos/feast/serving" + "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/go-redis/redis/v8" + "github.com/golang/protobuf/proto" + "github.com/spaolacci/murmur3" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +type redisType int + +const ( + redisNode redisType = 0 + redisCluster redisType = 1 +) + +type RedisOnlineStore struct { + + // Feast project name + // TODO (woop): Should we remove project as state that is tracked at the store level? + project string + + // Redis database type, either a single node server (RedisType.Redis) or a cluster (RedisType.RedisCluster) + t redisType + + // Redis client connector + client *redis.Client +} + +func NewRedisOnlineStore(project string, onlineStoreConfig map[string]interface{}) (*RedisOnlineStore, error) { + store := RedisOnlineStore{project: project} + + var address []string + var password string + var db int // Default to 0 + + // Parse redis_type and write it into conf.t + t, err := getRedisType(onlineStoreConfig) + if err != nil { + return nil, err + } + + // Parse connection_string and write it into conf.address, conf.password, and conf.ssl + redisConnJson, ok := onlineStoreConfig["connection_string"] + if !ok { + // Default to "localhost:6379" + redisConnJson = "localhost:6379" + } + if redisConnStr, ok := redisConnJson.(string); !ok { + return nil, errors.New(fmt.Sprintf("failed to convert connection_string to string: %+v", redisConnJson)) + } else { + parts := strings.Split(redisConnStr, ",") + for _, part := range parts { + if strings.Contains(part, ":") { + address = append(address, part) + } else if strings.Contains(part, "=") { + kv := strings.SplitN(part, "=", 2) + if kv[0] == "password" { + password = kv[1] + } else if kv[0] == "ssl" { + // TODO (woop): Add support for TLS/SSL + // ssl = kv[1] == "true" + } else if kv[0] == "db" { + db, err = strconv.Atoi(kv[1]) + if err != nil { + return nil, err + } + } else { + return nil, errors.New(fmt.Sprintf("unrecognized option in connection_string: %s. Must be one of 'password', 'ssl'", kv[0])) + } + } else { + return nil, errors.New(fmt.Sprintf("unable to parse a part of connection_string: %s. Must contain either ':' (addresses) or '=' (options", part)) + } + } + } + + if t == redisNode { + store.client = redis.NewClient(&redis.Options{ + Addr: address[0], + Password: password, // No password set + DB: db, + }) + } else { + return nil, errors.New("only single node Redis is supported at this time") + } + + return &store, nil +} + +func getRedisType(onlineStoreConfig map[string]interface{}) (redisType, error) { + var t redisType + + redisTypeJson, ok := onlineStoreConfig["redis_type"] + if !ok { + // Default to "redis" + redisTypeJson = "redis" + } else if redisTypeStr, ok := redisTypeJson.(string); !ok { + return -1, errors.New(fmt.Sprintf("failed to convert redis_type to string: %+v", redisTypeJson)) + } else { + if redisTypeStr == "redis" { + t = redisNode + } else if redisTypeStr == "redis_cluster" { + t = redisCluster + } else { + return -1, errors.New(fmt.Sprintf("failed to convert redis_type to enum: %s. Must be one of 'redis', 'redis_cluster'", redisTypeStr)) + } + } + return t, nil +} + +func (r *RedisOnlineStore) OnlineRead(ctx context.Context, entityKeys []*types.EntityKey, featureViewNames []string, featureNames []string) ([][]FeatureData, error) { + featureCount := len(featureNames) + index := featureCount + featureViewIndices := make(map[string]int) + indicesFeatureView := make(map[int]string) + for _, featureViewName := range featureViewNames { + if _, ok := featureViewIndices[featureViewName]; !ok { + featureViewIndices[featureViewName] = index + indicesFeatureView[index] = featureViewName + index += 1 + } + } + var hsetKeys = make([]string, index) + h := murmur3.New32() + intBuffer := h.Sum32() + byteBuffer := make([]byte, 4) + + for i := 0; i < featureCount; i++ { + h.Write([]byte(fmt.Sprintf("%s:%s", featureViewNames[i], featureNames[i]))) + intBuffer = h.Sum32() + binary.LittleEndian.PutUint32(byteBuffer, intBuffer) + hsetKeys[i] = string(byteBuffer) + h.Reset() + } + for i := featureCount; i < index; i++ { + view := indicesFeatureView[i] + tsKey := fmt.Sprintf("_ts:%s", view) + hsetKeys[i] = tsKey + featureNames = append(featureNames, tsKey) + } + + redisKeys := make([]*[]byte, len(entityKeys)) + redisKeyToEntityIndex := make(map[string]int) + for i := 0; i < len(entityKeys); i++ { + + var key, err = buildRedisKey(r.project, entityKeys[i]) + if err != nil { + return nil, err + } + redisKeys[i] = key + redisKeyToEntityIndex[string(*key)] = i + } + + // Retrieve features from Redis + // TODO: Move context object out + + results := make([][]FeatureData, len(entityKeys)) + pipe := r.client.Pipeline() + commands := map[string]*redis.SliceCmd{} + + for _, redisKey := range redisKeys { + keyString := string(*redisKey) + commands[keyString] = pipe.HMGet(ctx, keyString, hsetKeys...) + } + + _, err := pipe.Exec(ctx) + if err != nil { + return nil, err + } + + var entityIndex int + var resContainsNonNil bool + for redisKey, values := range commands { + + entityIndex = redisKeyToEntityIndex[redisKey] + resContainsNonNil = false + + results[entityIndex] = make([]FeatureData, featureCount) + res, err := values.Result() + if err != nil { + return nil, err + } + + var timeStamp timestamppb.Timestamp + + for featureIndex, resString := range res { + if featureIndex == featureCount { + break + } + + if resString == nil { + // TODO (Ly): Can there be nil result within each feature or they will all be returned as string proto of types.Value_NullVal proto? + featureName := featureNames[featureIndex] + featureViewName := featureViewNames[featureIndex] + timeStampIndex := featureViewIndices[featureViewName] + timeStampInterface := res[timeStampIndex] + if timeStampInterface != nil { + if timeStampString, ok := timeStampInterface.(string); !ok { + return nil, errors.New("error parsing value from redis") + } else { + if err := proto.Unmarshal([]byte(timeStampString), &timeStamp); err != nil { + return nil, errors.New("error converting parsed redis value to timestamppb.Timestamp") + } + } + } + + results[entityIndex][featureIndex] = FeatureData{Reference: serving.FeatureReferenceV2{FeatureViewName: featureViewName, FeatureName: featureName}, + Timestamp: timestamppb.Timestamp{Seconds: timeStamp.Seconds, Nanos: timeStamp.Nanos}, + Value: types.Value{Val: &types.Value_NullVal{NullVal: types.Null_NULL}}, + } + + } else if valueString, ok := resString.(string); !ok { + return nil, errors.New("error parsing Value from redis") + } else { + resContainsNonNil = true + var value types.Value + if err := proto.Unmarshal([]byte(valueString), &value); err != nil { + return nil, errors.New("error converting parsed redis Value to types.Value") + } else { + featureName := featureNames[featureIndex] + featureViewName := featureViewNames[featureIndex] + timeStampIndex := featureViewIndices[featureViewName] + timeStampInterface := res[timeStampIndex] + if timeStampInterface != nil { + if timeStampString, ok := timeStampInterface.(string); !ok { + return nil, errors.New("error parsing Value from redis") + } else { + if err := proto.Unmarshal([]byte(timeStampString), &timeStamp); err != nil { + return nil, errors.New("error converting parsed redis Value to timestamppb.Timestamp") + } + } + } + results[entityIndex][featureIndex] = FeatureData{Reference: serving.FeatureReferenceV2{FeatureViewName: featureViewName, FeatureName: featureName}, + Timestamp: timestamppb.Timestamp{Seconds: timeStamp.Seconds, Nanos: timeStamp.Nanos}, + Value: types.Value{Val: value.Val}, + } + } + } + } + + if !resContainsNonNil { + results[entityIndex] = nil + } + + } + + return results, nil +} + +// Dummy destruct function to conform with plugin OnlineStore interface +func (r *RedisOnlineStore) Destruct() { + +} + +func buildRedisKey(project string, entityKey *types.EntityKey) (*[]byte, error) { + serKey, err := serializeEntityKey(entityKey) + if err != nil { + return nil, err + } + fullKey := append(*serKey, []byte(project)...) + return &fullKey, nil +} + +func serializeEntityKey(entityKey *types.EntityKey) (*[]byte, error) { + // Serialize entity key to a bytestring so that it can be used as a lookup key in a hash table. + + // Ensure that we have the right amount of join keys and entity values + if len(entityKey.JoinKeys) != len(entityKey.EntityValues) { + return nil, errors.New(fmt.Sprintf("the amount of join key names and entity values don't match: %s vs %s", entityKey.JoinKeys, entityKey.EntityValues)) + } + + // Make sure that join keys are sorted so that we have consistent key building + m := make(map[string]*types.Value) + + for i := 0; i < len(entityKey.JoinKeys); i++ { + m[entityKey.JoinKeys[i]] = entityKey.EntityValues[i] + } + + keys := make([]string, 0, len(m)) + for k := range entityKey.JoinKeys { + keys = append(keys, entityKey.JoinKeys[k]) + } + sort.Strings(keys) + + // Build the key + length := 5 * len(keys) + bufferList := make([][]byte, length) + + for i := 0; i < len(keys); i++ { + offset := i * 2 + byteBuffer := make([]byte, 4) + binary.LittleEndian.PutUint32(byteBuffer, uint32(types.ValueType_Enum_value["STRING"])) + bufferList[offset] = byteBuffer + bufferList[offset+1] = []byte(keys[i]) + } + + for i := 0; i < len(keys); i++ { + offset := (2 * len(keys)) + (i * 3) + value := m[keys[i]].GetVal() + + valueBytes, valueTypeBytes, err := serializeValue(value) + if err != nil { + return valueBytes, err + } + + typeBuffer := make([]byte, 4) + binary.LittleEndian.PutUint32(typeBuffer, uint32(valueTypeBytes)) + + lenBuffer := make([]byte, 4) + binary.LittleEndian.PutUint32(lenBuffer, uint32(len(*valueBytes))) + + bufferList[offset+0] = typeBuffer + bufferList[offset+1] = lenBuffer + bufferList[offset+2] = *valueBytes + } + + // Convert from an array of byte arrays to a single byte array + var entityKeyBuffer []byte + for i := 0; i < len(bufferList); i++ { + entityKeyBuffer = append(entityKeyBuffer, bufferList[i]...) + } + + return &entityKeyBuffer, nil +} + +func serializeValue(value interface{}) (*[]byte, types.ValueType_Enum, error) { + // TODO: Implement support for other types (at least the major types like ints, strings, bytes) + switch x := (value).(type) { + case *types.Value_StringVal: + valueString := []byte(x.StringVal) + return &valueString, types.ValueType_STRING, nil + case *types.Value_BytesVal: + return &x.BytesVal, types.ValueType_BYTES, nil + case *types.Value_Int32Val: + valueBuffer := make([]byte, 4) + binary.LittleEndian.PutUint32(valueBuffer, uint32(x.Int32Val)) + return &valueBuffer, types.ValueType_INT32, nil + case *types.Value_Int64Val: + // TODO (woop): We unfortunately have to use 32 bit here for backward compatibility :( + valueBuffer := make([]byte, 4) + binary.LittleEndian.PutUint32(valueBuffer, uint32(x.Int64Val)) + return &valueBuffer, types.ValueType_INT64, nil + case nil: + return nil, types.ValueType_INVALID, fmt.Errorf("could not detect type for %v", x) + default: + return nil, types.ValueType_INVALID, fmt.Errorf("could not detect type for %v", x) + } +} diff --git a/go/internal/feast/onlinestore/sqliteonlinestore.go b/go/internal/feast/onlinestore/sqliteonlinestore.go new file mode 100644 index 00000000000..f8c53255455 --- /dev/null +++ b/go/internal/feast/onlinestore/sqliteonlinestore.go @@ -0,0 +1,160 @@ +package onlinestore + +import ( + "crypto/sha1" + "database/sql" + "encoding/hex" + "errors" + "github.com/feast-dev/feast/go/internal/feast/registry" + "strings" + "sync" + "time" + + "context" + "fmt" + + "github.com/feast-dev/feast/go/protos/feast/serving" + "github.com/feast-dev/feast/go/protos/feast/types" + _ "github.com/mattn/go-sqlite3" + "google.golang.org/protobuf/proto" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +type SqliteOnlineStore struct { + // Feast project name + project string + path string + db *sql.DB + db_mu sync.Mutex +} + +// Creates a new sqlite online store object. onlineStoreConfig should have relative path of database file with respect to repoConfig.repoPath. +func NewSqliteOnlineStore(project string, repoConfig *registry.RepoConfig, onlineStoreConfig map[string]interface{}) (*SqliteOnlineStore, error) { + store := SqliteOnlineStore{project: project} + if db_path, ok := onlineStoreConfig["path"]; !ok { + return nil, fmt.Errorf("cannot find sqlite path %s", db_path) + } else { + if dbPathStr, ok := db_path.(string); !ok { + return nil, fmt.Errorf("cannot find convert sqlite path to string %s", db_path) + } else { + store.path = fmt.Sprintf("%s/%s", repoConfig.RepoPath, dbPathStr) + db, err := initializeConnection(store.path) + if err != nil { + return nil, err + } + store.db = db + } + } + + return &store, nil +} + +func (s *SqliteOnlineStore) Destruct() { + s.db.Close() +} + +// Returns FeatureData 2D array. Each row corresponds to one entity Value and each column corresponds to a single feature where the number of columns should be +// same length as the length of featureNames. Reads from every table in featureViewNames with the entity keys described. +func (s *SqliteOnlineStore) OnlineRead(ctx context.Context, entityKeys []*types.EntityKey, featureViewNames []string, featureNames []string) ([][]FeatureData, error) { + featureCount := len(featureNames) + _, err := s.getConnection() + if err != nil { + return nil, err + } + project := s.project + results := make([][]FeatureData, len(entityKeys)) + entityNameToEntityIndex := make(map[string]int) + in_query := make([]string, len(entityKeys)) + serialized_entities := make([]interface{}, len(entityKeys)) + for i := 0; i < len(entityKeys); i++ { + serKey, err := serializeEntityKey(entityKeys[i]) + if err != nil { + return nil, err + } + // TODO: fix this, string conversion is not safe + entityNameToEntityIndex[hashSerializedEntityKey(serKey)] = i + // for IN clause in read query + in_query[i] = "?" + serialized_entities[i] = *serKey + } + featureNamesToIdx := make(map[string]int) + for idx, name := range featureNames { + featureNamesToIdx[name] = idx + } + + for _, featureViewName := range featureViewNames { + query_string := fmt.Sprintf(`SELECT entity_key, feature_name, Value, event_ts + FROM %s + WHERE entity_key IN (%s) + ORDER BY entity_key`, tableId(project, featureViewName), strings.Join(in_query, ",")) + rows, err := s.db.Query(query_string, serialized_entities...) + if err != nil { + return nil, err + } + defer rows.Close() + for rows.Next() { + var entity_key []byte + var feature_name string + var valueString []byte + var event_ts time.Time + var value types.Value + err = rows.Scan(&entity_key, &feature_name, &valueString, &event_ts) + if err != nil { + return nil, errors.New("error could not resolve row in query (entity key, feature name, value, event ts)") + } + if err := proto.Unmarshal(valueString, &value); err != nil { + return nil, errors.New("error converting parsed value to types.Value") + } + rowIdx := entityNameToEntityIndex[hashSerializedEntityKey(&entity_key)] + if results[rowIdx] == nil { + results[rowIdx] = make([]FeatureData, featureCount) + } + results[rowIdx][featureNamesToIdx[feature_name]] = FeatureData{Reference: serving.FeatureReferenceV2{FeatureViewName: featureViewName, FeatureName: feature_name}, + Timestamp: *timestamppb.New(event_ts), + Value: types.Value{Val: value.Val}, + } + } + } + return results, nil +} + +// Gets a sqlite connection and sets it to the online store and also returns a pointer to the connection. +func (s *SqliteOnlineStore) getConnection() (*sql.DB, error) { + s.db_mu.Lock() + defer s.db_mu.Unlock() + if s.db == nil { + if s.path == "" { + return nil, errors.New("no database path available") + } + db, err := initializeConnection(s.path) + s.db = db + if err != nil { + return nil, err + } + } + return s.db, nil +} + +// Constructs the table id from the project and table(featureViewName) string. +func tableId(project string, featureViewName string) string { + return fmt.Sprintf("%s_%s", project, featureViewName) +} + +// Creates a connection to the sqlite database and returns the connection. +func initializeConnection(db_path string) (*sql.DB, error) { + db, err := sql.Open("sqlite3", db_path) + if err != nil { + return nil, err + } + return db, nil +} + +func hashSerializedEntityKey(serializedEntityKey *[]byte) string { + if serializedEntityKey == nil { + return "" + } + h := sha1.New() + h.Write(*serializedEntityKey) + sha1_hash := hex.EncodeToString(h.Sum(nil)) + return sha1_hash +} diff --git a/go/internal/feast/onlinestore/sqliteonlinestore_test.go b/go/internal/feast/onlinestore/sqliteonlinestore_test.go new file mode 100644 index 00000000000..cbee9cd91c2 --- /dev/null +++ b/go/internal/feast/onlinestore/sqliteonlinestore_test.go @@ -0,0 +1,83 @@ +package onlinestore + +import ( + "context" + "path/filepath" + "reflect" + "testing" + + "github.com/feast-dev/feast/go/internal/feast/registry" + + "github.com/feast-dev/feast/go/internal/test" + "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/stretchr/testify/assert" +) + +func TestSqliteAndFeatureRepoSetup(t *testing.T) { + dir := "../../test" + feature_repo_path := filepath.Join(dir, "feature_repo") + err := test.SetupCleanFeatureRepo(dir) + assert.Nil(t, err) + defer test.CleanUpRepo(dir) + config, err := registry.NewRepoConfigFromFile(feature_repo_path) + assert.Nil(t, err) + assert.Equal(t, "feature_repo", config.Project) + assert.Equal(t, "data/registry.db", config.GetRegistryConfig().Path) + assert.Equal(t, "local", config.Provider) + assert.Equal(t, map[string]interface{}{ + "path": "data/online_store.db", + }, config.OnlineStore) + assert.Empty(t, config.OfflineStore) + assert.Empty(t, config.FeatureServer) + assert.Empty(t, config.Flags) +} + +func TestSqliteOnlineRead(t *testing.T) { + dir := "../../test" + feature_repo_path := filepath.Join(dir, "feature_repo") + test.SetupCleanFeatureRepo(dir) + defer test.CleanUpRepo(dir) + config, err := registry.NewRepoConfigFromFile(feature_repo_path) + assert.Nil(t, err) + store, err := NewSqliteOnlineStore("feature_repo", config, config.OnlineStore) + defer store.Destruct() + assert.Nil(t, err) + entity_key1 := types.EntityKey{ + JoinKeys: []string{"driver_id"}, + EntityValues: []*types.Value{{Val: &types.Value_Int64Val{Int64Val: 1005}}}, + } + entity_key2 := types.EntityKey{ + JoinKeys: []string{"driver_id"}, + EntityValues: []*types.Value{{Val: &types.Value_Int64Val{Int64Val: 1001}}}, + } + entity_key3 := types.EntityKey{ + JoinKeys: []string{"driver_id"}, + EntityValues: []*types.Value{{Val: &types.Value_Int64Val{Int64Val: 1003}}}, + } + entityKeys := []*types.EntityKey{&entity_key1, &entity_key2, &entity_key3} + tableNames := []string{"driver_hourly_stats"} + featureNames := []string{"conv_rate", "acc_rate", "avg_daily_trips"} + featureData, err := store.OnlineRead(context.Background(), entityKeys, tableNames, featureNames) + assert.Nil(t, err) + returnedFeatureValues := make([]*types.Value, 0) + returnedFeatureNames := make([]string, 0) + for _, featureVector := range featureData { + for idx := range featureVector { + returnedFeatureValues = append(returnedFeatureValues, &featureVector[idx].Value) + returnedFeatureNames = append(returnedFeatureNames, featureVector[idx].Reference.FeatureName) + } + } + rows, err := test.ReadParquet(filepath.Join(feature_repo_path, "data", "driver_stats.parquet")) + assert.Nil(t, err) + entities := map[int64]bool{1005: true, 1001: true, 1003: true} + correctFeatures := test.GetLatestFeatures(rows, entities) + expectedFeatureValues := make([]*types.Value, 0) + for _, key := range []int64{1005, 1001, 1003} { + expectedFeatureValues = append(expectedFeatureValues, &types.Value{Val: &types.Value_FloatVal{FloatVal: correctFeatures[key].ConvRate}}) + expectedFeatureValues = append(expectedFeatureValues, &types.Value{Val: &types.Value_FloatVal{FloatVal: correctFeatures[key].AccRate}}) + expectedFeatureValues = append(expectedFeatureValues, &types.Value{Val: &types.Value_Int64Val{Int64Val: int64(correctFeatures[key].AvgDailyTrips)}}) + } + expectedFeatureNames := []string{"conv_rate", "acc_rate", "avg_daily_trips", "conv_rate", "acc_rate", "avg_daily_trips", "conv_rate", "acc_rate", "avg_daily_trips"} + assert.True(t, reflect.DeepEqual(expectedFeatureValues, returnedFeatureValues)) + assert.True(t, reflect.DeepEqual(expectedFeatureNames, returnedFeatureNames)) +} diff --git a/go/internal/feast/registry/local.go b/go/internal/feast/registry/local.go new file mode 100644 index 00000000000..22db73a3206 --- /dev/null +++ b/go/internal/feast/registry/local.go @@ -0,0 +1,64 @@ +package registry + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" + "github.com/golang/protobuf/proto" + "github.com/google/uuid" + "google.golang.org/protobuf/types/known/timestamppb" + "io/ioutil" + "os" + "path/filepath" +) + +// A LocalRegistryStore is a file-based implementation of the RegistryStore interface. +type LocalRegistryStore struct { + filePath string +} + +// NewLocalRegistryStore creates a LocalRegistryStore with the given configuration and infers +// the file path from the repo path and registry path. +func NewLocalRegistryStore(config *RegistryConfig, repoPath string) *LocalRegistryStore { + lr := LocalRegistryStore{} + registryPath := config.Path + if filepath.IsAbs(registryPath) { + lr.filePath = registryPath + } else { + lr.filePath = filepath.Join(repoPath, registryPath) + } + return &lr +} + +// GetRegistryProto reads and parses the registry proto from the file path. +func (r *LocalRegistryStore) GetRegistryProto() (*core.Registry, error) { + registry := &core.Registry{} + in, err := ioutil.ReadFile(r.filePath) + if err != nil { + return nil, err + } + if err := proto.Unmarshal(in, registry); err != nil { + return nil, err + } + return registry, nil +} + +func (r *LocalRegistryStore) UpdateRegistryProto(rp *core.Registry) error { + return r.writeRegistry(rp) +} + +func (r *LocalRegistryStore) Teardown() error { + return os.Remove(r.filePath) +} + +func (r *LocalRegistryStore) writeRegistry(rp *core.Registry) error { + rp.VersionId = uuid.New().String() + rp.LastUpdated = timestamppb.Now() + bytes, err := proto.Marshal(rp) + if err != nil { + return err + } + err = ioutil.WriteFile(r.filePath, bytes, 0644) + if err != nil { + return err + } + return nil +} diff --git a/go/internal/feast/registry/registry.go b/go/internal/feast/registry/registry.go new file mode 100644 index 00000000000..38cf167a9fd --- /dev/null +++ b/go/internal/feast/registry/registry.go @@ -0,0 +1,298 @@ +package registry + +import ( + "errors" + "fmt" + "net/url" + "sync" + "time" + + "github.com/feast-dev/feast/go/internal/feast/model" + + "github.com/feast-dev/feast/go/protos/feast/core" +) + +var REGISTRY_SCHEMA_VERSION string = "1" +var REGISTRY_STORE_CLASS_FOR_SCHEME map[string]string = map[string]string{ + "gs": "GCSRegistryStore", + "s3": "S3RegistryStore", + "file": "LocalRegistryStore", + "": "LocalRegistryStore", +} + +/* + Store protos of FeatureView, FeatureService, Entity, OnDemandFeatureView + but return to user copies of non-proto versions of these objects +*/ + +type Registry struct { + registryStore RegistryStore + cachedFeatureServices map[string]map[string]*core.FeatureService + cachedEntities map[string]map[string]*core.Entity + cachedFeatureViews map[string]map[string]*core.FeatureView + cachedOnDemandFeatureViews map[string]map[string]*core.OnDemandFeatureView + cachedRegistry *core.Registry + cachedRegistryProtoLastUpdated time.Time + cachedRegistryProtoTtl time.Duration + mu sync.Mutex +} + +func NewRegistry(registryConfig *RegistryConfig, repoPath string) (*Registry, error) { + registryStoreType := registryConfig.RegistryStoreType + registryPath := registryConfig.Path + r := &Registry{ + cachedRegistryProtoTtl: time.Duration(registryConfig.CacheTtlSeconds), + } + + if len(registryStoreType) == 0 { + registryStore, err := getRegistryStoreFromScheme(registryPath, registryConfig, repoPath) + if err != nil { + return nil, err + } + r.registryStore = registryStore + } else { + registryStore, err := getRegistryStoreFromType(registryStoreType, registryConfig, repoPath) + if err != nil { + return nil, err + } + r.registryStore = registryStore + } + + return r, nil +} + +func (r *Registry) InitializeRegistry() { + _, err := r.getRegistryProto() + if err != nil { + registryProto := &core.Registry{RegistrySchemaVersion: REGISTRY_SCHEMA_VERSION} + r.registryStore.UpdateRegistryProto(registryProto) + go r.refreshRegistryOnInterval() + } +} + +func (r *Registry) refreshRegistryOnInterval() { + ticker := time.NewTicker(r.cachedRegistryProtoTtl) + for ; true; <-ticker.C { + err := r.refresh() + if err != nil { + return + } + } +} + +// TODO: Add a goroutine and automatically refresh every cachedRegistryProtoTtl +func (r *Registry) refresh() error { + _, err := r.getRegistryProto() + return err +} + +func (r *Registry) getRegistryProto() (*core.Registry, error) { + expired := r.cachedRegistry == nil || (r.cachedRegistryProtoTtl > 0 && time.Now().After(r.cachedRegistryProtoLastUpdated.Add(r.cachedRegistryProtoTtl))) + if !expired { + return r.cachedRegistry, nil + } + registryProto, err := r.registryStore.GetRegistryProto() + if err != nil { + return registryProto, err + } + r.load(registryProto) + return registryProto, nil +} + +func (r *Registry) load(registry *core.Registry) { + r.mu.Lock() + defer r.mu.Unlock() + r.cachedRegistry = registry + r.cachedFeatureServices = make(map[string]map[string]*core.FeatureService) + r.cachedEntities = make(map[string]map[string]*core.Entity) + r.cachedFeatureViews = make(map[string]map[string]*core.FeatureView) + r.cachedOnDemandFeatureViews = make(map[string]map[string]*core.OnDemandFeatureView) + r.loadEntities(registry) + r.loadFeatureServices(registry) + r.loadFeatureViews(registry) + r.loadOnDemandFeatureViews(registry) + r.cachedRegistryProtoLastUpdated = time.Now() +} + +func (r *Registry) loadEntities(registry *core.Registry) { + entities := registry.Entities + for _, entity := range entities { + if _, ok := r.cachedEntities[entity.Spec.Project]; !ok { + r.cachedEntities[entity.Spec.Project] = make(map[string]*core.Entity) + } + r.cachedEntities[entity.Spec.Project][entity.Spec.Name] = entity + } +} + +func (r *Registry) loadFeatureServices(registry *core.Registry) { + featureServices := registry.FeatureServices + for _, featureService := range featureServices { + if _, ok := r.cachedFeatureServices[featureService.Spec.Project]; !ok { + r.cachedFeatureServices[featureService.Spec.Project] = make(map[string]*core.FeatureService) + } + r.cachedFeatureServices[featureService.Spec.Project][featureService.Spec.Name] = featureService + } +} + +func (r *Registry) loadFeatureViews(registry *core.Registry) { + featureViews := registry.FeatureViews + for _, featureView := range featureViews { + if _, ok := r.cachedFeatureViews[featureView.Spec.Project]; !ok { + r.cachedFeatureViews[featureView.Spec.Project] = make(map[string]*core.FeatureView) + } + r.cachedFeatureViews[featureView.Spec.Project][featureView.Spec.Name] = featureView + } +} + +func (r *Registry) loadOnDemandFeatureViews(registry *core.Registry) { + onDemandFeatureViews := registry.OnDemandFeatureViews + for _, onDemandFeatureView := range onDemandFeatureViews { + if _, ok := r.cachedOnDemandFeatureViews[onDemandFeatureView.Spec.Project]; !ok { + r.cachedOnDemandFeatureViews[onDemandFeatureView.Spec.Project] = make(map[string]*core.OnDemandFeatureView) + } + r.cachedOnDemandFeatureViews[onDemandFeatureView.Spec.Project][onDemandFeatureView.Spec.Name] = onDemandFeatureView + } +} + +/* + Look up Entities inside project + Returns empty list if project not found +*/ + +func (r *Registry) ListEntities(project string) ([]*model.Entity, error) { + if cachedEntities, ok := r.cachedEntities[project]; !ok { + return []*model.Entity{}, nil + } else { + entities := make([]*model.Entity, len(cachedEntities)) + index := 0 + for _, entityProto := range cachedEntities { + entities[index] = model.NewEntityFromProto(entityProto) + index += 1 + } + return entities, nil + } +} + +/* + Look up Feature Views inside project + Returns empty list if project not found +*/ + +func (r *Registry) ListFeatureViews(project string) ([]*model.FeatureView, error) { + if cachedFeatureViews, ok := r.cachedFeatureViews[project]; !ok { + return []*model.FeatureView{}, nil + } else { + featureViews := make([]*model.FeatureView, len(cachedFeatureViews)) + index := 0 + for _, featureViewProto := range cachedFeatureViews { + featureViews[index] = model.NewFeatureViewFromProto(featureViewProto) + index += 1 + } + return featureViews, nil + } +} + +/* + Look up Feature Views inside project + Returns empty list if project not found +*/ + +func (r *Registry) ListFeatureServices(project string) ([]*model.FeatureService, error) { + if cachedFeatureServices, ok := r.cachedFeatureServices[project]; !ok { + return []*model.FeatureService{}, nil + } else { + featureServices := make([]*model.FeatureService, len(cachedFeatureServices)) + index := 0 + for _, featureServiceProto := range cachedFeatureServices { + featureServices[index] = model.NewFeatureServiceFromProto(featureServiceProto) + index += 1 + } + return featureServices, nil + } +} + +/* + Look up On Demand Feature Views inside project + Returns empty list if project not found +*/ + +func (r *Registry) ListOnDemandFeatureViews(project string) ([]*model.OnDemandFeatureView, error) { + if cachedOnDemandFeatureViews, ok := r.cachedOnDemandFeatureViews[project]; !ok { + return []*model.OnDemandFeatureView{}, nil + } else { + onDemandFeatureViews := make([]*model.OnDemandFeatureView, len(cachedOnDemandFeatureViews)) + index := 0 + for _, onDemandFeatureViewProto := range cachedOnDemandFeatureViews { + onDemandFeatureViews[index] = model.NewOnDemandFeatureViewFromProto(onDemandFeatureViewProto) + index += 1 + } + return onDemandFeatureViews, nil + } +} + +func (r *Registry) GetEntity(project, entityName string) (*model.Entity, error) { + if cachedEntities, ok := r.cachedEntities[project]; !ok { + return nil, fmt.Errorf("no cached entities found for project %s", project) + } else { + if entity, ok := cachedEntities[entityName]; !ok { + return nil, fmt.Errorf("no cached entity %s found for project %s", entityName, project) + } else { + return model.NewEntityFromProto(entity), nil + } + } +} + +func (r *Registry) GetFeatureView(project, featureViewName string) (*model.FeatureView, error) { + if cachedFeatureViews, ok := r.cachedFeatureViews[project]; !ok { + return nil, fmt.Errorf("no cached feature views found for project %s", project) + } else { + if featureViewProto, ok := cachedFeatureViews[featureViewName]; !ok { + return nil, fmt.Errorf("no cached feature view %s found for project %s", featureViewName, project) + } else { + return model.NewFeatureViewFromProto(featureViewProto), nil + } + } +} + +func (r *Registry) GetFeatureService(project, featureServiceName string) (*model.FeatureService, error) { + if cachedFeatureServices, ok := r.cachedFeatureServices[project]; !ok { + return nil, fmt.Errorf("no cached feature services found for project %s", project) + } else { + if featureServiceProto, ok := cachedFeatureServices[featureServiceName]; !ok { + return nil, fmt.Errorf("no cached feature service %s found for project %s", featureServiceName, project) + } else { + return model.NewFeatureServiceFromProto(featureServiceProto), nil + } + } +} + +func (r *Registry) GetOnDemandFeatureView(project, onDemandFeatureViewName string) (*model.OnDemandFeatureView, error) { + if cachedOnDemandFeatureViews, ok := r.cachedOnDemandFeatureViews[project]; !ok { + return nil, fmt.Errorf("no cached on demand feature views found for project %s", project) + } else { + if onDemandFeatureViewProto, ok := cachedOnDemandFeatureViews[onDemandFeatureViewName]; !ok { + return nil, fmt.Errorf("no cached on demand feature view %s found for project %s", onDemandFeatureViewName, project) + } else { + return model.NewOnDemandFeatureViewFromProto(onDemandFeatureViewProto), nil + } + } +} + +func getRegistryStoreFromScheme(registryPath string, registryConfig *RegistryConfig, repoPath string) (RegistryStore, error) { + uri, err := url.Parse(registryPath) + if err != nil { + return nil, err + } + if registryStoreType, ok := REGISTRY_STORE_CLASS_FOR_SCHEME[uri.Scheme]; ok { + return getRegistryStoreFromType(registryStoreType, registryConfig, repoPath) + } + return nil, fmt.Errorf("registry path %s has unsupported scheme %s. Supported schemes are file, s3 and gs", registryPath, uri.Scheme) +} + +func getRegistryStoreFromType(registryStoreType string, registryConfig *RegistryConfig, repoPath string) (RegistryStore, error) { + switch registryStoreType { + case "LocalRegistryStore": + return NewLocalRegistryStore(registryConfig, repoPath), nil + } + return nil, errors.New("only LocalRegistryStore as a RegistryStore is supported at this moment") +} diff --git a/go/internal/feast/registry/registrystore.go b/go/internal/feast/registry/registrystore.go new file mode 100644 index 00000000000..f872d66858b --- /dev/null +++ b/go/internal/feast/registry/registrystore.go @@ -0,0 +1,12 @@ +package registry + +import ( + "github.com/feast-dev/feast/go/protos/feast/core" +) + +// A RegistryStore is a storage backend for the Feast registry. +type RegistryStore interface { + GetRegistryProto() (*core.Registry, error) + UpdateRegistryProto(*core.Registry) error + Teardown() error +} diff --git a/go/internal/feast/registry/repoconfig.go b/go/internal/feast/registry/repoconfig.go new file mode 100644 index 00000000000..e5efd899de9 --- /dev/null +++ b/go/internal/feast/registry/repoconfig.go @@ -0,0 +1,97 @@ +package registry + +import ( + "encoding/json" + "github.com/ghodss/yaml" + "io/ioutil" + "path/filepath" +) + +const ( + defaultCacheTtlSeconds = 600 +) + +type RepoConfig struct { + // Feast project name + Project string `json:"project"` + // Feast provider name + Provider string `json:"provider"` + // Path to the registry. Custom registry loaders are not yet supported + // Registry string `json:"registry"` + Registry interface{} `json:"registry"` + // Online store config + OnlineStore map[string]interface{} `json:"online_store"` + // Offline store config + OfflineStore map[string]interface{} `json:"offline_store"` + // Feature server config (currently unrelated to Go server) + FeatureServer map[string]interface{} `json:"feature_server"` + // Feature flags for experimental features + Flags map[string]interface{} `json:"flags"` + // RepoPath + RepoPath string `json:"repo_path"` +} + +type RegistryConfig struct { + RegistryStoreType string `json:"registry_store_type"` + Path string `json:"path"` + CacheTtlSeconds int64 `json:"cache_ttl_seconds" default:"600"` +} + +// NewRepoConfigFromJSON converts a JSON string into a RepoConfig struct and also sets the repo path. +func NewRepoConfigFromJSON(repoPath, configJSON string) (*RepoConfig, error) { + config := RepoConfig{} + if err := json.Unmarshal([]byte(configJSON), &config); err != nil { + return nil, err + } + repoPath, err := filepath.Abs(repoPath) + if err != nil { + return nil, err + } + config.RepoPath = repoPath + return &config, nil +} + +// NewRepoConfigFromFile reads the `feature_store.yaml` file in the repo path and converts it +// into a RepoConfig struct. +func NewRepoConfigFromFile(repoPath string) (*RepoConfig, error) { + data, err := ioutil.ReadFile(filepath.Join(repoPath, "feature_store.yaml")) + if err != nil { + return nil, err + } + repoPath, err = filepath.Abs(repoPath) + if err != nil { + return nil, err + } + + config := RepoConfig{} + if err = yaml.Unmarshal(data, &config); err != nil { + return nil, err + } + config.RepoPath = repoPath + return &config, nil +} + +func (r *RepoConfig) GetRegistryConfig() *RegistryConfig { + if registryConfigMap, ok := r.Registry.(map[string]interface{}); ok { + registryConfig := RegistryConfig{CacheTtlSeconds: defaultCacheTtlSeconds} + for k, v := range registryConfigMap { + switch k { + case "path": + if value, ok := v.(string); ok { + registryConfig.Path = value + } + case "registry_store_type": + if value, ok := v.(string); ok { + registryConfig.RegistryStoreType = value + } + case "cache_ttl_seconds": + if value, ok := v.(int64); ok { + registryConfig.CacheTtlSeconds = value + } + } + } + return ®istryConfig + } else { + return &RegistryConfig{Path: r.Registry.(string), CacheTtlSeconds: defaultCacheTtlSeconds} + } +} diff --git a/go/internal/feast/registry/repoconfig_test.go b/go/internal/feast/registry/repoconfig_test.go new file mode 100644 index 00000000000..c3336fd618f --- /dev/null +++ b/go/internal/feast/registry/repoconfig_test.go @@ -0,0 +1,97 @@ +package registry + +import ( + "github.com/stretchr/testify/assert" + "os" + "path/filepath" + "testing" +) + +func TestNewRepoConfig(t *testing.T) { + dir, err := os.MkdirTemp("", "feature_repo_*") + assert.Nil(t, err) + defer func() { + assert.Nil(t, os.RemoveAll(dir)) + }() + filePath := filepath.Join(dir, "feature_store.yaml") + data := []byte(` +project: feature_repo +registry: "data/registry.db" +provider: local +online_store: + type: redis + connection_string: "localhost:6379" +`) + err = os.WriteFile(filePath, data, 0666) + assert.Nil(t, err) + config, err := NewRepoConfigFromFile(dir) + assert.Nil(t, err) + assert.Equal(t, "feature_repo", config.Project) + assert.Equal(t, dir, config.RepoPath) + assert.Equal(t, "data/registry.db", config.GetRegistryConfig().Path) + assert.Equal(t, "local", config.Provider) + assert.Equal(t, map[string]interface{}{ + "type": "redis", + "connection_string": "localhost:6379", + }, config.OnlineStore) + assert.Empty(t, config.OfflineStore) + assert.Empty(t, config.FeatureServer) + assert.Empty(t, config.Flags) +} + +func TestNewRepoConfigRegistryMap(t *testing.T) { + dir, err := os.MkdirTemp("", "feature_repo_*") + assert.Nil(t, err) + defer func() { + assert.Nil(t, os.RemoveAll(dir)) + }() + filePath := filepath.Join(dir, "feature_store.yaml") + data := []byte(` +registry: + path: data/registry.db +project: feature_repo +provider: local +online_store: + type: redis + connection_string: "localhost:6379" +`) + err = os.WriteFile(filePath, data, 0666) + assert.Nil(t, err) + config, err := NewRepoConfigFromFile(dir) + assert.Nil(t, err) + assert.Equal(t, "feature_repo", config.Project) + assert.Equal(t, dir, config.RepoPath) + assert.Equal(t, "data/registry.db", config.GetRegistryConfig().Path) + assert.Equal(t, "local", config.Provider) + assert.Equal(t, map[string]interface{}{ + "type": "redis", + "connection_string": "localhost:6379", + }, config.OnlineStore) + assert.Empty(t, config.OfflineStore) + assert.Empty(t, config.FeatureServer) + assert.Empty(t, config.Flags) +} + +func TestNewRepoConfigRegistryConfig(t *testing.T) { + dir, err := os.MkdirTemp("", "feature_repo_*") + assert.Nil(t, err) + defer func() { + assert.Nil(t, os.RemoveAll(dir)) + }() + filePath := filepath.Join(dir, "feature_store.yaml") + data := []byte(` +registry: + path: data/registry.db +project: feature_repo +provider: local +online_store: + type: redis + connection_string: "localhost:6379" +`) + err = os.WriteFile(filePath, data, 0666) + assert.Nil(t, err) + config, err := NewRepoConfigFromFile(dir) + assert.Nil(t, err) + assert.Equal(t, dir, config.RepoPath) + assert.Equal(t, "data/registry.db", config.GetRegistryConfig().Path) +} diff --git a/go/internal/feast/transformation/transformation.go b/go/internal/feast/transformation/transformation.go new file mode 100644 index 00000000000..319bed3b2c2 --- /dev/null +++ b/go/internal/feast/transformation/transformation.go @@ -0,0 +1,208 @@ +package transformation + +import ( + "errors" + "fmt" + "github.com/apache/arrow/go/v8/arrow" + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/apache/arrow/go/v8/arrow/cdata" + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/internal/feast/onlineserving" + "github.com/feast-dev/feast/go/protos/feast/serving" + prototypes "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/feast-dev/feast/go/types" + "google.golang.org/protobuf/types/known/timestamppb" + "strings" + "unsafe" +) + +/* + TransformationCallback is a Python callback function's expected signature. + The function should accept name of the on demand feature view and pointers to input & output record batches. + Each record batch is being passed as two pointers: pointer to array (data) and pointer to schema. + Python function is expected to return number of rows added to the output record batch. +*/ +type TransformationCallback func(ODFVName string, inputArrPtr, inputSchemaPtr, outArrPtr, outSchemaPtr uintptr, fullFeatureNames bool) int + +func AugmentResponseWithOnDemandTransforms( + onDemandFeatureViews []*model.OnDemandFeatureView, + requestData map[string]*prototypes.RepeatedValue, + entityRows map[string]*prototypes.RepeatedValue, + features []*onlineserving.FeatureVector, + transformationCallback TransformationCallback, + arrowMemory memory.Allocator, + numRows int, + fullFeatureNames bool, + +) ([]*onlineserving.FeatureVector, error) { + result := make([]*onlineserving.FeatureVector, 0) + var err error + + for _, odfv := range onDemandFeatureViews { + requestContextArrow := make(map[string]array.Interface) + for name, values := range requestData { + requestContextArrow[name], err = types.ProtoValuesToArrowArray(values.Val, arrowMemory, numRows) + if err != nil { + return nil, err + } + } + + for name, values := range entityRows { + requestContextArrow[name], err = types.ProtoValuesToArrowArray(values.Val, arrowMemory, numRows) + if err != nil { + return nil, err + } + } + + retrievedFeatures := make(map[string]array.Interface) + for _, vector := range features { + retrievedFeatures[vector.Name] = vector.Values + } + + onDemandFeatures, err := CallTransformations( + odfv, + retrievedFeatures, + requestContextArrow, + transformationCallback, + numRows, + fullFeatureNames, + ) + if err != nil { + return nil, err + } + result = append(result, onDemandFeatures...) + } + + return result, nil +} + +func CallTransformations( + featureView *model.OnDemandFeatureView, + retrievedFeatures map[string]array.Interface, + requestContext map[string]array.Interface, + callback TransformationCallback, + numRows int, + fullFeatureNames bool, +) ([]*onlineserving.FeatureVector, error) { + + inputArr := cdata.CArrowArray{} + inputSchema := cdata.CArrowSchema{} + + outArr := cdata.CArrowArray{} + outSchema := cdata.CArrowSchema{} + + defer cdata.ReleaseCArrowArray(&inputArr) + defer cdata.ReleaseCArrowArray(&outArr) + defer cdata.ReleaseCArrowSchema(&inputSchema) + defer cdata.ReleaseCArrowSchema(&outSchema) + + inputArrPtr := uintptr(unsafe.Pointer(&inputArr)) + inputSchemaPtr := uintptr(unsafe.Pointer(&inputSchema)) + + outArrPtr := uintptr(unsafe.Pointer(&outArr)) + outSchemaPtr := uintptr(unsafe.Pointer(&outSchema)) + + inputFields := make([]arrow.Field, 0) + inputColumns := make([]array.Interface, 0) + for name, arr := range retrievedFeatures { + inputFields = append(inputFields, arrow.Field{Name: name, Type: arr.DataType()}) + inputColumns = append(inputColumns, arr) + } + for name, arr := range requestContext { + inputFields = append(inputFields, arrow.Field{Name: name, Type: arr.DataType()}) + inputColumns = append(inputColumns, arr) + } + + inputRecord := array.NewRecord(arrow.NewSchema(inputFields, nil), inputColumns, int64(numRows)) + defer inputRecord.Release() + + cdata.ExportArrowRecordBatch(inputRecord, &inputArr, &inputSchema) + + ret := callback(featureView.Base.Name, inputArrPtr, inputSchemaPtr, outArrPtr, outSchemaPtr, fullFeatureNames) + + if ret != numRows { + return nil, errors.New("python transformation callback failed") + } + + outRecord, err := cdata.ImportCRecordBatch(&outArr, &outSchema) + if err != nil { + return nil, err + } + + result := make([]*onlineserving.FeatureVector, 0) + for idx, field := range outRecord.Schema().Fields() { + dropFeature := true + + if featureView.Base.Projection != nil { + var featureName string + if fullFeatureNames { + featureName = strings.Split(field.Name, "__")[1] + } else { + featureName = field.Name + } + + for _, feature := range featureView.Base.Projection.Features { + if featureName == feature.Name { + dropFeature = false + } + } + } else { + dropFeature = false + } + + if dropFeature { + continue + } + + statuses := make([]serving.FieldStatus, numRows) + timestamps := make([]*timestamppb.Timestamp, numRows) + + for idx := 0; idx < numRows; idx++ { + statuses[idx] = serving.FieldStatus_PRESENT + timestamps[idx] = timestamppb.Now() + } + + result = append(result, &onlineserving.FeatureVector{ + Name: field.Name, + Values: outRecord.Column(idx), + Statuses: statuses, + Timestamps: timestamps, + }) + } + + return result, nil +} + +func EnsureRequestedDataExist(requestedOnDemandFeatureViews []*model.OnDemandFeatureView, + requestDataFeatures map[string]*prototypes.RepeatedValue) error { + + neededRequestData, err := getNeededRequestData(requestedOnDemandFeatureViews) + if err != nil { + return err + } + missingFeatures := make([]string, 0) + for feature := range neededRequestData { + if _, ok := requestDataFeatures[feature]; !ok { + missingFeatures = append(missingFeatures, feature) + } + } + + if len(missingFeatures) > 0 { + return fmt.Errorf("requestDataNotFoundInEntityRowsException: %s", strings.Join(missingFeatures, ", ")) + } + return nil +} + +func getNeededRequestData(requestedOnDemandFeatureViews []*model.OnDemandFeatureView) (map[string]struct{}, error) { + neededRequestData := make(map[string]struct{}) + + for _, onDemandFeatureView := range requestedOnDemandFeatureViews { + requestSchema := onDemandFeatureView.GetRequestDataSchema() + for fieldName := range requestSchema { + neededRequestData[fieldName] = struct{}{} + } + } + + return neededRequestData, nil +} diff --git a/go/internal/test/go_integration_test_utils.go b/go/internal/test/go_integration_test_utils.go new file mode 100644 index 00000000000..d66a5461930 --- /dev/null +++ b/go/internal/test/go_integration_test_utils.go @@ -0,0 +1,253 @@ +package test + +import ( + "context" + "fmt" + "log" + + "github.com/apache/arrow/go/v8/arrow/memory" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/apache/arrow/go/v8/arrow" + "github.com/apache/arrow/go/v8/parquet/file" + "github.com/apache/arrow/go/v8/parquet/pqarrow" + + "os" + "os/exec" + "path/filepath" + "time" + + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/feast-dev/feast/go/internal/feast/model" + "github.com/feast-dev/feast/go/protos/feast/types" + gotypes "github.com/feast-dev/feast/go/types" +) + +type Row struct { + EventTimestamp int64 + DriverId int64 + ConvRate float32 + AccRate float32 + AvgDailyTrips int32 + Created int64 +} + +func ReadParquet(filePath string) ([]*Row, error) { + allocator := memory.NewGoAllocator() + pqfile, err := file.OpenParquetFile(filePath, false) + if err != nil { + return nil, err + } + reader, err := pqarrow.NewFileReader(pqfile, pqarrow.ArrowReadProperties{}, allocator) + if err != nil { + return nil, err + } + fmt.Println(reader) + table, err := reader.ReadTable(context.Background()) + if err != nil { + return nil, err + } + + columns := make(map[string]arrow.Array) + fields := table.Schema().Fields() + for idx, field := range fields { + columns[field.Name] = table.Column(idx).Data().Chunk(0) + } + + rows := make([]*Row, 0) + for rowIdx := 0; rowIdx < int(table.NumRows()); rowIdx++ { + rows = append(rows, &Row{ + EventTimestamp: columns["event_timestamp"].(*array.Timestamp).Value(rowIdx).ToTime(arrow.Second).Unix(), + DriverId: columns["driver_id"].(*array.Int64).Value(rowIdx), + ConvRate: columns["conv_rate"].(*array.Float32).Value(rowIdx), + AccRate: columns["acc_rate"].(*array.Float32).Value(rowIdx), + AvgDailyTrips: columns["avg_daily_trips"].(*array.Int32).Value(rowIdx), + Created: columns["created"].(*array.Timestamp).Value(rowIdx).ToTime(arrow.Second).Unix(), + }) + } + + return rows, nil +} + +func GetLatestFeatures(Rows []*Row, entities map[int64]bool) map[int64]*Row { + correctFeatureRows := make(map[int64]*Row) + for _, Row := range Rows { + if _, ok := entities[Row.DriverId]; ok { + if _, ok := correctFeatureRows[Row.DriverId]; ok { + if Row.EventTimestamp > correctFeatureRows[Row.DriverId].EventTimestamp { + correctFeatureRows[Row.DriverId] = Row + } + } else { + correctFeatureRows[Row.DriverId] = Row + } + } + } + return correctFeatureRows +} + +func SetupCleanFeatureRepo(basePath string) error { + cmd := exec.Command("feast", "init", "feature_repo") + path, err := filepath.Abs(basePath) + cmd.Env = os.Environ() + + if err != nil { + return err + } + cmd.Dir = path + err = cmd.Run() + if err != nil { + return err + } + applyCommand := exec.Command("feast", "apply") + applyCommand.Env = os.Environ() + featureRepoPath, err := filepath.Abs(filepath.Join(path, "feature_repo")) + if err != nil { + return err + } + applyCommand.Dir = featureRepoPath + applyCommand.Run() + t := time.Now() + + formattedTime := fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d", + t.Year(), t.Month(), t.Day(), + t.Hour(), t.Minute(), t.Second()) + materializeCommand := exec.Command("feast", "materialize-incremental", formattedTime) + materializeCommand.Env = os.Environ() + materializeCommand.Dir = featureRepoPath + err = materializeCommand.Run() + if err != nil { + return err + } + + return nil +} + +func SetupInitializedRepo(basePath string) error { + path, err := filepath.Abs(basePath) + if err != nil { + return err + } + applyCommand := exec.Command("feast", "apply") + applyCommand.Env = os.Environ() + featureRepoPath, err := filepath.Abs(filepath.Join(path, "feature_repo")) + if err != nil { + return err + } + // var stderr bytes.Buffer + // var stdout bytes.Buffer + applyCommand.Dir = featureRepoPath + err = applyCommand.Run() + if err != nil { + return err + + } + t := time.Now() + + formattedTime := fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d", + t.Year(), t.Month(), t.Day(), + t.Hour(), t.Minute(), t.Second()) + + materializeCommand := exec.Command("feast", "materialize-incremental", formattedTime) + materializeCommand.Env = os.Environ() + materializeCommand.Dir = featureRepoPath + out, err := materializeCommand.Output() + if err != nil { + log.Println(string(out)) + return err + } + return nil +} + +func CleanUpInitializedRepo(basePath string) { + featureRepoPath, err := filepath.Abs(filepath.Join(basePath, "feature_repo")) + if err != nil { + log.Fatal(err) + } + + err = os.Remove(filepath.Join(featureRepoPath, "data", "registry.db")) + if err != nil { + log.Fatal(err) + } + err = os.Remove(filepath.Join(featureRepoPath, "data", "online_store.db")) + if err != nil { + log.Fatal(err) + } +} + +func CleanUpRepo(basePath string) { + featureRepoPath, err := filepath.Abs(filepath.Join(basePath, "feature_repo")) + if err != nil { + log.Fatal(err) + } + err = os.RemoveAll(featureRepoPath) + if err != nil { + log.Fatal(err) + } +} + +func GetProtoFromRecord(rec array.Record) (map[string]*types.RepeatedValue, error) { + r := make(map[string]*types.RepeatedValue) + schema := rec.Schema() + for idx, column := range rec.Columns() { + field := schema.Field(idx) + values, err := gotypes.ArrowValuesToProtoValues(column) + if err != nil { + return nil, err + } + r[field.Name] = &types.RepeatedValue{Val: values} + } + return r, nil +} + +func CleanUpFile(absPath string) error { + return os.Remove(absPath) +} + +func CreateBaseFeatureView(name string, features []*model.Feature, projection *model.FeatureViewProjection) *model.BaseFeatureView { + return &model.BaseFeatureView{ + Name: name, + Features: features, + Projection: projection, + } +} + +func CreateNewEntity(name string, valueType types.ValueType_Enum, joinKey string) *model.Entity { + return &model.Entity{ + Name: name, + ValueType: valueType, + JoinKey: joinKey, + } +} + +func CreateNewFeature(name string, dtype types.ValueType_Enum) *model.Feature { + return &model.Feature{Name: name, + Dtype: dtype, + } +} + +func CreateNewFeatureService(name string, project string, createdTimestamp *timestamppb.Timestamp, lastUpdatedTimestamp *timestamppb.Timestamp, projections []*model.FeatureViewProjection) *model.FeatureService { + return &model.FeatureService{ + Name: name, + Project: project, + CreatedTimestamp: createdTimestamp, + LastUpdatedTimestamp: lastUpdatedTimestamp, + Projections: projections, + } +} + +func CreateNewFeatureViewProjection(name string, nameAlias string, features []*model.Feature, joinKeyMap map[string]string) *model.FeatureViewProjection { + return &model.FeatureViewProjection{Name: name, + NameAlias: nameAlias, + Features: features, + JoinKeyMap: joinKeyMap, + } +} + +func CreateFeatureView(base *model.BaseFeatureView, ttl *durationpb.Duration, entities []string) *model.FeatureView { + return &model.FeatureView{ + Base: base, + Ttl: ttl, + Entities: entities, + } +} diff --git a/go/types/typeconversion.go b/go/types/typeconversion.go new file mode 100644 index 00000000000..c02768c755d --- /dev/null +++ b/go/types/typeconversion.go @@ -0,0 +1,319 @@ +package types + +import ( + "fmt" + + "github.com/apache/arrow/go/v8/arrow" + "github.com/apache/arrow/go/v8/arrow/array" + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/feast-dev/feast/go/protos/feast/types" +) + +func ProtoTypeToArrowType(sample *types.Value) (arrow.DataType, error) { + switch sample.Val.(type) { + case *types.Value_BytesVal: + return arrow.BinaryTypes.Binary, nil + case *types.Value_StringVal: + return arrow.BinaryTypes.String, nil + case *types.Value_Int32Val: + return arrow.PrimitiveTypes.Int32, nil + case *types.Value_Int64Val: + return arrow.PrimitiveTypes.Int64, nil + case *types.Value_FloatVal: + return arrow.PrimitiveTypes.Float32, nil + case *types.Value_DoubleVal: + return arrow.PrimitiveTypes.Float64, nil + case *types.Value_BoolVal: + return arrow.FixedWidthTypes.Boolean, nil + case *types.Value_BoolListVal: + return arrow.ListOf(arrow.FixedWidthTypes.Boolean), nil + case *types.Value_StringListVal: + return arrow.ListOf(arrow.BinaryTypes.String), nil + case *types.Value_BytesListVal: + return arrow.ListOf(arrow.BinaryTypes.Binary), nil + case *types.Value_Int32ListVal: + return arrow.ListOf(arrow.PrimitiveTypes.Int32), nil + case *types.Value_Int64ListVal: + return arrow.ListOf(arrow.PrimitiveTypes.Int64), nil + case *types.Value_FloatListVal: + return arrow.ListOf(arrow.PrimitiveTypes.Float32), nil + case *types.Value_DoubleListVal: + return arrow.ListOf(arrow.PrimitiveTypes.Float64), nil + case *types.Value_UnixTimestampVal: + return arrow.FixedWidthTypes.Time64ns, nil + case *types.Value_UnixTimestampListVal: + return arrow.ListOf(arrow.FixedWidthTypes.Time64ns), nil + default: + return nil, + fmt.Errorf("unsupported proto type in proto to arrow conversion: %s", sample.Val) + } +} + +func ValueTypeEnumToArrowType(t types.ValueType_Enum) (arrow.DataType, error) { + switch t { + case types.ValueType_BYTES: + return arrow.BinaryTypes.Binary, nil + case types.ValueType_STRING: + return arrow.BinaryTypes.String, nil + case types.ValueType_INT32: + return arrow.PrimitiveTypes.Int32, nil + case types.ValueType_INT64: + return arrow.PrimitiveTypes.Int64, nil + case types.ValueType_FLOAT: + return arrow.PrimitiveTypes.Float32, nil + case types.ValueType_DOUBLE: + return arrow.PrimitiveTypes.Float64, nil + case types.ValueType_BOOL: + return arrow.FixedWidthTypes.Boolean, nil + case types.ValueType_BOOL_LIST: + return arrow.ListOf(arrow.FixedWidthTypes.Boolean), nil + case types.ValueType_STRING_LIST: + return arrow.ListOf(arrow.BinaryTypes.String), nil + case types.ValueType_BYTES_LIST: + return arrow.ListOf(arrow.BinaryTypes.Binary), nil + case types.ValueType_INT32_LIST: + return arrow.ListOf(arrow.PrimitiveTypes.Int32), nil + case types.ValueType_INT64_LIST: + return arrow.ListOf(arrow.PrimitiveTypes.Int64), nil + case types.ValueType_FLOAT_LIST: + return arrow.ListOf(arrow.PrimitiveTypes.Float32), nil + case types.ValueType_DOUBLE_LIST: + return arrow.ListOf(arrow.PrimitiveTypes.Float64), nil + case types.ValueType_UNIX_TIMESTAMP: + return arrow.FixedWidthTypes.Time64ns, nil + case types.ValueType_UNIX_TIMESTAMP_LIST: + return arrow.ListOf(arrow.FixedWidthTypes.Time64ns), nil + default: + return nil, + fmt.Errorf("unsupported value type enum in enum to arrow type conversion: %s", t) + } +} + +func copyProtoValuesToArrowArray(builder array.Builder, values []*types.Value) error { + switch fieldBuilder := builder.(type) { + case *array.BooleanBuilder: + for _, v := range values { + fieldBuilder.Append(v.GetBoolVal()) + } + case *array.BinaryBuilder: + for _, v := range values { + fieldBuilder.Append(v.GetBytesVal()) + } + case *array.StringBuilder: + for _, v := range values { + fieldBuilder.Append(v.GetStringVal()) + } + case *array.Int32Builder: + for _, v := range values { + fieldBuilder.Append(v.GetInt32Val()) + } + case *array.Int64Builder: + for _, v := range values { + fieldBuilder.Append(v.GetInt64Val()) + } + case *array.Float32Builder: + for _, v := range values { + fieldBuilder.Append(v.GetFloatVal()) + } + case *array.Float64Builder: + for _, v := range values { + fieldBuilder.Append(v.GetDoubleVal()) + } + case *array.Time64Builder: + for _, v := range values { + fieldBuilder.Append(arrow.Time64(v.GetUnixTimestampVal())) + } + case *array.ListBuilder: + for _, list := range values { + fieldBuilder.Append(true) + + switch valueBuilder := fieldBuilder.ValueBuilder().(type) { + + case *array.BooleanBuilder: + for _, v := range list.GetBoolListVal().GetVal() { + valueBuilder.Append(v) + } + case *array.BinaryBuilder: + for _, v := range list.GetBytesListVal().GetVal() { + valueBuilder.Append(v) + } + case *array.StringBuilder: + for _, v := range list.GetStringListVal().GetVal() { + valueBuilder.Append(v) + } + case *array.Int32Builder: + for _, v := range list.GetInt32ListVal().GetVal() { + valueBuilder.Append(v) + } + case *array.Int64Builder: + for _, v := range list.GetInt64ListVal().GetVal() { + valueBuilder.Append(v) + } + case *array.Float32Builder: + for _, v := range list.GetFloatListVal().GetVal() { + valueBuilder.Append(v) + } + case *array.Float64Builder: + for _, v := range list.GetDoubleListVal().GetVal() { + valueBuilder.Append(v) + } + case *array.Time64Builder: + for _, v := range list.GetUnixTimestampListVal().GetVal() { + valueBuilder.Append(arrow.Time64(v)) + } + } + } + default: + return fmt.Errorf("unsupported array builder: %s", builder) + } + return nil +} + +func ArrowValuesToProtoValues(arr arrow.Array) ([]*types.Value, error) { + values := make([]*types.Value, 0) + + if listArr, ok := arr.(*array.List); ok { + listValues := listArr.ListValues() + offsets := listArr.Offsets()[1:] + pos := 0 + for idx := 0; idx < listArr.Len(); idx++ { + switch listValues.DataType() { + case arrow.PrimitiveTypes.Int32: + vals := make([]int32, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = listValues.(*array.Int32).Value(j) + } + values = append(values, + &types.Value{Val: &types.Value_Int32ListVal{Int32ListVal: &types.Int32List{Val: vals}}}) + case arrow.PrimitiveTypes.Int64: + vals := make([]int64, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = listValues.(*array.Int64).Value(j) + } + values = append(values, + &types.Value{Val: &types.Value_Int64ListVal{Int64ListVal: &types.Int64List{Val: vals}}}) + case arrow.PrimitiveTypes.Float32: + vals := make([]float32, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = listValues.(*array.Float32).Value(j) + } + values = append(values, + &types.Value{Val: &types.Value_FloatListVal{FloatListVal: &types.FloatList{Val: vals}}}) + case arrow.PrimitiveTypes.Float64: + vals := make([]float64, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = listValues.(*array.Float64).Value(j) + } + values = append(values, + &types.Value{Val: &types.Value_DoubleListVal{DoubleListVal: &types.DoubleList{Val: vals}}}) + case arrow.BinaryTypes.Binary: + vals := make([][]byte, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = listValues.(*array.Binary).Value(j) + } + values = append(values, + &types.Value{Val: &types.Value_BytesListVal{BytesListVal: &types.BytesList{Val: vals}}}) + case arrow.BinaryTypes.String: + vals := make([]string, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = listValues.(*array.String).Value(j) + } + values = append(values, + &types.Value{Val: &types.Value_StringListVal{StringListVal: &types.StringList{Val: vals}}}) + case arrow.FixedWidthTypes.Boolean: + vals := make([]bool, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = listValues.(*array.Boolean).Value(j) + } + values = append(values, + &types.Value{Val: &types.Value_BoolListVal{BoolListVal: &types.BoolList{Val: vals}}}) + case arrow.FixedWidthTypes.Time64ns: + vals := make([]int64, int(offsets[idx])-pos) + for j := pos; j < int(offsets[idx]); j++ { + vals[j-pos] = int64(listValues.(*array.Time64).Value(j)) + } + + values = append(values, + &types.Value{Val: &types.Value_UnixTimestampListVal{ + UnixTimestampListVal: &types.Int64List{Val: vals}}}) + + } + + // set the end of current element as start of the next + pos = int(offsets[idx]) + } + + return values, nil + } + + switch arr.DataType() { + case arrow.PrimitiveTypes.Int32: + for _, v := range arr.(*array.Int32).Int32Values() { + values = append(values, &types.Value{Val: &types.Value_Int32Val{Int32Val: v}}) + } + case arrow.PrimitiveTypes.Int64: + for _, v := range arr.(*array.Int64).Int64Values() { + values = append(values, &types.Value{Val: &types.Value_Int64Val{Int64Val: v}}) + } + case arrow.PrimitiveTypes.Float32: + for _, v := range arr.(*array.Float32).Float32Values() { + values = append(values, &types.Value{Val: &types.Value_FloatVal{FloatVal: v}}) + } + case arrow.PrimitiveTypes.Float64: + for _, v := range arr.(*array.Float64).Float64Values() { + values = append(values, &types.Value{Val: &types.Value_DoubleVal{DoubleVal: v}}) + } + case arrow.FixedWidthTypes.Boolean: + for idx := 0; idx < arr.Len(); idx++ { + values = append(values, + &types.Value{Val: &types.Value_BoolVal{BoolVal: arr.(*array.Boolean).Value(idx)}}) + } + case arrow.BinaryTypes.Binary: + for idx := 0; idx < arr.Len(); idx++ { + values = append(values, + &types.Value{Val: &types.Value_BytesVal{BytesVal: arr.(*array.Binary).Value(idx)}}) + } + case arrow.BinaryTypes.String: + for idx := 0; idx < arr.Len(); idx++ { + values = append(values, + &types.Value{Val: &types.Value_StringVal{StringVal: arr.(*array.String).Value(idx)}}) + } + case arrow.FixedWidthTypes.Time64ns: + for idx := 0; idx < arr.Len(); idx++ { + values = append(values, + &types.Value{Val: &types.Value_UnixTimestampVal{ + UnixTimestampVal: int64(arr.(*array.Time64).Value(idx))}}) + } + default: + return nil, fmt.Errorf("unsupported arrow to proto conversion for type %s", arr.DataType()) + } + + return values, nil +} + +func ProtoValuesToArrowArray(protoValues []*types.Value, arrowAllocator memory.Allocator, numRows int) (arrow.Array, error) { + var fieldType arrow.DataType + var err error + + for _, val := range protoValues { + if val != nil { + fieldType, err = ProtoTypeToArrowType(val) + if err != nil { + return nil, err + } + break + } + } + + if fieldType != nil { + builder := array.NewBuilder(arrowAllocator, fieldType) + err = copyProtoValuesToArrowArray(builder, protoValues) + if err != nil { + return nil, err + } + + return builder.NewArray(), nil + } else { + return array.NewNull(numRows), nil + } +} diff --git a/go/types/typeconversion_test.go b/go/types/typeconversion_test.go new file mode 100644 index 00000000000..05fc32f63ac --- /dev/null +++ b/go/types/typeconversion_test.go @@ -0,0 +1,80 @@ +package types + +import ( + "github.com/apache/arrow/go/v8/arrow/memory" + "github.com/feast-dev/feast/go/protos/feast/types" + "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +var ( + PROTO_VALUES = [][]*types.Value{ + {{Val: &types.Value_Int32Val{10}}, {Val: &types.Value_Int32Val{20}}}, + {{Val: &types.Value_Int64Val{10}}, {Val: &types.Value_Int64Val{20}}}, + {{Val: &types.Value_FloatVal{1.0}}, {Val: &types.Value_FloatVal{2.0}}}, + {{Val: &types.Value_DoubleVal{1.0}}, {Val: &types.Value_DoubleVal{2.0}}}, + {{Val: &types.Value_StringVal{"aaa"}}, {Val: &types.Value_StringVal{"bbb"}}}, + {{Val: &types.Value_BytesVal{[]byte{1, 2, 3}}}, {Val: &types.Value_BytesVal{[]byte{4, 5, 6}}}}, + {{Val: &types.Value_BoolVal{true}}, {Val: &types.Value_BoolVal{false}}}, + {{Val: &types.Value_UnixTimestampVal{time.Now().Unix()}}, + {Val: &types.Value_UnixTimestampVal{time.Now().Unix()}}}, + + { + {Val: &types.Value_Int32ListVal{&types.Int32List{Val: []int32{0, 1, 2}}}}, + {Val: &types.Value_Int32ListVal{&types.Int32List{Val: []int32{3, 4, 5}}}}, + }, + { + {Val: &types.Value_Int64ListVal{&types.Int64List{Val: []int64{0, 1, 2}}}}, + {Val: &types.Value_Int64ListVal{&types.Int64List{Val: []int64{3, 4, 5}}}}, + }, + { + {Val: &types.Value_FloatListVal{&types.FloatList{Val: []float32{0.5, 1.5, 2}}}}, + {Val: &types.Value_FloatListVal{&types.FloatList{Val: []float32{3.5, 4, 5}}}}, + }, + { + {Val: &types.Value_DoubleListVal{&types.DoubleList{Val: []float64{0.5, 1, 2}}}}, + {Val: &types.Value_DoubleListVal{&types.DoubleList{Val: []float64{3.5, 4, 5}}}}, + }, + { + {Val: &types.Value_BytesListVal{&types.BytesList{Val: [][]byte{{0, 1}, {2}}}}}, + {Val: &types.Value_BytesListVal{&types.BytesList{Val: [][]byte{{3, 4}, {5}}}}}, + }, + { + {Val: &types.Value_StringListVal{&types.StringList{Val: []string{"aa", "bb"}}}}, + {Val: &types.Value_StringListVal{&types.StringList{Val: []string{"cc", "dd"}}}}, + }, + { + {Val: &types.Value_BoolListVal{&types.BoolList{Val: []bool{false, false}}}}, + {Val: &types.Value_BoolListVal{&types.BoolList{Val: []bool{true, true}}}}, + }, + { + {Val: &types.Value_UnixTimestampListVal{&types.Int64List{Val: []int64{time.Now().Unix()}}}}, + {Val: &types.Value_UnixTimestampListVal{&types.Int64List{Val: []int64{time.Now().Unix()}}}}, + }, + } +) + +func TestConversionBetweenProtoAndArrow(t *testing.T) { + pool := memory.NewGoAllocator() + for _, vector := range PROTO_VALUES { + arrowArray, err := ProtoValuesToArrowArray(vector, pool, len(vector)) + assert.Nil(t, err) + + protoValues, err := ArrowValuesToProtoValues(arrowArray) + assert.Nil(t, err) + + protoValuesEquals(t, vector, protoValues) + } + +} + +func protoValuesEquals(t *testing.T, a, b []*types.Value) { + assert.Equal(t, len(a), len(b)) + + for idx, left := range a { + assert.Truef(t, proto.Equal(left, b[idx]), + "Arrays are not equal. Diff[%d] %v != %v", idx, left, b[idx]) + } +} diff --git a/infra/charts/feast-python-server/Chart.yaml b/infra/charts/feast-python-server/Chart.yaml index 6e3773af725..1c1271b11e4 100644 --- a/infra/charts/feast-python-server/Chart.yaml +++ b/infra/charts/feast-python-server/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: feast-python-server description: Feast Feature Server in Python type: application -version: 0.19.0 +version: 0.20.0 keywords: - machine learning - big data diff --git a/infra/charts/feast-python-server/README.md b/infra/charts/feast-python-server/README.md index 5182d4c451d..02a8054799b 100644 --- a/infra/charts/feast-python-server/README.md +++ b/infra/charts/feast-python-server/README.md @@ -1,6 +1,6 @@ # feast-python-server -![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![Version: 0.20.0](https://img.shields.io/badge/Version-0.20.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) Feast Feature Server in Python diff --git a/infra/charts/feast/Chart.yaml b/infra/charts/feast/Chart.yaml index ef47acb778a..f526e0a7386 100644 --- a/infra/charts/feast/Chart.yaml +++ b/infra/charts/feast/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v1 description: Feature store for machine learning name: feast -version: 0.19.0 +version: 0.20.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/README.md b/infra/charts/feast/README.md index 7a62bd2a56c..de28d54d8e3 100644 --- a/infra/charts/feast/README.md +++ b/infra/charts/feast/README.md @@ -8,7 +8,7 @@ This repo contains Helm charts for Feast components that are being installed on ## Chart: Feast -Feature store for machine learning Current chart version is `0.19.0` +Feature store for machine learning Current chart version is `0.20.0` ## Installation @@ -55,8 +55,8 @@ For more details, please see: https://docs.feast.dev/how-to-guides/running-feast | Repository | Name | Version | |------------|------|---------| | https://charts.helm.sh/stable | redis | 10.5.6 | -| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.19.0 | -| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.19.0 | +| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.20.0 | +| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.20.0 | ## Values diff --git a/infra/charts/feast/charts/feature-server/Chart.yaml b/infra/charts/feast/charts/feature-server/Chart.yaml index 7e58368ab01..492a0f3b616 100644 --- a/infra/charts/feast/charts/feature-server/Chart.yaml +++ b/infra/charts/feast/charts/feature-server/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Feast Feature Server: Online feature serving service for Feast" name: feature-server -version: 0.19.0 -appVersion: v0.19.0 +version: 0.20.0 +appVersion: v0.20.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/feature-server/README.md b/infra/charts/feast/charts/feature-server/README.md index 74596103572..43d4787d7b2 100644 --- a/infra/charts/feast/charts/feature-server/README.md +++ b/infra/charts/feast/charts/feature-server/README.md @@ -1,6 +1,6 @@ # feature-server -![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) +![Version: 0.20.0](https://img.shields.io/badge/Version-0.20.0-informational?style=flat-square) ![AppVersion: v0.20.0](https://img.shields.io/badge/AppVersion-v0.20.0-informational?style=flat-square) Feast Feature Server: Online feature serving service for Feast @@ -17,7 +17,7 @@ Feast Feature Server: Online feature serving service for Feast | envOverrides | object | `{}` | Extra environment variables to set | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | | image.repository | string | `"feastdev/feature-server-java"` | Docker image for Feature Server repository | -| image.tag | string | `"0.19.0"` | Image tag | +| image.tag | string | `"0.20.0"` | Image tag | | ingress.grpc.annotations | object | `{}` | Extra annotations for the ingress | | ingress.grpc.auth.enabled | bool | `false` | Flag to enable auth | | ingress.grpc.class | string | `"nginx"` | Which ingress controller to use | diff --git a/infra/charts/feast/charts/feature-server/values.yaml b/infra/charts/feast/charts/feature-server/values.yaml index 99a9bf460d9..c8089b4d5e6 100644 --- a/infra/charts/feast/charts/feature-server/values.yaml +++ b/infra/charts/feast/charts/feature-server/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Feature Server repository repository: feastdev/feature-server-java # image.tag -- Image tag - tag: 0.19.0 + tag: 0.20.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent diff --git a/infra/charts/feast/charts/transformation-service/Chart.yaml b/infra/charts/feast/charts/transformation-service/Chart.yaml index 0e1d26e6678..8fd50e76641 100644 --- a/infra/charts/feast/charts/transformation-service/Chart.yaml +++ b/infra/charts/feast/charts/transformation-service/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Transformation service: to compute on-demand features" name: transformation-service -version: 0.19.0 -appVersion: v0.19.0 +version: 0.20.0 +appVersion: v0.20.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/transformation-service/README.md b/infra/charts/feast/charts/transformation-service/README.md index 7747fabc610..5324c191eec 100644 --- a/infra/charts/feast/charts/transformation-service/README.md +++ b/infra/charts/feast/charts/transformation-service/README.md @@ -1,6 +1,6 @@ # transformation-service -![Version: 0.19.0](https://img.shields.io/badge/Version-0.19.0-informational?style=flat-square) ![AppVersion: v0.19.0](https://img.shields.io/badge/AppVersion-v0.19.0-informational?style=flat-square) +![Version: 0.20.0](https://img.shields.io/badge/Version-0.20.0-informational?style=flat-square) ![AppVersion: v0.20.0](https://img.shields.io/badge/AppVersion-v0.20.0-informational?style=flat-square) Transformation service: to compute on-demand features @@ -13,7 +13,7 @@ Transformation service: to compute on-demand features | envOverrides | object | `{}` | Extra environment variables to set | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | | image.repository | string | `"feastdev/feature-transformation-server"` | Docker image for Transformation Server repository | -| image.tag | string | `"0.19.0"` | Image tag | +| image.tag | string | `"0.20.0"` | Image tag | | nodeSelector | object | `{}` | Node labels for pod assignment | | podLabels | object | `{}` | Labels to be added to Feast Serving pods | | replicaCount | int | `1` | Number of pods that will be created | diff --git a/infra/charts/feast/charts/transformation-service/values.yaml b/infra/charts/feast/charts/transformation-service/values.yaml index f76fa979799..248f9faac3d 100644 --- a/infra/charts/feast/charts/transformation-service/values.yaml +++ b/infra/charts/feast/charts/transformation-service/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Transformation Server repository repository: feastdev/feature-transformation-server # image.tag -- Image tag - tag: 0.19.0 + tag: 0.20.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent diff --git a/infra/charts/feast/requirements.yaml b/infra/charts/feast/requirements.yaml index 2839b039ca4..e0eb8368af6 100644 --- a/infra/charts/feast/requirements.yaml +++ b/infra/charts/feast/requirements.yaml @@ -1,12 +1,12 @@ dependencies: - name: feature-server alias: feature-server - version: 0.19.0 + version: 0.20.0 condition: feature-server.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: transformation-service alias: transformation-service - version: 0.19.0 + version: 0.20.0 condition: transformation-service.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: redis diff --git a/infra/scripts/version_bump/bump_file_versions.py b/infra/scripts/release/bump_file_versions.py similarity index 95% rename from infra/scripts/version_bump/bump_file_versions.py rename to infra/scripts/release/bump_file_versions.py index b87c3392fbe..b706c2c141b 100644 --- a/infra/scripts/version_bump/bump_file_versions.py +++ b/infra/scripts/release/bump_file_versions.py @@ -4,7 +4,7 @@ import sys USAGE = f"Usage: python {sys.argv[0]} [--help] | current_semver_version new_semver_version]" -VERSIONS_TO_BUMP = 26 +VERSIONS_TO_BUMP = 27 def main() -> None: @@ -27,7 +27,7 @@ def main() -> None: # Get git repo root directory repo_root = pathlib.Path(__file__).resolve().parent.parent.parent.parent - path_to_file_list = repo_root.joinpath("infra", "scripts", "version_bump", "files_to_bump.txt") + path_to_file_list = repo_root.joinpath("infra", "scripts", "release", "files_to_bump.txt") # Get files to bump versions within with open(path_to_file_list, "r") as f: @@ -57,6 +57,8 @@ def main() -> None: current_version = current_version_patch found = True break + else: + print(f"Found {versions_in_files} occurrences of {current_version_patch}, instead of {VERSIONS_TO_BUMP}") if not found: raise SystemExit(f"Could not find {VERSIONS_TO_BUMP} versions of {current_version} in {path_to_file_list}") diff --git a/infra/scripts/version_bump/files_to_bump.txt b/infra/scripts/release/files_to_bump.txt similarity index 94% rename from infra/scripts/version_bump/files_to_bump.txt rename to infra/scripts/release/files_to_bump.txt index 7b086081d9c..2c3eece6bef 100644 --- a/infra/scripts/version_bump/files_to_bump.txt +++ b/infra/scripts/release/files_to_bump.txt @@ -9,4 +9,5 @@ infra/charts/feast/charts/feature-server/values.yaml infra/charts/feast/README.md infra/charts/feast-python-server/Chart.yaml infra/charts/feast-python-server/README.md -java/pom.xml \ No newline at end of file +java/pom.xml +ui/package.json \ No newline at end of file diff --git a/infra/scripts/release/unset_prerelease.py b/infra/scripts/release/unset_prerelease.py new file mode 100644 index 00000000000..4a2ba131970 --- /dev/null +++ b/infra/scripts/release/unset_prerelease.py @@ -0,0 +1,70 @@ +# For some reason patch releases with Semantic Release are tagged as "pre-release" on GitHub. This script +# removes the "pre-release" tag from the release. +import os +import sys +import requests + +USAGE = f"Usage: python {sys.argv[0]} [--help] | version_being_released (e.g., v0.19.1)]" + + +def get_prerelease_status(version_being_released, token): + url = f"https://api.github.com/repos/feast-dev/feast/releases/tags/v{version_being_released}" + + headers = { + "Content-Type": "application/json", + "Accept": "application/vnd.github.v3+json", + "Authorization": f"Bearer {token}" + } + + response = requests.request("GET", url, headers=headers) + response_json = response.json() + return bool(response_json['prerelease']), response_json['id'] + + +def set_prerelease_status(release_id, status, token): + url = f"https://api.github.com/repos/feast-dev/feast/releases/{release_id}" + + payload = {"prerelease": status} + + headers = { + "Content-Type": "application/json", + "Accept": "application/vnd.github.v3+json", + "Authorization": f"Bearer {token}" + } + + requests.request("PATCH", url, json=payload, headers=headers) + + +def main() -> None: + args = sys.argv[1:] + if not args or len(args) != 1: + raise SystemExit(USAGE) + + version_being_released = args[0].strip() # should look like 0.19.1 (without the v) + + print(f"Disabling prerelease status for {version_being_released}") + + token = os.getenv('GITHUB_TOKEN', default=None) + + if token is None: + raise OSError("GITHUB_TOKEN environmental variable is not set") + + is_prerelease, release_id = get_prerelease_status(version_being_released, token) + + if is_prerelease: + set_prerelease_status(release_id, False, token) + else: + print(f"{version_being_released} is not a pre-release, exiting.") + exit(0) + + is_prerelease, release_id = get_prerelease_status(version_being_released, token) + + if is_prerelease: + import warnings + warnings.warn(f"Failed to unset prerelease status for {version_being_released} release id {release_id}") + else: + print(f"Successfully unset prerelease status for {version_being_released} release id {release_id}") + + +if __name__ == "__main__": + main() diff --git a/infra/scripts/test-golang-sdk.sh b/infra/scripts/test-golang-sdk.sh deleted file mode 100755 index 666f6c12d0c..00000000000 --- a/infra/scripts/test-golang-sdk.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -o pipefail - -make lint-go - -cd sdk/go -go test -v 2>&1 | tee /tmp/test_output -TEST_EXIT_CODE=$? - -# Default artifact location setting in Prow jobs -LOGS_ARTIFACT_PATH=/logs/artifacts - -go get -u github.com/jstemmer/go-junit-report -cat /tmp/test_output | ${GOPATH}/bin/go-junit-report > ${LOGS_ARTIFACT_PATH}/golang-sdk-test-report.xml - -exit ${TEST_EXIT_CODE} \ No newline at end of file diff --git a/java/common/pom.xml b/java/common/pom.xml index e5a648a7f95..6b580880f13 100644 --- a/java/common/pom.xml +++ b/java/common/pom.xml @@ -75,12 +75,12 @@ com.fasterxml.jackson.core jackson-databind - 2.10.5.1 + 2.12.6.1 com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.10.1 + ${jackson.version} diff --git a/java/pom.xml b/java/pom.xml index c11e7f7df28..4a4049305b5 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -38,7 +38,7 @@ - 0.19.0 + 0.20.0 https://github.com/feast-dev/feast UTF-8 @@ -64,6 +64,7 @@ 1.5.24 3.14.7 3.10 + 2.12.6 2.3.1 1.3.2 2.0.1.Final diff --git a/java/serving/pom.xml b/java/serving/pom.xml index 8c81dfa7e72..47a636d7d5f 100644 --- a/java/serving/pom.xml +++ b/java/serving/pom.xml @@ -301,13 +301,13 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml - 2.11.0 + ${jackson.version} com.fasterxml.jackson.core jackson-annotations - 2.12.2 + ${jackson.version} diff --git a/java/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java b/java/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java index f4e330fbf73..12e8a5b158e 100644 --- a/java/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java +++ b/java/serving/src/main/java/feast/serving/service/OnlineServingServiceV2.java @@ -88,16 +88,16 @@ public ServingAPIProto.GetOnlineFeaturesResponse getOnlineFeatures( .collect(Collectors.toList()); // ToDo (pyalex): refactor transformation service to delete unused left part of the returned - // Pair from extractRequestDataFeatureNamesAndOnDemandFeatureInputs. + // Pair from extractRequestDataFeatureNamesAndOnDemandFeatureSources. // Currently, we can retrieve context variables directly from GetOnlineFeaturesRequest. - List onDemandFeatureInputs = + List onDemandFeatureSources = this.onlineTransformationService.extractOnDemandFeaturesDependencies( onDemandFeatureReferences); - // Add on demand feature inputs to list of feature references to retrieve. - for (FeatureReferenceV2 onDemandFeatureInput : onDemandFeatureInputs) { - if (!retrievedFeatureReferences.contains(onDemandFeatureInput)) { - retrievedFeatureReferences.add(onDemandFeatureInput); + // Add on demand feature sources to list of feature references to retrieve. + for (FeatureReferenceV2 onDemandFeatureSource : onDemandFeatureSources) { + if (!retrievedFeatureReferences.contains(onDemandFeatureSource)) { + retrievedFeatureReferences.add(onDemandFeatureSource); } } @@ -194,7 +194,7 @@ public ServingAPIProto.GetOnlineFeaturesResponse getOnlineFeatures( // data. this.populateOnDemandFeatures( onDemandFeatureReferences, - onDemandFeatureInputs, + onDemandFeatureSources, retrievedFeatureReferences, request, features, @@ -257,7 +257,7 @@ private List> getEntityRows( private void populateOnDemandFeatures( List onDemandFeatureReferences, - List onDemandFeatureInputs, + List onDemandFeatureSources, List retrievedFeatureReferences, ServingAPIProto.GetOnlineFeaturesRequest request, List> features, @@ -271,7 +271,7 @@ private void populateOnDemandFeatures( for (int featureIdx = 0; featureIdx < retrievedFeatureReferences.size(); featureIdx++) { FeatureReferenceV2 featureReference = retrievedFeatureReferences.get(featureIdx); - if (!onDemandFeatureInputs.contains(featureReference)) { + if (!onDemandFeatureSources.contains(featureReference)) { continue; } diff --git a/java/serving/src/main/java/feast/serving/service/OnlineTransformationService.java b/java/serving/src/main/java/feast/serving/service/OnlineTransformationService.java index d1df763f6ed..365432b84e1 100644 --- a/java/serving/src/main/java/feast/serving/service/OnlineTransformationService.java +++ b/java/serving/src/main/java/feast/serving/service/OnlineTransformationService.java @@ -83,55 +83,55 @@ public TransformFeaturesResponse transformFeatures( @Override public List extractOnDemandFeaturesDependencies( List onDemandFeatureReferences) { - List onDemandFeatureInputs = new ArrayList<>(); + List onDemandFeatureSources = new ArrayList<>(); for (ServingAPIProto.FeatureReferenceV2 featureReference : onDemandFeatureReferences) { OnDemandFeatureViewProto.OnDemandFeatureViewSpec onDemandFeatureViewSpec = this.registryRepository.getOnDemandFeatureViewSpec(featureReference); - Map inputs = - onDemandFeatureViewSpec.getInputsMap(); + Map sources = + onDemandFeatureViewSpec.getSourcesMap(); - for (OnDemandFeatureViewProto.OnDemandInput input : inputs.values()) { - OnDemandFeatureViewProto.OnDemandInput.InputCase inputCase = input.getInputCase(); - switch (inputCase) { + for (OnDemandFeatureViewProto.OnDemandSource source : sources.values()) { + OnDemandFeatureViewProto.OnDemandSource.SourceCase sourceCase = source.getSourceCase(); + switch (sourceCase) { case REQUEST_DATA_SOURCE: // Do nothing. The value should be provided as dedicated request parameter break; case FEATURE_VIEW_PROJECTION: FeatureReferenceProto.FeatureViewProjection projection = - input.getFeatureViewProjection(); + source.getFeatureViewProjection(); for (FeatureProto.FeatureSpecV2 featureSpec : projection.getFeatureColumnsList()) { String featureName = featureSpec.getName(); - ServingAPIProto.FeatureReferenceV2 onDemandFeatureInput = + ServingAPIProto.FeatureReferenceV2 onDemandFeatureSource = ServingAPIProto.FeatureReferenceV2.newBuilder() .setFeatureViewName(projection.getFeatureViewName()) .setFeatureName(featureName) .build(); - onDemandFeatureInputs.add(onDemandFeatureInput); + onDemandFeatureSources.add(onDemandFeatureSource); } break; case FEATURE_VIEW: - FeatureViewProto.FeatureView featureView = input.getFeatureView(); + FeatureViewProto.FeatureView featureView = source.getFeatureView(); FeatureViewProto.FeatureViewSpec featureViewSpec = featureView.getSpec(); String featureViewName = featureViewSpec.getName(); for (FeatureProto.FeatureSpecV2 featureSpec : featureViewSpec.getFeaturesList()) { String featureName = featureSpec.getName(); - ServingAPIProto.FeatureReferenceV2 onDemandFeatureInput = + ServingAPIProto.FeatureReferenceV2 onDemandFeatureSource = ServingAPIProto.FeatureReferenceV2.newBuilder() .setFeatureViewName(featureViewName) .setFeatureName(featureName) .build(); - onDemandFeatureInputs.add(onDemandFeatureInput); + onDemandFeatureSources.add(onDemandFeatureSource); } break; default: throw Status.INTERNAL .withDescription( - "OnDemandInput proto input field has an unexpected type: " + inputCase) + "OnDemandSource proto source field has an unexpected type: " + sourceCase) .asRuntimeException(); } } } - return onDemandFeatureInputs; + return onDemandFeatureSources; } /** {@inheritDoc} */ @@ -321,8 +321,8 @@ public ValueType serializeValuesIntoArrowIPC(List extractOnDemandFeaturesDependencies( List onDemandFeatureReferences); diff --git a/java/serving/src/test/java/feast/serving/util/DataGenerator.java b/java/serving/src/test/java/feast/serving/util/DataGenerator.java index c6c11a9bf78..e38d1ce4596 100644 --- a/java/serving/src/test/java/feast/serving/util/DataGenerator.java +++ b/java/serving/src/test/java/feast/serving/util/DataGenerator.java @@ -158,7 +158,7 @@ public static FeatureTableSpec createFeatureTableSpec( .setMaxAge(Duration.newBuilder().setSeconds(3600).build()) .setBatchSource( DataSource.newBuilder() - .setEventTimestampColumn("ts") + .setTimestampField("ts") .setType(DataSource.SourceType.BATCH_FILE) .setFileOptions( FileOptions.newBuilder() @@ -166,7 +166,7 @@ public static FeatureTableSpec createFeatureTableSpec( FileFormat.newBuilder() .setParquetFormat(ParquetFormat.newBuilder().build()) .build()) - .setFileUrl("/dev/null") + .setUri("/dev/null") .build()) .build()) .putAllLabels(labels) @@ -203,22 +203,18 @@ public static DataSource createFileDataSourceSpec( return DataSource.newBuilder() .setType(DataSource.SourceType.BATCH_FILE) .setFileOptions( - FileOptions.newBuilder() - .setFileFormat(createParquetFormat()) - .setFileUrl(fileURL) - .build()) - .setEventTimestampColumn(timestampColumn) + FileOptions.newBuilder().setFileFormat(createParquetFormat()).setUri(fileURL).build()) + .setTimestampField(timestampColumn) .setDatePartitionColumn(datePartitionColumn) .build(); } public static DataSource createBigQueryDataSourceSpec( - String bigQueryTableRef, String timestampColumn, String datePartitionColumn) { + String bigQueryTable, String timestampColumn, String datePartitionColumn) { return DataSource.newBuilder() .setType(DataSource.SourceType.BATCH_BIGQUERY) - .setBigqueryOptions( - DataSource.BigQueryOptions.newBuilder().setTableRef(bigQueryTableRef).build()) - .setEventTimestampColumn(timestampColumn) + .setBigqueryOptions(DataSource.BigQueryOptions.newBuilder().setTable(bigQueryTable).build()) + .setTimestampField(timestampColumn) .setDatePartitionColumn(datePartitionColumn) .build(); } @@ -233,7 +229,7 @@ public static DataSource createKafkaDataSourceSpec( .setBootstrapServers(servers) .setMessageFormat(createProtoFormat("class.path")) .build()) - .setEventTimestampColumn(timestampColumn) + .setTimestampField(timestampColumn) .build(); } @@ -295,7 +291,7 @@ public static DataSource createKinesisDataSourceSpec( .setStreamName("stream") .setRecordFormat(createProtoFormat(classPath)) .build()) - .setEventTimestampColumn(timestampColumn) + .setTimestampField(timestampColumn) .build(); } diff --git a/java/serving/src/test/resources/docker-compose/feast10/definitions.py b/java/serving/src/test/resources/docker-compose/feast10/definitions.py index c7ed6c96193..374408a20bd 100644 --- a/java/serving/src/test/resources/docker-compose/feast10/definitions.py +++ b/java/serving/src/test/resources/docker-compose/feast10/definitions.py @@ -1,20 +1,19 @@ import pandas as pd - -from google.protobuf.duration_pb2 import Duration - -from feast.value_type import ValueType -from feast.feature import Feature -from feast.feature_view import FeatureView +from feast.data_source import RequestSource from feast.entity import Entity from feast.feature_service import FeatureService -from feast.on_demand_feature_view import RequestDataSource, on_demand_feature_view +from feast.feature_view import FeatureView +from feast.field import Field +from feast.on_demand_feature_view import on_demand_feature_view +from feast.types import Float32, Float64, Int64 +from feast.value_type import ValueType +from google.protobuf.duration_pb2 import Duration from feast import FileSource - file_path = "driver_stats.parquet" driver_hourly_stats = FileSource( path=file_path, - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) @@ -29,10 +28,10 @@ name="driver_hourly_stats", entities=["driver_id"], ttl=Duration(seconds=86400 * 7), - features=[ - Feature(name="conv_rate", dtype=ValueType.DOUBLE), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + schema=[ + Field(name="conv_rate", dtype=Float64), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], online=True, batch_source=driver_hourly_stats, @@ -40,51 +39,45 @@ ) -input_request = RequestDataSource( +input_request = RequestSource( name="vals_to_add", - schema={ - "val_to_add": ValueType.INT64, - "val_to_add_2": ValueType.INT64 - } + schema=[ + Field(name="val_to_add", dtype=Int64), + Field(name="val_to_add_2", dtype=Int64), + Field(name="avg_daily_trips", dtype=Int64), + ], ) @on_demand_feature_view( - inputs={ - 'driver_hourly_stats': driver_hourly_stats_view, - 'vals_to_add': input_request - }, - features=[ - Feature(name='conv_rate_plus_val1', dtype=ValueType.DOUBLE), - Feature(name='conv_rate_plus_val2', dtype=ValueType.DOUBLE) - ] + sources={ + "driver_hourly_stats": driver_hourly_stats_view, + "vals_to_add": input_request, + }, + schema=[ + Field(name="conv_rate_plus_val1", dtype=Float64), + Field(name="conv_rate_plus_val2", dtype=Float64), + ], ) def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: df = pd.DataFrame() - df['conv_rate_plus_val1'] = (features_df['conv_rate'] + features_df['val_to_add']) - df['conv_rate_plus_val2'] = (features_df['conv_rate'] + features_df['val_to_add_2']) + df["conv_rate_plus_val1"] = features_df["conv_rate"] + features_df["val_to_add"] + df["conv_rate_plus_val2"] = features_df["conv_rate"] + features_df["val_to_add_2"] return df generated_data_source = FileSource( - path="benchmark_data.parquet", - event_timestamp_column="event_timestamp", + path="benchmark_data.parquet", timestamp_field="event_timestamp", ) -entity = Entity( - name="entity", - value_type=ValueType.STRING, -) +entity = Entity(name="entity", value_type=ValueType.STRING,) benchmark_feature_views = [ FeatureView( name=f"feature_view_{i}", entities=["entity"], ttl=Duration(seconds=86400), - features=[ - Feature(name=f"feature_{10 * i + j}", dtype=ValueType.INT64) - for j in range(10) - ], + schema=[Field(name=f"feature_{10 * i + j}", dtype=Int64) for j in range(10)], online=True, batch_source=generated_data_source, ) @@ -92,6 +85,5 @@ def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: ] benchmark_feature_service = FeatureService( - name=f"benchmark_feature_service", - features=benchmark_feature_views, + name=f"benchmark_feature_service", features=benchmark_feature_views, ) diff --git a/java/serving/src/test/resources/docker-compose/feast10/materialize.py b/java/serving/src/test/resources/docker-compose/feast10/materialize.py index 8389d8527bf..404fec27e12 100644 --- a/java/serving/src/test/resources/docker-compose/feast10/materialize.py +++ b/java/serving/src/test/resources/docker-compose/feast10/materialize.py @@ -1,12 +1,17 @@ -import pandas as pd -import numpy as np - from datetime import datetime, timedelta -from feast import FeatureStore -from definitions import driver_hourly_stats_view, driver, entity,\ - benchmark_feature_service, benchmark_feature_views, transformed_conv_rate +import numpy as np +import pandas as pd +from definitions import ( + benchmark_feature_service, + benchmark_feature_views, + driver, + driver_hourly_stats_view, + entity, + transformed_conv_rate, +) +from feast import FeatureStore print("Running materialize.py") @@ -21,7 +26,9 @@ df["avg_daily_trips"] = np.arange(0, 1000, 100) # some of rows are beyond 7 days to test OUTSIDE_MAX_AGE status -df["event_timestamp"] = start + pd.Series(np.arange(0, 10)).map(lambda days: timedelta(days=days)) +df["event_timestamp"] = start + pd.Series(np.arange(0, 10)).map( + lambda days: timedelta(days=days) +) # Store data in parquet files. Parquet is convenient for local development mode. For # production, you can use your favorite DWH, such as BigQuery. See Feast documentation @@ -41,21 +48,27 @@ def generate_data(num_rows: int, num_features: int, destination: str) -> pd.Data for column in features: df[column] = np.random.randint(1, num_rows, num_rows) - df["entity"] = "key-" + \ - pd.Series(np.arange(1, num_rows + 1)).astype(pd.StringDtype()) + df["entity"] = "key-" + pd.Series(np.arange(1, num_rows + 1)).astype( + pd.StringDtype() + ) df.to_parquet(destination) -generate_data(10**3, 250, "benchmark_data.parquet") +generate_data(10 ** 3, 250, "benchmark_data.parquet") fs = FeatureStore(".") -fs.apply([driver_hourly_stats_view, - transformed_conv_rate, - driver, - entity, benchmark_feature_service, - *benchmark_feature_views]) +fs.apply( + [ + driver_hourly_stats_view, + transformed_conv_rate, + driver, + entity, + benchmark_feature_service, + *benchmark_feature_views, + ] +) now = datetime.now() fs.materialize(start, now) diff --git a/protos/feast/core/DataFormat.proto b/protos/feast/core/DataFormat.proto index 2926e08c630..9fd01e865c2 100644 --- a/protos/feast/core/DataFormat.proto +++ b/protos/feast/core/DataFormat.proto @@ -18,7 +18,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "DataFormatProto"; option java_package = "feast.proto.core"; diff --git a/protos/feast/core/DataSource.proto b/protos/feast/core/DataSource.proto index 82f6c4ab4a6..d958281ca2c 100644 --- a/protos/feast/core/DataSource.proto +++ b/protos/feast/core/DataSource.proto @@ -18,22 +18,23 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "DataSourceProto"; option java_package = "feast.proto.core"; import "feast/core/DataFormat.proto"; import "feast/types/Value.proto"; +import "feast/core/Feature.proto"; // Defines a Data Source that can be used source Feature data -// Next available id: 22 +// Next available id: 28 message DataSource { // Field indexes should *not* be reused. Not sure if fields 6-10 were used previously or not, // but they are going to be reserved for backwards compatibility. reserved 6 to 10; // Type of Data Source. - // Next available id: 9 + // Next available id: 12 enum SourceType { INVALID = 0; BATCH_FILE = 1; @@ -44,7 +45,9 @@ message DataSource { STREAM_KINESIS = 4; CUSTOM_SOURCE = 6; REQUEST_SOURCE = 7; - + PUSH_SOURCE = 9; + BATCH_TRINO = 10; + BATCH_SPARK = 11; } // Unique name of data source within the project @@ -53,6 +56,12 @@ message DataSource { // Name of Feast project that this data source belongs to. string project = 21; + string description = 23; + + map tags = 24; + + string owner = 25; + SourceType type = 1; // Defines mapping between fields in the sourced data @@ -60,7 +69,7 @@ message DataSource { map field_mapping = 2; // Must specify event timestamp column name - string event_timestamp_column = 3; + string timestamp_field = 3; // (Optional) Specify partition column // useful for file sources @@ -71,8 +80,14 @@ message DataSource { // This is an internal field that is represents the python class for the data source object a proto object represents. // This should be set by feast, and not by users. + // The field is used primarily by custom data sources and is mandatory for them to set. Feast may set it for + // first party sources as well. string data_source_class_type = 17; + // Optional batch source for streaming sources for historical features and materialization. + DataSource batch_source = 26; + + // Defines options for DataSource that sources features from a file message FileOptions { FileFormat file_format = 1; @@ -81,7 +96,7 @@ message DataSource { // s3://path/to/file for AWS S3 storage // gs://path/to/file for GCP GCS storage // file:///path/to/file for local storage - string file_url = 2; + string uri = 2; // override AWS S3 storage endpoint with custom S3 endpoint string s3_endpoint_override = 3; @@ -90,7 +105,17 @@ message DataSource { // Defines options for DataSource that sources features from a BigQuery Query message BigQueryOptions { // Full table reference in the form of [project:dataset.table] - string table_ref = 1; + string table = 1; + + // SQL query that returns a table containing feature data. Must contain an event_timestamp column, and respective + // entity columns + string query = 2; + } + + // Defines options for DataSource that sources features from a Trino Query + message TrinoOptions { + // Full table reference in the form of [project:dataset.table] + string table = 1; // SQL query that returns a table containing feature data. Must contain an event_timestamp column, and respective // entity columns @@ -109,6 +134,7 @@ message DataSource { // Defines the stream data format encoding feature/entity data in Kafka messages. StreamFormat message_format = 3; + } // Defines options for DataSource that sources features from Kinesis records. @@ -137,6 +163,9 @@ message DataSource { // Redshift schema name string schema = 3; + + // Redshift database name + string database = 4; } // Defines options for DataSource that sources features from a Snowflake Query @@ -153,6 +182,24 @@ message DataSource { // Snowflake schema name string database = 4; + + // Snowflake warehouse name + string warehouse = 5; + } + + // Defines options for DataSource that sources features from a spark table/query + message SparkOptions { + // Table name + string table = 1; + + // Spark SQl query that returns the table, this is an alternative to `table` + string query = 2; + + // Path from which spark can read the table, this is an alternative to `table` + string path = 3; + + // Format of files at `path` (e.g. parquet, avro, etc) + string file_format = 4; } // Defines configuration for custom third-party data sources. @@ -166,9 +213,20 @@ message DataSource { message RequestDataOptions { reserved 1; // Mapping of feature name to type - map schema = 2; + map deprecated_schema = 2; + + repeated FeatureSpecV2 schema = 3; + + } + + // Defines options for DataSource that supports pushing data to it. This allows data to be pushed to + // the online store on-demand, such as by stream consumers. + message PushOptions { + // Mapping of feature name to type + map schema = 1; } + // DataSource options. oneof options { FileOptions file_options = 11; @@ -179,5 +237,8 @@ message DataSource { RequestDataOptions request_data_options = 18; CustomSourceOptions custom_options = 16; SnowflakeOptions snowflake_options = 19; + PushOptions push_options = 22; + SparkOptions spark_options = 27; + TrinoOptions trino_options = 30; } } diff --git a/protos/feast/core/DatastoreTable.proto b/protos/feast/core/DatastoreTable.proto index 15720ad809c..4246a6ae6e7 100644 --- a/protos/feast/core/DatastoreTable.proto +++ b/protos/feast/core/DatastoreTable.proto @@ -19,7 +19,7 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "DatastoreTableProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; import "google/protobuf/wrappers.proto"; diff --git a/protos/feast/core/DynamoDBTable.proto b/protos/feast/core/DynamoDBTable.proto index 1ab77febbd3..4e5c8714e84 100644 --- a/protos/feast/core/DynamoDBTable.proto +++ b/protos/feast/core/DynamoDBTable.proto @@ -19,7 +19,7 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "DynamoDBTableProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; // Represents a DynamoDB table message DynamoDBTable { diff --git a/protos/feast/core/Entity.proto b/protos/feast/core/Entity.proto index cd54c649229..d8d8bedc5eb 100644 --- a/protos/feast/core/Entity.proto +++ b/protos/feast/core/Entity.proto @@ -19,7 +19,7 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "EntityProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; import "feast/types/Value.proto"; import "google/protobuf/timestamp.proto"; diff --git a/protos/feast/core/Feature.proto b/protos/feast/core/Feature.proto index ea0d340a008..a96423bfbde 100644 --- a/protos/feast/core/Feature.proto +++ b/protos/feast/core/Feature.proto @@ -18,7 +18,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "FeatureProto"; option java_package = "feast.proto.core"; diff --git a/protos/feast/core/FeatureService.proto b/protos/feast/core/FeatureService.proto index 4aaa0d5f06f..2295677583a 100644 --- a/protos/feast/core/FeatureService.proto +++ b/protos/feast/core/FeatureService.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "FeatureServiceProto"; option java_package = "feast.proto.core"; diff --git a/protos/feast/core/FeatureTable.proto b/protos/feast/core/FeatureTable.proto index 661f4eecfc5..4054db58aed 100644 --- a/protos/feast/core/FeatureTable.proto +++ b/protos/feast/core/FeatureTable.proto @@ -19,7 +19,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "FeatureTableProto"; option java_package = "feast.proto.core"; diff --git a/protos/feast/core/FeatureView.proto b/protos/feast/core/FeatureView.proto index 6edba9f7fee..26623505401 100644 --- a/protos/feast/core/FeatureView.proto +++ b/protos/feast/core/FeatureView.proto @@ -18,7 +18,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "FeatureViewProto"; option java_package = "feast.proto.core"; @@ -35,6 +35,7 @@ message FeatureView { FeatureViewMeta meta = 2; } +// Next available id: 12 // TODO(adchia): refactor common fields from this and ODFV into separate metadata proto message FeatureViewSpec { // Name of the feature view. Must be unique. Not updated. @@ -47,12 +48,18 @@ message FeatureViewSpec { // Feature View. Not updatable. repeated string entities = 3; - // List of features specifications for each feature defined with this feature view. + // List of specifications for each field defined as part of this feature view. repeated FeatureSpecV2 features = 4; + // Description of the feature view. + string description = 10; + // User defined metadata map tags = 5; + // Owner of the feature view. + string owner = 11; + // Features in this feature view can only be retrieved from online serving // younger than ttl. Ttl is measured as the duration of time between // the feature's event timestamp and when the feature is retrieved diff --git a/protos/feast/core/FeatureViewProjection.proto b/protos/feast/core/FeatureViewProjection.proto index e81d8dad01e..36d17632e7d 100644 --- a/protos/feast/core/FeatureViewProjection.proto +++ b/protos/feast/core/FeatureViewProjection.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "FeatureReferenceProto"; option java_package = "feast.proto.core"; diff --git a/protos/feast/core/InfraObject.proto b/protos/feast/core/InfraObject.proto index 863f1b64daa..35204015173 100644 --- a/protos/feast/core/InfraObject.proto +++ b/protos/feast/core/InfraObject.proto @@ -19,7 +19,7 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "InfraObjectProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; import "feast/core/DatastoreTable.proto"; import "feast/core/DynamoDBTable.proto"; diff --git a/protos/feast/core/OnDemandFeatureView.proto b/protos/feast/core/OnDemandFeatureView.proto index bd9a289a1bb..33c51f5c4d3 100644 --- a/protos/feast/core/OnDemandFeatureView.proto +++ b/protos/feast/core/OnDemandFeatureView.proto @@ -18,7 +18,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "OnDemandFeatureViewProto"; option java_package = "feast.proto.core"; @@ -34,6 +34,7 @@ message OnDemandFeatureView { OnDemandFeatureViewMeta meta = 2; } +// Next available id: 9 message OnDemandFeatureViewSpec { // Name of the feature view. Must be unique. Not updated. string name = 1; @@ -44,10 +45,19 @@ message OnDemandFeatureViewSpec { // List of features specifications for each feature defined with this feature view. repeated FeatureSpecV2 features = 3; - // Map of inputs for this feature view. - map inputs = 4; + // Map of sources for this feature view. + map sources = 4; UserDefinedFunction user_defined_function = 5; + + // Description of the on demand feature view. + string description = 6; + + // User defined metadata. + map tags = 7; + + // Owner of the on demand feature view. + string owner = 8; } message OnDemandFeatureViewMeta { @@ -58,8 +68,8 @@ message OnDemandFeatureViewMeta { google.protobuf.Timestamp last_updated_timestamp = 2; } -message OnDemandInput { - oneof input { +message OnDemandSource { + oneof source { FeatureView feature_view = 1; FeatureViewProjection feature_view_projection = 3; DataSource request_data_source = 2; diff --git a/protos/feast/core/Registry.proto b/protos/feast/core/Registry.proto index a19e4c0a094..1978f41064a 100644 --- a/protos/feast/core/Registry.proto +++ b/protos/feast/core/Registry.proto @@ -19,7 +19,7 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "RegistryProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; import "feast/core/Entity.proto"; import "feast/core/FeatureService.proto"; diff --git a/protos/feast/core/RequestFeatureView.proto b/protos/feast/core/RequestFeatureView.proto index 39711d8d3f2..4049053c2be 100644 --- a/protos/feast/core/RequestFeatureView.proto +++ b/protos/feast/core/RequestFeatureView.proto @@ -18,7 +18,7 @@ syntax = "proto3"; package feast.core; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; option java_outer_classname = "RequestFeatureViewProto"; option java_package = "feast.proto.core"; @@ -29,6 +29,7 @@ message RequestFeatureView { RequestFeatureViewSpec spec = 1; } +// Next available id: 7 message RequestFeatureViewSpec { // Name of the feature view. Must be unique. Not updated. string name = 1; @@ -38,4 +39,13 @@ message RequestFeatureViewSpec { // Request data which contains the underlying data schema and list of associated features DataSource request_data_source = 3; + + // Description of the request feature view. + string description = 4; + + // User defined metadata. + map tags = 5; + + // Owner of the request feature view. + string owner = 6; } diff --git a/protos/feast/core/SavedDataset.proto b/protos/feast/core/SavedDataset.proto index e6d103a691b..353e925ad1c 100644 --- a/protos/feast/core/SavedDataset.proto +++ b/protos/feast/core/SavedDataset.proto @@ -20,11 +20,10 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "SavedDatasetProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; import "google/protobuf/timestamp.proto"; import "feast/core/DataSource.proto"; -import "feast/core/FeatureService.proto"; message SavedDatasetSpec { // Name of the dataset. Must be unique since it's possible to overwrite dataset by name @@ -57,6 +56,8 @@ message SavedDatasetStorage { DataSource.BigQueryOptions bigquery_storage = 5; DataSource.RedshiftOptions redshift_storage = 6; DataSource.SnowflakeOptions snowflake_storage = 7; + DataSource.TrinoOptions trino_storage = 8; + DataSource.SparkOptions spark_storage = 9; } } diff --git a/protos/feast/core/SqliteTable.proto b/protos/feast/core/SqliteTable.proto index 1732931b8f0..8665be840ae 100644 --- a/protos/feast/core/SqliteTable.proto +++ b/protos/feast/core/SqliteTable.proto @@ -19,7 +19,7 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "SqliteTableProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; // Represents a Sqlite table message SqliteTable { diff --git a/protos/feast/core/Store.proto b/protos/feast/core/Store.proto index 41a76a11c2c..c92a526354d 100644 --- a/protos/feast/core/Store.proto +++ b/protos/feast/core/Store.proto @@ -19,7 +19,7 @@ package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "StoreProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; // Store provides a location where Feast reads and writes feature values. // Feature values will be written to the Store in the form of FeatureRow elements. diff --git a/protos/feast/core/ValidationProfile.proto b/protos/feast/core/ValidationProfile.proto index 502e79f72b4..673a792fdf8 100644 --- a/protos/feast/core/ValidationProfile.proto +++ b/protos/feast/core/ValidationProfile.proto @@ -20,7 +20,7 @@ syntax = "proto3"; package feast.core; option java_package = "feast.proto.core"; option java_outer_classname = "ValidationProfile"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; import "feast/core/SavedDataset.proto"; diff --git a/protos/feast/serving/Connector.proto b/protos/feast/serving/Connector.proto new file mode 100644 index 00000000000..4e4ec51774d --- /dev/null +++ b/protos/feast/serving/Connector.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + +package grpc.connector; + +import "google/protobuf/timestamp.proto"; +import "feast/types/Value.proto"; +import "feast/types/EntityKey.proto"; +import "feast/serving/ServingService.proto"; + +option go_package = "github.com/feast-dev/feast/go/protos/feast/serving"; + +message ConnectorFeature { + feast.serving.FeatureReferenceV2 reference = 1; + google.protobuf.Timestamp timestamp = 2; + feast.types.Value value = 3; +} + +message ConnectorFeatureList { + repeated ConnectorFeature featureList = 1; +} + +service OnlineStore { + rpc OnlineRead(OnlineReadRequest) returns (OnlineReadResponse); +} + +message OnlineReadRequest { + repeated feast.types.EntityKey entityKeys = 1; + string view = 2; + repeated string features = 3; +} + +message OnlineReadResponse { + repeated ConnectorFeatureList results = 1; +} \ No newline at end of file diff --git a/protos/feast/serving/ServingService.proto b/protos/feast/serving/ServingService.proto index 6c551a97baf..a940b725025 100644 --- a/protos/feast/serving/ServingService.proto +++ b/protos/feast/serving/ServingService.proto @@ -23,12 +23,11 @@ import "feast/types/Value.proto"; option java_package = "feast.proto.serving"; option java_outer_classname = "ServingAPIProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/serving"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/serving"; service ServingService { // Get information about this Feast serving. rpc GetFeastServingInfo (GetFeastServingInfoRequest) returns (GetFeastServingInfoResponse); - // Get online features synchronously. rpc GetOnlineFeatures (GetOnlineFeaturesRequest) returns (GetOnlineFeaturesResponse); } diff --git a/protos/feast/serving/TransformationService.proto b/protos/feast/serving/TransformationService.proto index 113bd120c8f..bd1a7917f3c 100644 --- a/protos/feast/serving/TransformationService.proto +++ b/protos/feast/serving/TransformationService.proto @@ -20,7 +20,7 @@ package feast.serving; option java_package = "feast.proto.serving"; option java_outer_classname = "TransformationServiceAPIProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/serving"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/serving"; service TransformationService { rpc GetTransformationServiceInfo (GetTransformationServiceInfoRequest) returns (GetTransformationServiceInfoResponse); diff --git a/protos/feast/storage/Redis.proto b/protos/feast/storage/Redis.proto index bc9d0c61d32..c89e0b6b2fa 100644 --- a/protos/feast/storage/Redis.proto +++ b/protos/feast/storage/Redis.proto @@ -22,7 +22,7 @@ package feast.storage; option java_outer_classname = "RedisProto"; option java_package = "feast.proto.storage"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/storage"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/storage"; message RedisKeyV2 { string project = 1; diff --git a/protos/feast/types/EntityKey.proto b/protos/feast/types/EntityKey.proto index cbc3c55442f..d7eebf25d03 100644 --- a/protos/feast/types/EntityKey.proto +++ b/protos/feast/types/EntityKey.proto @@ -22,7 +22,7 @@ package feast.types; option java_package = "feast.proto.types"; option java_outer_classname = "EntityKeyProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/types"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/types"; message EntityKey { repeated string join_keys = 1; diff --git a/protos/feast/types/Field.proto b/protos/feast/types/Field.proto index 3b8416c253a..8349263cc60 100644 --- a/protos/feast/types/Field.proto +++ b/protos/feast/types/Field.proto @@ -22,9 +22,9 @@ package feast.types; option java_package = "feast.proto.types"; option java_outer_classname = "FieldProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/types"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/types"; message Field { string name = 1; - feast.types.Value value = 2; + feast.types.ValueType.Enum value = 2; } diff --git a/protos/feast/types/Value.proto b/protos/feast/types/Value.proto index b00d4d9b847..b273fecfeae 100644 --- a/protos/feast/types/Value.proto +++ b/protos/feast/types/Value.proto @@ -20,7 +20,7 @@ package feast.types; option java_package = "feast.proto.types"; option java_outer_classname = "ValueProto"; -option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/types"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/types"; message ValueType { enum Enum { diff --git a/sdk/go/README.md b/sdk/go/README.md deleted file mode 100644 index 79211df4a51..00000000000 --- a/sdk/go/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# Feast Golang SDK - -The Feast golang SDK currently only supports retrieval from online stores. - -## Quickstart -```{go} -import ( - "context" - feast "github.com/feast-dev/feast/sdk/go" -) - -func main() { - cli, err := feast.NewGrpcClient("localhost", 6565) - if err != nil { - panic(err) - } - - ctx := context.Background() - req := feast.OnlineFeaturesRequest{ - Features: []string{"my_project_1/feature1", "my_project_2/feature1", "my_project_4/feature3", "feature2", "feature2"}, - Entities: []feast.Row{ - {"entity1": feast.Int64Val(1), "entity2": feast.StrVal("bob")}, - {"entity1": feast.Int64Val(1), "entity2": feast.StrVal("annie")}, - {"entity1": feast.Int64Val(1), "entity2": feast.StrVal("jane")}, - }, - Project: "my_project_3", - } - - resp, err := cli.GetOnlineFeatures(ctx, &req) - if err != nil { - panic(err) - } - - // returns a list of rows (map[string]featureValue) - out := resp.Rows() -} - -``` - -If all features retrieved are of a single type, Feast provides convenience functions to retrieve your features as a vector of feature values: -```{go} -arr, err := resp.Int64Arrays( - []string{"my_project_1/feature1", - "my_project_2/feature1", - "my_project_4/feature3", - "feature2", - "feature2"}, // order of features - []int64{1,2,3,4,5}) // fillNa values -``` diff --git a/sdk/go/auth.go b/sdk/go/auth.go deleted file mode 100644 index 1b6703dae12..00000000000 --- a/sdk/go/auth.go +++ /dev/null @@ -1,136 +0,0 @@ -package feast - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "google.golang.org/api/idtoken" - "io/ioutil" - "net/http" - "net/url" -) - -// Credential provides OIDC ID tokens used when authenticating with Feast. -// Implements credentials.PerRPCCredentials -type Credential struct { - tokenSrc oauth2.TokenSource -} - -// GetRequestMetadata attaches OIDC token as metadata, refreshing tokens if required. -// This should be called by the GRPC to authenticate each request. -func (provider *Credential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { - token, err := provider.tokenSrc.Token() - if err != nil { - return map[string]string{}, nil - } - return map[string]string{ - "Authorization": "Bearer " + token.AccessToken, - }, nil -} - -// Disable requirement of transport security to allow user to configure it explictly instead. -func (provider *Credential) RequireTransportSecurity() bool { - return false -} - -// Create a Static Authentication Provider that provides a static token -func NewStaticCredential(token string) *Credential { - return &Credential{tokenSrc: oauth2.StaticTokenSource( - &oauth2.Token{ - AccessToken: token, - }), - } -} - -func newGoogleCredential( - audience string, - findDefaultCredentials func(ctx context.Context, scopes ...string) (*google.Credentials, error), - makeTokenSource func(ctx context.Context, audience string, opts ...idtoken.ClientOption) (oauth2.TokenSource, error)) (*Credential, error) { - // Refresh a Google Id token - // Attempt to id token from Google Application Default Credentials - ctx := context.Background() - creds, err := findDefaultCredentials(ctx, "openid", "email") - if err != nil { - return nil, err - } - tokenSrc, err := makeTokenSource(ctx, audience, idtoken.WithCredentialsJSON(creds.JSON)) - if err != nil { - return nil, err - } - return &Credential{tokenSrc: tokenSrc}, nil -} - -// Creates a new Google Credential which obtains credentials from Application Default Credentials -func NewGoogleCredential(audience string) (*Credential, error) { - return newGoogleCredential(audience, google.FindDefaultCredentials, idtoken.NewTokenSource) -} - -// Creates a new OAuth credential witch obtains credentials by making a client credentials request to an OAuth endpoint. -// clientId, clientSecret - Client credentials used to authenticate the client when obtaining credentials. -// endpointURL - target URL of the OAuth endpoint to make the OAuth request to. -func NewOAuthCredential(audience string, clientId string, clientSecret string, endpointURL *url.URL) *Credential { - tokenSrc := &oauthTokenSource{ - clientId: clientId, - clientSecret: clientSecret, - endpointURL: endpointURL, - audience: audience, - } - return &Credential{tokenSrc: tokenSrc} -} - -// Defines a Token Source that obtains tokens via making a OAuth client credentials request. -type oauthTokenSource struct { - clientId string - clientSecret string - endpointURL *url.URL - audience string - token *oauth2.Token -} - -// Defines a Oauth cleint credentials request. -type oauthClientCredientialsRequest struct { - GrantType string `json:"grant_type"` - ClientId string `json:"client_id"` - ClientSecret string `json:"client_secret"` - Audience string `json:"audience"` -} - -// Obtain or Refresh token from OAuth Token Source. -func (tokenSrc *oauthTokenSource) Token() (*oauth2.Token, error) { - if tokenSrc.token == nil || !tokenSrc.token.Valid() { - // Refresh Oauth Id token by making Oauth client credentials request - req := &oauthClientCredientialsRequest{ - GrantType: "client_credentials", - ClientId: tokenSrc.clientId, - ClientSecret: tokenSrc.clientSecret, - Audience: tokenSrc.audience, - } - - reqBytes, err := json.Marshal(req) - if err != nil { - return nil, err - } - resp, err := http.Post(tokenSrc.endpointURL.String(), - "application/json", bytes.NewBuffer(reqBytes)) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("OAuth Endpoint returned unexpected status: %s", resp.Status) - } - respBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - tokenSrc.token = &oauth2.Token{} - err = json.Unmarshal(respBytes, tokenSrc.token) - if err != nil { - return nil, err - } - } - - return tokenSrc.token, nil -} diff --git a/sdk/go/auth_test.go b/sdk/go/auth_test.go deleted file mode 100644 index 5c1711994cf..00000000000 --- a/sdk/go/auth_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package feast - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "google.golang.org/api/idtoken" -) - -// Returns a mocked google credential. -func mockGoogleCredential(token string, targetAudience string) (*Credential, error) { - // mock find default credentials implementation. - findDefaultCredentials := func(ctx context.Context, scopes ...string) (*google.Credentials, error) { - if len(scopes) != 2 && scopes[0] != "openid" && scopes[1] != "email" { - return nil, fmt.Errorf("Got bad scopes. Expected 'openid', 'email'") - } - - return &google.Credentials{ - ProjectID: "project_id", - JSON: []byte("mock key json"), - }, nil - } - - // mock id token source implementation. - makeTokenSource := func(ctx context.Context, audience string, opts ...idtoken.ClientOption) (oauth2.TokenSource, error) { - // unable to check opts as ClientOption refrences internal type. - if targetAudience != audience { - return nil, fmt.Errorf("Audience does not match up with target audience") - } - - return oauth2.StaticTokenSource(&oauth2.Token{ - AccessToken: "google token", - }), nil - } - - return newGoogleCredential(targetAudience, findDefaultCredentials, makeTokenSource) -} - -// Create a mocked OAuth credential with a backing mocked OAuth server. -func mockOAuthCredential(token string, audience string) (*httptest.Server, *Credential) { - clientId := "id" - clientSecret := "secret" - path := "/oauth" - - // Create a mock OAuth server to test Oauth provider. - handlers := http.NewServeMux() - handlers.HandleFunc(path, func(resp http.ResponseWriter, req *http.Request) { - reqBytes, err := ioutil.ReadAll(req.Body) - if err != nil { - resp.WriteHeader(http.StatusBadRequest) - } - - oauthReq := oauthClientCredientialsRequest{} - err = json.Unmarshal(reqBytes, &oauthReq) - if err != nil { - resp.WriteHeader(http.StatusBadRequest) - } - - if oauthReq.GrantType != "client_credentials" || - oauthReq.ClientId != clientId || - oauthReq.ClientSecret != clientSecret || - oauthReq.Audience != audience { - resp.WriteHeader(http.StatusUnauthorized) - } - - _, err = resp.Write([]byte(fmt.Sprintf("{\"access_token\": \"%s\"}", token))) - if err != nil { - resp.WriteHeader(http.StatusInternalServerError) - } - }) - - srv := httptest.NewServer(handlers) - endpointURL, _ := url.Parse(srv.URL + path) - return srv, NewOAuthCredential(audience, clientId, clientSecret, endpointURL) -} - -func TestCredentials(t *testing.T) { - audience := "localhost" - srv, oauthCred := mockOAuthCredential("oauth token", audience) - defer srv.Close() - googleCred, err := mockGoogleCredential("google token", audience) - if err != nil { - t.Errorf("Unexpected error creating mock google credential: %v", err) - } - - tt := []struct { - name string - credential *Credential - want string - wantErr bool - err error - }{ - { - name: "Valid Static Credential get authentication metadata.", - credential: NewStaticCredential("static token"), - want: "static token", - wantErr: false, - err: nil, - }, - { - name: "Valid Google Credential get authentication metadata.", - credential: googleCred, - want: "google token", - wantErr: false, - err: nil, - }, - { - name: "Valid OAuth Credential get authentication metadata.", - credential: oauthCred, - want: "oauth token", - wantErr: false, - err: nil, - }, - } - - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - ctx := context.Background() - meta, err := tc.credential.GetRequestMetadata(ctx, "feast.serving") - if err != nil { - t.Error(err) - } - authKey := "Authorization" - if _, ok := meta[authKey]; !ok { - t.Errorf("Expected authentication metadata with key: '%s'", authKey) - } - - expectedVal := "Bearer " + tc.want - if meta[authKey] != expectedVal { - t.Errorf("Expected authentication metadata with value: '%s' Got instead: '%s'", expectedVal, meta[authKey]) - } - }) - } -} diff --git a/sdk/go/client.go b/sdk/go/client.go deleted file mode 100644 index c7251e33195..00000000000 --- a/sdk/go/client.go +++ /dev/null @@ -1,134 +0,0 @@ -package feast - -import ( - "context" - "crypto/x509" - "fmt" - - "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - "github.com/opentracing-contrib/go-grpc" - "github.com/opentracing/opentracing-go" - "go.opencensus.io/plugin/ocgrpc" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" -) - -// Client is a feast serving client. -type Client interface { - GetOnlineFeatures(ctx context.Context, req *OnlineFeaturesRequest) (*OnlineFeaturesResponse, error) - GetFeastServingInfo(ctx context.Context, in *serving.GetFeastServingInfoRequest) (*serving.GetFeastServingInfoResponse, error) - Close() error -} - -// GrpcClient is a grpc client for feast serving. -type GrpcClient struct { - cli serving.ServingServiceClient - conn *grpc.ClientConn -} - -// SecurityConfig wraps security config for GrpcClient -type SecurityConfig struct { - // Whether to enable TLS SSL trasnport security if true. - EnableTLS bool - // Optional: Provides path to TLS certificate used the verify Service identity. - TLSCertPath string - // Optional: Credential used for authentication. - // Disables authentication if unspecified. - Credential *Credential -} - -// NewGrpcClient constructs a client that can interact via grpc with the feast serving instance at the given host:port. -func NewGrpcClient(host string, port int) (*GrpcClient, error) { - return NewSecureGrpcClient(host, port, SecurityConfig{ - EnableTLS: false, - Credential: nil, - }) -} - -// NewSecureGrpcClient constructs a secure client that uses security features (ie authentication). -// host - hostname of the serving host/instance to connect to. -// port - post of the host to service host/instancf to connect to. -// securityConfig - security config configures client security. -func NewSecureGrpcClient(host string, port int, security SecurityConfig) (*GrpcClient, error) { - return NewSecureGrpcClientWithDialOptions(host, port, security) -} - -// NewSecureGrpcClientWithDialOptions constructs a secure client that uses security features (ie authentication) along with custom grpc dial options. -// host - hostname of the serving host/instance to connect to. -// port - post of the host to service host/instancf to connect to. -// securityConfig - security config configures client security. -// opts - grpc.DialOptions which should be used with this connection -func NewSecureGrpcClientWithDialOptions(host string, port int, security SecurityConfig, opts ...grpc.DialOption) (*GrpcClient, error) { - feastCli := &GrpcClient{} - adr := fmt.Sprintf("%s:%d", host, port) - - // Compile grpc dial options from security config. - options := append(opts, grpc.WithStatsHandler(&ocgrpc.ClientHandler{})) - // Configure client TLS. - if !security.EnableTLS { - options = append(options, grpc.WithInsecure()) - } else if security.EnableTLS && security.TLSCertPath != "" { - // Read TLS certificate from given path. - tlsCreds, err := credentials.NewClientTLSFromFile(security.TLSCertPath, "") - if err != nil { - return nil, err - } - options = append(options, grpc.WithTransportCredentials(tlsCreds)) - } else { - // Use system TLS certificate pool. - certPool, err := x509.SystemCertPool() - if err != nil { - return nil, err - } - tlsCreds := credentials.NewClientTLSFromCert(certPool, "") - options = append(options, grpc.WithTransportCredentials(tlsCreds)) - } - - // Enable authentication by attaching credentials if given - if security.Credential != nil { - options = append(options, grpc.WithPerRPCCredentials(security.Credential)) - } - - // Enable tracing if a global tracer is registered - tracingInterceptor := grpc.WithUnaryInterceptor( - otgrpc.OpenTracingClientInterceptor(opentracing.GlobalTracer())) - options = append(options, tracingInterceptor) - - conn, err := grpc.Dial(adr, options...) - if err != nil { - return nil, err - } - feastCli.cli = serving.NewServingServiceClient(conn) - feastCli.conn = conn - return feastCli, nil -} - -// GetOnlineFeatures gets the latest values of the request features from the Feast serving instance provided. -func (fc *GrpcClient) GetOnlineFeatures(ctx context.Context, req *OnlineFeaturesRequest) ( - *OnlineFeaturesResponse, error) { - featuresRequest, err := req.buildRequest() - if err != nil { - return nil, err - } - resp, err := fc.cli.GetOnlineFeatures(ctx, featuresRequest) - - // collect unqiue entity refs from entity rows - entityRefs := make(map[string]struct{}) - for _, entityRows := range req.Entities { - for ref := range entityRows { - entityRefs[ref] = struct{}{} - } - } - return &OnlineFeaturesResponse{RawResponse: resp}, err -} - -// GetFeastServingInfo gets information about the feast serving instance this client is connected to. -func (fc *GrpcClient) GetFeastServingInfo(ctx context.Context, in *serving.GetFeastServingInfoRequest) ( - *serving.GetFeastServingInfoResponse, error) { - return fc.cli.GetFeastServingInfo(ctx, in) -} - -// Close the grpc connection. -func (fc *GrpcClient) Close() error { - return fc.conn.Close() -} diff --git a/sdk/go/client_test.go b/sdk/go/client_test.go deleted file mode 100644 index cb15f66654b..00000000000 --- a/sdk/go/client_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package feast - -import ( - "context" - "testing" - - "github.com/feast-dev/feast/sdk/go/mocks" - "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - "github.com/feast-dev/feast/sdk/go/protos/feast/types" - "github.com/golang/mock/gomock" - "github.com/google/go-cmp/cmp" -) - -func TestGetOnlineFeatures(t *testing.T) { - tt := []struct { - name string - req OnlineFeaturesRequest - recieve OnlineFeaturesResponse - want OnlineFeaturesResponse - wantErr bool - err error - }{ - { - name: "Valid client Get Online Features call", - req: OnlineFeaturesRequest{ - Features: []string{ - "driver:rating", - "driver:null_value", - }, - Entities: []Row{ - {"driver_id": Int64Val(1)}, - }, - Project: "driver_project", - }, - want: OnlineFeaturesResponse{ - RawResponse: &serving.GetOnlineFeaturesResponse{ - Results: []*serving.GetOnlineFeaturesResponse_FeatureVector{ - { - Values: []*types.Value{Int64Val(1)}, - Statuses: []serving.FieldStatus{ - serving.FieldStatus_PRESENT, - }, - }, - { - Values: []*types.Value{{}}, - Statuses: []serving.FieldStatus{ - serving.FieldStatus_NULL_VALUE, - }, - }, - }, - Metadata: &serving.GetOnlineFeaturesResponseMetadata{ - FeatureNames: &serving.FeatureList{ - Val: []string{"driver:rating", "driver:null_value"}, - }, - }, - }, - }, - }, - } - - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - // mock feast grpc client get online feature requestss - ctrl := gomock.NewController(t) - defer ctrl.Finish() - cli := mock_serving.NewMockServingServiceClient(ctrl) - ctx := context.Background() - rawRequest, _ := tc.req.buildRequest() - resp := tc.want.RawResponse - cli.EXPECT().GetOnlineFeatures(ctx, rawRequest).Return(resp, nil).Times(1) - - client := &GrpcClient{ - cli: cli, - } - got, err := client.GetOnlineFeatures(ctx, &tc.req) - - if err != nil && !tc.wantErr { - t.Errorf("error = %v, wantErr %v", err, tc.wantErr) - return - } - if tc.wantErr && err.Error() != tc.err.Error() { - t.Errorf("error = %v, expected err = %v", err, tc.err) - return - } - // TODO: compare directly once OnlineFeaturesResponse no longer embeds a rawResponse. - if !cmp.Equal(got.RawResponse.String(), tc.want.RawResponse.String()) { - t.Errorf("got: \n%v\nwant:\n%v", got.RawResponse.String(), tc.want.RawResponse.String()) - } - }) - } -} diff --git a/sdk/go/go.mod b/sdk/go/go.mod deleted file mode 100644 index d3b454d55c3..00000000000 --- a/sdk/go/go.mod +++ /dev/null @@ -1,16 +0,0 @@ -module github.com/feast-dev/feast/sdk/go - -go 1.13 - -require ( - github.com/golang/mock v1.4.3 - github.com/golang/protobuf v1.4.2 - github.com/google/go-cmp v0.5.1 - github.com/opentracing-contrib/go-grpc v0.0.0-20200813121455-4a6760c71486 - github.com/opentracing/opentracing-go v1.1.0 - go.opencensus.io v0.22.4 - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d - google.golang.org/api v0.30.0 - google.golang.org/grpc v1.31.0 - google.golang.org/protobuf v1.25.0 -) diff --git a/sdk/go/go.sum b/sdk/go/go.sum deleted file mode 100644 index f9a22785a53..00000000000 --- a/sdk/go/go.sum +++ /dev/null @@ -1,404 +0,0 @@ -cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0 h1:RmDygqvj27Zf3fCQjQRtLyC7KwFcHkeJitcO0OoGOcA= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0 h1:aRz0NBceriICVtjhCgKkDvl+RudKu1CT6h0ZvUTrNfE= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/opentracing-contrib/go-grpc v0.0.0-20200813121455-4a6760c71486 h1:K35HCWaOTJIPW6cDHK4yj3QfRY/NhE0pBbfoc0M2NMQ= -github.com/opentracing-contrib/go-grpc v0.0.0-20200813121455-4a6760c71486/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd h1:r7DufRZuZbWB7j439YfAzP8RPDa9unLkpwQKUYbIMPI= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c h1:Lq4llNryJoaVFRmvrIwC/ZHH7tNt4tUYIu8+se2aayY= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/sdk/go/mocks/serving_mock.go b/sdk/go/mocks/serving_mock.go deleted file mode 100644 index 038d49f5e53..00000000000 --- a/sdk/go/mocks/serving_mock.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/feast-dev/feast/sdk/go/protos/feast/serving (interfaces: ServingServiceClient) - -// Package mock_serving is a generated GoMock package. -package mock_serving - -import ( - context "context" - reflect "reflect" - - serving "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - gomock "github.com/golang/mock/gomock" - grpc "google.golang.org/grpc" -) - -// MockServingServiceClient is a mock of ServingServiceClient interface -type MockServingServiceClient struct { - ctrl *gomock.Controller - recorder *MockServingServiceClientMockRecorder -} - -// MockServingServiceClientMockRecorder is the mock recorder for MockServingServiceClient -type MockServingServiceClientMockRecorder struct { - mock *MockServingServiceClient -} - -// NewMockServingServiceClient creates a new mock instance -func NewMockServingServiceClient(ctrl *gomock.Controller) *MockServingServiceClient { - mock := &MockServingServiceClient{ctrl: ctrl} - mock.recorder = &MockServingServiceClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockServingServiceClient) EXPECT() *MockServingServiceClientMockRecorder { - return m.recorder -} - -// GetFeastServingInfo mocks base method -func (m *MockServingServiceClient) GetFeastServingInfo(arg0 context.Context, arg1 *serving.GetFeastServingInfoRequest, arg2 ...grpc.CallOption) (*serving.GetFeastServingInfoResponse, error) { - m.ctrl.T.Helper() - varargs := []interface{}{arg0, arg1} - for _, a := range arg2 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "GetFeastServingInfo", varargs...) - ret0, _ := ret[0].(*serving.GetFeastServingInfoResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetFeastServingInfo indicates an expected call of GetFeastServingInfo -func (mr *MockServingServiceClientMockRecorder) GetFeastServingInfo(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0, arg1}, arg2...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFeastServingInfo", reflect.TypeOf((*MockServingServiceClient)(nil).GetFeastServingInfo), varargs...) -} - -// GetOnlineFeaturesV2 mocks base method -func (m *MockServingServiceClient) GetOnlineFeatures(arg0 context.Context, arg1 *serving.GetOnlineFeaturesRequest, arg2 ...grpc.CallOption) (*serving.GetOnlineFeaturesResponse, error) { - m.ctrl.T.Helper() - varargs := []interface{}{arg0, arg1} - for _, a := range arg2 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "GetOnlineFeatures", varargs...) - ret0, _ := ret[0].(*serving.GetOnlineFeaturesResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetOnlineFeaturesV2 indicates an expected call of GetOnlineFeaturesV2 -func (mr *MockServingServiceClientMockRecorder) GetOnlineFeatures(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0, arg1}, arg2...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOnlineFeatures", reflect.TypeOf((*MockServingServiceClient)(nil).GetOnlineFeatures), varargs...) -} diff --git a/sdk/go/protos/feast/core/CoreService.pb.go b/sdk/go/protos/feast/core/CoreService.pb.go deleted file mode 100644 index 1978edce45a..00000000000 --- a/sdk/go/protos/feast/core/CoreService.pb.go +++ /dev/null @@ -1,3172 +0,0 @@ -// -// Copyright 2018 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.11.2 -// source: feast/core/CoreService.proto - -package core - -import ( - context "context" - _ "github.com/feast-dev/feast/sdk/go/protos/tensorflow_metadata/proto/v0" - 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" - _ "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type UpdateStoreResponse_Status int32 - -const ( - // Existing store config matching the given store id is identical to the given store config. - UpdateStoreResponse_NO_CHANGE UpdateStoreResponse_Status = 0 - // New store created or existing config updated. - UpdateStoreResponse_UPDATED UpdateStoreResponse_Status = 1 -) - -// Enum value maps for UpdateStoreResponse_Status. -var ( - UpdateStoreResponse_Status_name = map[int32]string{ - 0: "NO_CHANGE", - 1: "UPDATED", - } - UpdateStoreResponse_Status_value = map[string]int32{ - "NO_CHANGE": 0, - "UPDATED": 1, - } -) - -func (x UpdateStoreResponse_Status) Enum() *UpdateStoreResponse_Status { - p := new(UpdateStoreResponse_Status) - *p = x - return p -} - -func (x UpdateStoreResponse_Status) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (UpdateStoreResponse_Status) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_CoreService_proto_enumTypes[0].Descriptor() -} - -func (UpdateStoreResponse_Status) Type() protoreflect.EnumType { - return &file_feast_core_CoreService_proto_enumTypes[0] -} - -func (x UpdateStoreResponse_Status) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use UpdateStoreResponse_Status.Descriptor instead. -func (UpdateStoreResponse_Status) EnumDescriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{13, 0} -} - -// Request for a single entity -type GetEntityRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of entity (required). - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Name of project the entity belongs to. If omitted will default to 'default' project. - Project string `protobuf:"bytes,2,opt,name=project,proto3" json:"project,omitempty"` -} - -func (x *GetEntityRequest) Reset() { - *x = GetEntityRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetEntityRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetEntityRequest) ProtoMessage() {} - -func (x *GetEntityRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetEntityRequest.ProtoReflect.Descriptor instead. -func (*GetEntityRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{0} -} - -func (x *GetEntityRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *GetEntityRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -// Response containing a single entity -type GetEntityResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Entity *Entity `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"` -} - -func (x *GetEntityResponse) Reset() { - *x = GetEntityResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetEntityResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetEntityResponse) ProtoMessage() {} - -func (x *GetEntityResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetEntityResponse.ProtoReflect.Descriptor instead. -func (*GetEntityResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{1} -} - -func (x *GetEntityResponse) GetEntity() *Entity { - if x != nil { - return x.Entity - } - return nil -} - -// Retrieves details for all versions of a specific entity -type ListEntitiesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Filter *ListEntitiesRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` -} - -func (x *ListEntitiesRequest) Reset() { - *x = ListEntitiesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListEntitiesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListEntitiesRequest) ProtoMessage() {} - -func (x *ListEntitiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListEntitiesRequest.ProtoReflect.Descriptor instead. -func (*ListEntitiesRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{2} -} - -func (x *ListEntitiesRequest) GetFilter() *ListEntitiesRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -type ListEntitiesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Entities []*Entity `protobuf:"bytes,1,rep,name=entities,proto3" json:"entities,omitempty"` -} - -func (x *ListEntitiesResponse) Reset() { - *x = ListEntitiesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListEntitiesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListEntitiesResponse) ProtoMessage() {} - -func (x *ListEntitiesResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListEntitiesResponse.ProtoReflect.Descriptor instead. -func (*ListEntitiesResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{3} -} - -func (x *ListEntitiesResponse) GetEntities() []*Entity { - if x != nil { - return x.Entities - } - return nil -} - -type ListFeaturesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Filter *ListFeaturesRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` -} - -func (x *ListFeaturesRequest) Reset() { - *x = ListFeaturesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListFeaturesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListFeaturesRequest) ProtoMessage() {} - -func (x *ListFeaturesRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListFeaturesRequest.ProtoReflect.Descriptor instead. -func (*ListFeaturesRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{4} -} - -func (x *ListFeaturesRequest) GetFilter() *ListFeaturesRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -type ListFeaturesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Features map[string]*FeatureSpecV2 `protobuf:"bytes,2,rep,name=features,proto3" json:"features,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ListFeaturesResponse) Reset() { - *x = ListFeaturesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListFeaturesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListFeaturesResponse) ProtoMessage() {} - -func (x *ListFeaturesResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListFeaturesResponse.ProtoReflect.Descriptor instead. -func (*ListFeaturesResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{5} -} - -func (x *ListFeaturesResponse) GetFeatures() map[string]*FeatureSpecV2 { - if x != nil { - return x.Features - } - return nil -} - -type ListStoresRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Filter *ListStoresRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` -} - -func (x *ListStoresRequest) Reset() { - *x = ListStoresRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListStoresRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListStoresRequest) ProtoMessage() {} - -func (x *ListStoresRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListStoresRequest.ProtoReflect.Descriptor instead. -func (*ListStoresRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{6} -} - -func (x *ListStoresRequest) GetFilter() *ListStoresRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -type ListStoresResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Store []*Store `protobuf:"bytes,1,rep,name=store,proto3" json:"store,omitempty"` -} - -func (x *ListStoresResponse) Reset() { - *x = ListStoresResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListStoresResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListStoresResponse) ProtoMessage() {} - -func (x *ListStoresResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListStoresResponse.ProtoReflect.Descriptor instead. -func (*ListStoresResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{7} -} - -func (x *ListStoresResponse) GetStore() []*Store { - if x != nil { - return x.Store - } - return nil -} - -type ApplyEntityRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // If project is unspecified, will default to 'default' project. - // If project specified does not exist, the project would be automatically created. - Spec *EntitySpecV2 `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` - // Name of project that this entity belongs to. - Project string `protobuf:"bytes,2,opt,name=project,proto3" json:"project,omitempty"` -} - -func (x *ApplyEntityRequest) Reset() { - *x = ApplyEntityRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyEntityRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyEntityRequest) ProtoMessage() {} - -func (x *ApplyEntityRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyEntityRequest.ProtoReflect.Descriptor instead. -func (*ApplyEntityRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{8} -} - -func (x *ApplyEntityRequest) GetSpec() *EntitySpecV2 { - if x != nil { - return x.Spec - } - return nil -} - -func (x *ApplyEntityRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -type ApplyEntityResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Entity *Entity `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"` -} - -func (x *ApplyEntityResponse) Reset() { - *x = ApplyEntityResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyEntityResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyEntityResponse) ProtoMessage() {} - -func (x *ApplyEntityResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyEntityResponse.ProtoReflect.Descriptor instead. -func (*ApplyEntityResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{9} -} - -func (x *ApplyEntityResponse) GetEntity() *Entity { - if x != nil { - return x.Entity - } - return nil -} - -type GetFeastCoreVersionRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetFeastCoreVersionRequest) Reset() { - *x = GetFeastCoreVersionRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetFeastCoreVersionRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetFeastCoreVersionRequest) ProtoMessage() {} - -func (x *GetFeastCoreVersionRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetFeastCoreVersionRequest.ProtoReflect.Descriptor instead. -func (*GetFeastCoreVersionRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{10} -} - -type GetFeastCoreVersionResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *GetFeastCoreVersionResponse) Reset() { - *x = GetFeastCoreVersionResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetFeastCoreVersionResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetFeastCoreVersionResponse) ProtoMessage() {} - -func (x *GetFeastCoreVersionResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetFeastCoreVersionResponse.ProtoReflect.Descriptor instead. -func (*GetFeastCoreVersionResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{11} -} - -func (x *GetFeastCoreVersionResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type UpdateStoreRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Store *Store `protobuf:"bytes,1,opt,name=store,proto3" json:"store,omitempty"` -} - -func (x *UpdateStoreRequest) Reset() { - *x = UpdateStoreRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateStoreRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateStoreRequest) ProtoMessage() {} - -func (x *UpdateStoreRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateStoreRequest.ProtoReflect.Descriptor instead. -func (*UpdateStoreRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{12} -} - -func (x *UpdateStoreRequest) GetStore() *Store { - if x != nil { - return x.Store - } - return nil -} - -type UpdateStoreResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Store *Store `protobuf:"bytes,1,opt,name=store,proto3" json:"store,omitempty"` - Status UpdateStoreResponse_Status `protobuf:"varint,2,opt,name=status,proto3,enum=feast.core.UpdateStoreResponse_Status" json:"status,omitempty"` -} - -func (x *UpdateStoreResponse) Reset() { - *x = UpdateStoreResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateStoreResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateStoreResponse) ProtoMessage() {} - -func (x *UpdateStoreResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateStoreResponse.ProtoReflect.Descriptor instead. -func (*UpdateStoreResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{13} -} - -func (x *UpdateStoreResponse) GetStore() *Store { - if x != nil { - return x.Store - } - return nil -} - -func (x *UpdateStoreResponse) GetStatus() UpdateStoreResponse_Status { - if x != nil { - return x.Status - } - return UpdateStoreResponse_NO_CHANGE -} - -// Request to create a project -type CreateProjectRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of project (required) - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *CreateProjectRequest) Reset() { - *x = CreateProjectRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateProjectRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateProjectRequest) ProtoMessage() {} - -func (x *CreateProjectRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreateProjectRequest.ProtoReflect.Descriptor instead. -func (*CreateProjectRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{14} -} - -func (x *CreateProjectRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// Response for creation of a project -type CreateProjectResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *CreateProjectResponse) Reset() { - *x = CreateProjectResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateProjectResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateProjectResponse) ProtoMessage() {} - -func (x *CreateProjectResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreateProjectResponse.ProtoReflect.Descriptor instead. -func (*CreateProjectResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{15} -} - -// Request for the archival of a project -type ArchiveProjectRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of project to be archived - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *ArchiveProjectRequest) Reset() { - *x = ArchiveProjectRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ArchiveProjectRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArchiveProjectRequest) ProtoMessage() {} - -func (x *ArchiveProjectRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArchiveProjectRequest.ProtoReflect.Descriptor instead. -func (*ArchiveProjectRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{16} -} - -func (x *ArchiveProjectRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// Response for archival of a project -type ArchiveProjectResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ArchiveProjectResponse) Reset() { - *x = ArchiveProjectResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ArchiveProjectResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArchiveProjectResponse) ProtoMessage() {} - -func (x *ArchiveProjectResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArchiveProjectResponse.ProtoReflect.Descriptor instead. -func (*ArchiveProjectResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{17} -} - -// Request for listing of projects -type ListProjectsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ListProjectsRequest) Reset() { - *x = ListProjectsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListProjectsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListProjectsRequest) ProtoMessage() {} - -func (x *ListProjectsRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListProjectsRequest.ProtoReflect.Descriptor instead. -func (*ListProjectsRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{18} -} - -// Response for listing of projects -type ListProjectsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of project names (archived projects are filtered out) - Projects []string `protobuf:"bytes,1,rep,name=projects,proto3" json:"projects,omitempty"` -} - -func (x *ListProjectsResponse) Reset() { - *x = ListProjectsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListProjectsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListProjectsResponse) ProtoMessage() {} - -func (x *ListProjectsResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListProjectsResponse.ProtoReflect.Descriptor instead. -func (*ListProjectsResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{19} -} - -func (x *ListProjectsResponse) GetProjects() []string { - if x != nil { - return x.Projects - } - return nil -} - -type UpdateFeatureSetStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *UpdateFeatureSetStatusResponse) Reset() { - *x = UpdateFeatureSetStatusResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateFeatureSetStatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateFeatureSetStatusResponse) ProtoMessage() {} - -func (x *UpdateFeatureSetStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpdateFeatureSetStatusResponse.ProtoReflect.Descriptor instead. -func (*UpdateFeatureSetStatusResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{20} -} - -type ApplyFeatureTableRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional. Name of the Project to apply the Feature Table to. - // If unspecified, will apply FeatureTable to the default project. - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - // Feature Table specification to apply - TableSpec *FeatureTableSpec `protobuf:"bytes,2,opt,name=table_spec,json=tableSpec,proto3" json:"table_spec,omitempty"` -} - -func (x *ApplyFeatureTableRequest) Reset() { - *x = ApplyFeatureTableRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyFeatureTableRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyFeatureTableRequest) ProtoMessage() {} - -func (x *ApplyFeatureTableRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyFeatureTableRequest.ProtoReflect.Descriptor instead. -func (*ApplyFeatureTableRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{21} -} - -func (x *ApplyFeatureTableRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *ApplyFeatureTableRequest) GetTableSpec() *FeatureTableSpec { - if x != nil { - return x.TableSpec - } - return nil -} - -type ApplyFeatureTableResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Table *FeatureTable `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` -} - -func (x *ApplyFeatureTableResponse) Reset() { - *x = ApplyFeatureTableResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyFeatureTableResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyFeatureTableResponse) ProtoMessage() {} - -func (x *ApplyFeatureTableResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyFeatureTableResponse.ProtoReflect.Descriptor instead. -func (*ApplyFeatureTableResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{22} -} - -func (x *ApplyFeatureTableResponse) GetTable() *FeatureTable { - if x != nil { - return x.Table - } - return nil -} - -type GetFeatureTableRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional. Name of the Project to retrieve the Feature Table from. - // If unspecified, will apply FeatureTable to the default project. - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - // Name of the FeatureTable to retrieve. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *GetFeatureTableRequest) Reset() { - *x = GetFeatureTableRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetFeatureTableRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetFeatureTableRequest) ProtoMessage() {} - -func (x *GetFeatureTableRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetFeatureTableRequest.ProtoReflect.Descriptor instead. -func (*GetFeatureTableRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{23} -} - -func (x *GetFeatureTableRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *GetFeatureTableRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type GetFeatureTableResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The Feature Table retrieved. - Table *FeatureTable `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` -} - -func (x *GetFeatureTableResponse) Reset() { - *x = GetFeatureTableResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetFeatureTableResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetFeatureTableResponse) ProtoMessage() {} - -func (x *GetFeatureTableResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetFeatureTableResponse.ProtoReflect.Descriptor instead. -func (*GetFeatureTableResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{24} -} - -func (x *GetFeatureTableResponse) GetTable() *FeatureTable { - if x != nil { - return x.Table - } - return nil -} - -type ListFeatureTablesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Filter used when listing Feature Tables - Filter *ListFeatureTablesRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` -} - -func (x *ListFeatureTablesRequest) Reset() { - *x = ListFeatureTablesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListFeatureTablesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListFeatureTablesRequest) ProtoMessage() {} - -func (x *ListFeatureTablesRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListFeatureTablesRequest.ProtoReflect.Descriptor instead. -func (*ListFeatureTablesRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{25} -} - -func (x *ListFeatureTablesRequest) GetFilter() *ListFeatureTablesRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -type ListFeatureTablesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of matching Feature Tables - Tables []*FeatureTable `protobuf:"bytes,1,rep,name=tables,proto3" json:"tables,omitempty"` -} - -func (x *ListFeatureTablesResponse) Reset() { - *x = ListFeatureTablesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListFeatureTablesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListFeatureTablesResponse) ProtoMessage() {} - -func (x *ListFeatureTablesResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListFeatureTablesResponse.ProtoReflect.Descriptor instead. -func (*ListFeatureTablesResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{26} -} - -func (x *ListFeatureTablesResponse) GetTables() []*FeatureTable { - if x != nil { - return x.Tables - } - return nil -} - -type DeleteFeatureTableRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional. Name of the Project to delete the Feature Table from. - // If unspecified, will delete FeatureTable from the default project. - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - // Name of the FeatureTable to delete. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *DeleteFeatureTableRequest) Reset() { - *x = DeleteFeatureTableRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteFeatureTableRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteFeatureTableRequest) ProtoMessage() {} - -func (x *DeleteFeatureTableRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DeleteFeatureTableRequest.ProtoReflect.Descriptor instead. -func (*DeleteFeatureTableRequest) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{27} -} - -func (x *DeleteFeatureTableRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *DeleteFeatureTableRequest) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type DeleteFeatureTableResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DeleteFeatureTableResponse) Reset() { - *x = DeleteFeatureTableResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteFeatureTableResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteFeatureTableResponse) ProtoMessage() {} - -func (x *DeleteFeatureTableResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DeleteFeatureTableResponse.ProtoReflect.Descriptor instead. -func (*DeleteFeatureTableResponse) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{28} -} - -type ListEntitiesRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional. Specifies the name of the project to list Entities in. - // It is NOT possible to provide an asterisk with a string in order to do pattern matching. - // If unspecified, this field will default to the default project 'default'. - Project string `protobuf:"bytes,3,opt,name=project,proto3" json:"project,omitempty"` - // Optional. User defined metadata for entity. - // Entities with all matching labels will be returned. - Labels map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ListEntitiesRequest_Filter) Reset() { - *x = ListEntitiesRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListEntitiesRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListEntitiesRequest_Filter) ProtoMessage() {} - -func (x *ListEntitiesRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListEntitiesRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListEntitiesRequest_Filter) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{2, 0} -} - -func (x *ListEntitiesRequest_Filter) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *ListEntitiesRequest_Filter) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -type ListFeaturesRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // User defined metadata for feature. - // Features with all matching labels will be returned. - Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // List of entities contained within the featureSet that the feature belongs to. - // Only feature tables with these entities will be searched for features. - Entities []string `protobuf:"bytes,2,rep,name=entities,proto3" json:"entities,omitempty"` - // Name of project that the feature tables belongs to. Filtering on projects is disabled. - // It is NOT possible to provide an asterisk with a string in order to do pattern matching. - // If unspecified this field will default to the default project 'default'. - Project string `protobuf:"bytes,3,opt,name=project,proto3" json:"project,omitempty"` -} - -func (x *ListFeaturesRequest_Filter) Reset() { - *x = ListFeaturesRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListFeaturesRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListFeaturesRequest_Filter) ProtoMessage() {} - -func (x *ListFeaturesRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListFeaturesRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListFeaturesRequest_Filter) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{4, 0} -} - -func (x *ListFeaturesRequest_Filter) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -func (x *ListFeaturesRequest_Filter) GetEntities() []string { - if x != nil { - return x.Entities - } - return nil -} - -func (x *ListFeaturesRequest_Filter) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -type ListStoresRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of desired store. Regex is not supported in this query. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *ListStoresRequest_Filter) Reset() { - *x = ListStoresRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListStoresRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListStoresRequest_Filter) ProtoMessage() {} - -func (x *ListStoresRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[34] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListStoresRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListStoresRequest_Filter) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *ListStoresRequest_Filter) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type ListFeatureTablesRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional. Specifies the name of the project to list Feature Tables in. - // If unspecified would list Feature Tables in the default project. - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - // Optional. Feature Tables with all matching labels will be returned. - // If unspecified would list Feature Tables without filtering by labels. - Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ListFeatureTablesRequest_Filter) Reset() { - *x = ListFeatureTablesRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_CoreService_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListFeatureTablesRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListFeatureTablesRequest_Filter) ProtoMessage() {} - -func (x *ListFeatureTablesRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_CoreService_proto_msgTypes[35] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListFeatureTablesRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListFeatureTablesRequest_Filter) Descriptor() ([]byte, []int) { - return file_feast_core_CoreService_proto_rawDescGZIP(), []int{25, 0} -} - -func (x *ListFeatureTablesRequest_Filter) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *ListFeatureTablesRequest_Filter) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -var File_feast_core_CoreService_proto protoreflect.FileDescriptor - -var file_feast_core_CoreService_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x43, 0x6f, 0x72, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, - 0x74, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x40, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3f, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, - 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x81, 0x02, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, - 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x3e, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, - 0xa9, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x46, 0x0a, 0x14, 0x4c, - 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x22, 0x9d, 0x02, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x06, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0xc5, 0x01, 0x0a, 0x06, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x4c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x08, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x1a, 0x56, 0x0a, 0x0d, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x70, 0x65, 0x63, 0x56, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x6f, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x1c, 0x0a, 0x06, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, - 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, - 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x5c, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x04, - 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x70, - 0x65, 0x63, 0x56, 0x32, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x22, 0x41, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x45, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, - 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x1c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x46, 0x65, - 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x37, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, - 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3d, - 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0xa4, 0x01, - 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x05, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x3e, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x24, - 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, - 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, 0x54, - 0x45, 0x44, 0x10, 0x01, 0x22, 0x2a, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0x17, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x0a, 0x15, 0x41, 0x72, 0x63, - 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, - 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x15, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x32, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x20, 0x0a, 0x1e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x71, 0x0a, - 0x18, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x12, 0x3b, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x70, 0x65, - 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, - 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, - 0x22, 0x4b, 0x0a, 0x19, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, - 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x46, 0x0a, - 0x16, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x49, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2e, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x22, 0x90, 0x02, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, - 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x1a, 0xae, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x4f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x4d, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x30, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x73, 0x22, 0x49, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1c, 0x0a, - 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd9, 0x09, 0x0a, 0x0b, - 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x13, 0x47, - 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, - 0x43, 0x6f, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x12, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, - 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, - 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1f, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4b, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x1d, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, - 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1e, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, - 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4e, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, - 0x1e, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x54, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x20, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, - 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x21, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, - 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x51, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, - 0x1f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x60, 0x0a, 0x11, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x25, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x63, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x59, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x10, 0x43, 0x6f, 0x72, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, - 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, - 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_CoreService_proto_rawDescOnce sync.Once - file_feast_core_CoreService_proto_rawDescData = file_feast_core_CoreService_proto_rawDesc -) - -func file_feast_core_CoreService_proto_rawDescGZIP() []byte { - file_feast_core_CoreService_proto_rawDescOnce.Do(func() { - file_feast_core_CoreService_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_CoreService_proto_rawDescData) - }) - return file_feast_core_CoreService_proto_rawDescData -} - -var file_feast_core_CoreService_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_feast_core_CoreService_proto_msgTypes = make([]protoimpl.MessageInfo, 37) -var file_feast_core_CoreService_proto_goTypes = []interface{}{ - (UpdateStoreResponse_Status)(0), // 0: feast.core.UpdateStoreResponse.Status - (*GetEntityRequest)(nil), // 1: feast.core.GetEntityRequest - (*GetEntityResponse)(nil), // 2: feast.core.GetEntityResponse - (*ListEntitiesRequest)(nil), // 3: feast.core.ListEntitiesRequest - (*ListEntitiesResponse)(nil), // 4: feast.core.ListEntitiesResponse - (*ListFeaturesRequest)(nil), // 5: feast.core.ListFeaturesRequest - (*ListFeaturesResponse)(nil), // 6: feast.core.ListFeaturesResponse - (*ListStoresRequest)(nil), // 7: feast.core.ListStoresRequest - (*ListStoresResponse)(nil), // 8: feast.core.ListStoresResponse - (*ApplyEntityRequest)(nil), // 9: feast.core.ApplyEntityRequest - (*ApplyEntityResponse)(nil), // 10: feast.core.ApplyEntityResponse - (*GetFeastCoreVersionRequest)(nil), // 11: feast.core.GetFeastCoreVersionRequest - (*GetFeastCoreVersionResponse)(nil), // 12: feast.core.GetFeastCoreVersionResponse - (*UpdateStoreRequest)(nil), // 13: feast.core.UpdateStoreRequest - (*UpdateStoreResponse)(nil), // 14: feast.core.UpdateStoreResponse - (*CreateProjectRequest)(nil), // 15: feast.core.CreateProjectRequest - (*CreateProjectResponse)(nil), // 16: feast.core.CreateProjectResponse - (*ArchiveProjectRequest)(nil), // 17: feast.core.ArchiveProjectRequest - (*ArchiveProjectResponse)(nil), // 18: feast.core.ArchiveProjectResponse - (*ListProjectsRequest)(nil), // 19: feast.core.ListProjectsRequest - (*ListProjectsResponse)(nil), // 20: feast.core.ListProjectsResponse - (*UpdateFeatureSetStatusResponse)(nil), // 21: feast.core.UpdateFeatureSetStatusResponse - (*ApplyFeatureTableRequest)(nil), // 22: feast.core.ApplyFeatureTableRequest - (*ApplyFeatureTableResponse)(nil), // 23: feast.core.ApplyFeatureTableResponse - (*GetFeatureTableRequest)(nil), // 24: feast.core.GetFeatureTableRequest - (*GetFeatureTableResponse)(nil), // 25: feast.core.GetFeatureTableResponse - (*ListFeatureTablesRequest)(nil), // 26: feast.core.ListFeatureTablesRequest - (*ListFeatureTablesResponse)(nil), // 27: feast.core.ListFeatureTablesResponse - (*DeleteFeatureTableRequest)(nil), // 28: feast.core.DeleteFeatureTableRequest - (*DeleteFeatureTableResponse)(nil), // 29: feast.core.DeleteFeatureTableResponse - (*ListEntitiesRequest_Filter)(nil), // 30: feast.core.ListEntitiesRequest.Filter - nil, // 31: feast.core.ListEntitiesRequest.Filter.LabelsEntry - (*ListFeaturesRequest_Filter)(nil), // 32: feast.core.ListFeaturesRequest.Filter - nil, // 33: feast.core.ListFeaturesRequest.Filter.LabelsEntry - nil, // 34: feast.core.ListFeaturesResponse.FeaturesEntry - (*ListStoresRequest_Filter)(nil), // 35: feast.core.ListStoresRequest.Filter - (*ListFeatureTablesRequest_Filter)(nil), // 36: feast.core.ListFeatureTablesRequest.Filter - nil, // 37: feast.core.ListFeatureTablesRequest.Filter.LabelsEntry - (*Entity)(nil), // 38: feast.core.Entity - (*Store)(nil), // 39: feast.core.Store - (*EntitySpecV2)(nil), // 40: feast.core.EntitySpecV2 - (*FeatureTableSpec)(nil), // 41: feast.core.FeatureTableSpec - (*FeatureTable)(nil), // 42: feast.core.FeatureTable - (*FeatureSpecV2)(nil), // 43: feast.core.FeatureSpecV2 -} -var file_feast_core_CoreService_proto_depIdxs = []int32{ - 38, // 0: feast.core.GetEntityResponse.entity:type_name -> feast.core.Entity - 30, // 1: feast.core.ListEntitiesRequest.filter:type_name -> feast.core.ListEntitiesRequest.Filter - 38, // 2: feast.core.ListEntitiesResponse.entities:type_name -> feast.core.Entity - 32, // 3: feast.core.ListFeaturesRequest.filter:type_name -> feast.core.ListFeaturesRequest.Filter - 34, // 4: feast.core.ListFeaturesResponse.features:type_name -> feast.core.ListFeaturesResponse.FeaturesEntry - 35, // 5: feast.core.ListStoresRequest.filter:type_name -> feast.core.ListStoresRequest.Filter - 39, // 6: feast.core.ListStoresResponse.store:type_name -> feast.core.Store - 40, // 7: feast.core.ApplyEntityRequest.spec:type_name -> feast.core.EntitySpecV2 - 38, // 8: feast.core.ApplyEntityResponse.entity:type_name -> feast.core.Entity - 39, // 9: feast.core.UpdateStoreRequest.store:type_name -> feast.core.Store - 39, // 10: feast.core.UpdateStoreResponse.store:type_name -> feast.core.Store - 0, // 11: feast.core.UpdateStoreResponse.status:type_name -> feast.core.UpdateStoreResponse.Status - 41, // 12: feast.core.ApplyFeatureTableRequest.table_spec:type_name -> feast.core.FeatureTableSpec - 42, // 13: feast.core.ApplyFeatureTableResponse.table:type_name -> feast.core.FeatureTable - 42, // 14: feast.core.GetFeatureTableResponse.table:type_name -> feast.core.FeatureTable - 36, // 15: feast.core.ListFeatureTablesRequest.filter:type_name -> feast.core.ListFeatureTablesRequest.Filter - 42, // 16: feast.core.ListFeatureTablesResponse.tables:type_name -> feast.core.FeatureTable - 31, // 17: feast.core.ListEntitiesRequest.Filter.labels:type_name -> feast.core.ListEntitiesRequest.Filter.LabelsEntry - 33, // 18: feast.core.ListFeaturesRequest.Filter.labels:type_name -> feast.core.ListFeaturesRequest.Filter.LabelsEntry - 43, // 19: feast.core.ListFeaturesResponse.FeaturesEntry.value:type_name -> feast.core.FeatureSpecV2 - 37, // 20: feast.core.ListFeatureTablesRequest.Filter.labels:type_name -> feast.core.ListFeatureTablesRequest.Filter.LabelsEntry - 11, // 21: feast.core.CoreService.GetFeastCoreVersion:input_type -> feast.core.GetFeastCoreVersionRequest - 1, // 22: feast.core.CoreService.GetEntity:input_type -> feast.core.GetEntityRequest - 5, // 23: feast.core.CoreService.ListFeatures:input_type -> feast.core.ListFeaturesRequest - 7, // 24: feast.core.CoreService.ListStores:input_type -> feast.core.ListStoresRequest - 9, // 25: feast.core.CoreService.ApplyEntity:input_type -> feast.core.ApplyEntityRequest - 3, // 26: feast.core.CoreService.ListEntities:input_type -> feast.core.ListEntitiesRequest - 13, // 27: feast.core.CoreService.UpdateStore:input_type -> feast.core.UpdateStoreRequest - 15, // 28: feast.core.CoreService.CreateProject:input_type -> feast.core.CreateProjectRequest - 17, // 29: feast.core.CoreService.ArchiveProject:input_type -> feast.core.ArchiveProjectRequest - 19, // 30: feast.core.CoreService.ListProjects:input_type -> feast.core.ListProjectsRequest - 22, // 31: feast.core.CoreService.ApplyFeatureTable:input_type -> feast.core.ApplyFeatureTableRequest - 26, // 32: feast.core.CoreService.ListFeatureTables:input_type -> feast.core.ListFeatureTablesRequest - 24, // 33: feast.core.CoreService.GetFeatureTable:input_type -> feast.core.GetFeatureTableRequest - 28, // 34: feast.core.CoreService.DeleteFeatureTable:input_type -> feast.core.DeleteFeatureTableRequest - 12, // 35: feast.core.CoreService.GetFeastCoreVersion:output_type -> feast.core.GetFeastCoreVersionResponse - 2, // 36: feast.core.CoreService.GetEntity:output_type -> feast.core.GetEntityResponse - 6, // 37: feast.core.CoreService.ListFeatures:output_type -> feast.core.ListFeaturesResponse - 8, // 38: feast.core.CoreService.ListStores:output_type -> feast.core.ListStoresResponse - 10, // 39: feast.core.CoreService.ApplyEntity:output_type -> feast.core.ApplyEntityResponse - 4, // 40: feast.core.CoreService.ListEntities:output_type -> feast.core.ListEntitiesResponse - 14, // 41: feast.core.CoreService.UpdateStore:output_type -> feast.core.UpdateStoreResponse - 16, // 42: feast.core.CoreService.CreateProject:output_type -> feast.core.CreateProjectResponse - 18, // 43: feast.core.CoreService.ArchiveProject:output_type -> feast.core.ArchiveProjectResponse - 20, // 44: feast.core.CoreService.ListProjects:output_type -> feast.core.ListProjectsResponse - 23, // 45: feast.core.CoreService.ApplyFeatureTable:output_type -> feast.core.ApplyFeatureTableResponse - 27, // 46: feast.core.CoreService.ListFeatureTables:output_type -> feast.core.ListFeatureTablesResponse - 25, // 47: feast.core.CoreService.GetFeatureTable:output_type -> feast.core.GetFeatureTableResponse - 29, // 48: feast.core.CoreService.DeleteFeatureTable:output_type -> feast.core.DeleteFeatureTableResponse - 35, // [35:49] is the sub-list for method output_type - 21, // [21:35] is the sub-list for method input_type - 21, // [21:21] is the sub-list for extension type_name - 21, // [21:21] is the sub-list for extension extendee - 0, // [0:21] is the sub-list for field type_name -} - -func init() { file_feast_core_CoreService_proto_init() } -func file_feast_core_CoreService_proto_init() { - if File_feast_core_CoreService_proto != nil { - return - } - file_feast_core_Entity_proto_init() - file_feast_core_Feature_proto_init() - file_feast_core_FeatureTable_proto_init() - file_feast_core_Store_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_core_CoreService_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetEntityRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetEntityResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEntitiesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEntitiesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListFeaturesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListFeaturesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListStoresRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListStoresResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyEntityRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyEntityResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeastCoreVersionRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeastCoreVersionResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateStoreRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateStoreResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateProjectRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateProjectResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArchiveProjectRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArchiveProjectResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProjectsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProjectsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateFeatureSetStatusResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyFeatureTableRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyFeatureTableResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeatureTableRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeatureTableResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListFeatureTablesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListFeatureTablesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteFeatureTableRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteFeatureTableResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEntitiesRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListFeaturesRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListStoresRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_CoreService_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListFeatureTablesRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_CoreService_proto_rawDesc, - NumEnums: 1, - NumMessages: 37, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_feast_core_CoreService_proto_goTypes, - DependencyIndexes: file_feast_core_CoreService_proto_depIdxs, - EnumInfos: file_feast_core_CoreService_proto_enumTypes, - MessageInfos: file_feast_core_CoreService_proto_msgTypes, - }.Build() - File_feast_core_CoreService_proto = out.File - file_feast_core_CoreService_proto_rawDesc = nil - file_feast_core_CoreService_proto_goTypes = nil - file_feast_core_CoreService_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 - -// CoreServiceClient is the client API for CoreService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type CoreServiceClient interface { - // Retrieve version information about this Feast deployment - GetFeastCoreVersion(ctx context.Context, in *GetFeastCoreVersionRequest, opts ...grpc.CallOption) (*GetFeastCoreVersionResponse, error) - // Returns a specific entity - GetEntity(ctx context.Context, in *GetEntityRequest, opts ...grpc.CallOption) (*GetEntityResponse, error) - // Returns all feature references and respective features matching that filter. If none are found - // an empty map will be returned - // If no filter is provided in the request, the response will contain all the features - // currently stored in the default project. - ListFeatures(ctx context.Context, in *ListFeaturesRequest, opts ...grpc.CallOption) (*ListFeaturesResponse, error) - // Retrieve store details given a filter. - // - // Returns all stores matching that filter. If none are found, an empty list will be returned. - // If no filter is provided in the request, the response will contain all the stores currently - // stored in the registry. - ListStores(ctx context.Context, in *ListStoresRequest, opts ...grpc.CallOption) (*ListStoresResponse, error) - // Create or update and existing entity. - // - // This function is idempotent - it will not create a new entity if schema does not change. - // Schema changes will update the entity if the changes are valid. - // Following changes are not valid: - // - Changes to name - // - Changes to type - ApplyEntity(ctx context.Context, in *ApplyEntityRequest, opts ...grpc.CallOption) (*ApplyEntityResponse, error) - // Returns all entity references and respective entities matching that filter. If none are found - // an empty map will be returned - // If no filter is provided in the request, the response will contain all the entities - // currently stored in the default project. - ListEntities(ctx context.Context, in *ListEntitiesRequest, opts ...grpc.CallOption) (*ListEntitiesResponse, error) - // Updates core with the configuration of the store. - // - // If the changes are valid, core will return the given store configuration in response, and - // start or update the necessary feature population jobs for the updated store. - UpdateStore(ctx context.Context, in *UpdateStoreRequest, opts ...grpc.CallOption) (*UpdateStoreResponse, error) - // Creates a project. Projects serve as namespaces within which resources like features will be - // created. Feature table names as must be unique within a project while field (Feature/Entity) names - // must be unique within a Feature Table. Project names themselves must be globally unique. - CreateProject(ctx context.Context, in *CreateProjectRequest, opts ...grpc.CallOption) (*CreateProjectResponse, error) - // Archives a project. Archived projects will continue to exist and function, but won't be visible - // through the Core API. Any existing ingestion or serving requests will continue to function, - // but will result in warning messages being logged. It is not possible to unarchive a project - // through the Core API - ArchiveProject(ctx context.Context, in *ArchiveProjectRequest, opts ...grpc.CallOption) (*ArchiveProjectResponse, error) - // Lists all projects active projects. - ListProjects(ctx context.Context, in *ListProjectsRequest, opts ...grpc.CallOption) (*ListProjectsResponse, error) - // Create or update an existing feature table. - // This function is idempotent - it will not create a new feature table if the schema does not change. - // Schema changes will update the feature table if the changes are valid. - // All changes except the following are valid: - // - Changes to feature table name. - // - Changes to entities - // - Changes to feature name and type - ApplyFeatureTable(ctx context.Context, in *ApplyFeatureTableRequest, opts ...grpc.CallOption) (*ApplyFeatureTableResponse, error) - // List feature tables that match a given filter. - // Returns the references of the Feature Tables matching that filter. If none are found, - // an empty list will be returned. - // If no filter is provided in the request, the response will match all the feature - // tables currently stored in the registry. - ListFeatureTables(ctx context.Context, in *ListFeatureTablesRequest, opts ...grpc.CallOption) (*ListFeatureTablesResponse, error) - // Returns a specific feature table - GetFeatureTable(ctx context.Context, in *GetFeatureTableRequest, opts ...grpc.CallOption) (*GetFeatureTableResponse, error) - // Delete a specific feature table - DeleteFeatureTable(ctx context.Context, in *DeleteFeatureTableRequest, opts ...grpc.CallOption) (*DeleteFeatureTableResponse, error) -} - -type coreServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewCoreServiceClient(cc grpc.ClientConnInterface) CoreServiceClient { - return &coreServiceClient{cc} -} - -func (c *coreServiceClient) GetFeastCoreVersion(ctx context.Context, in *GetFeastCoreVersionRequest, opts ...grpc.CallOption) (*GetFeastCoreVersionResponse, error) { - out := new(GetFeastCoreVersionResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/GetFeastCoreVersion", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) GetEntity(ctx context.Context, in *GetEntityRequest, opts ...grpc.CallOption) (*GetEntityResponse, error) { - out := new(GetEntityResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/GetEntity", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ListFeatures(ctx context.Context, in *ListFeaturesRequest, opts ...grpc.CallOption) (*ListFeaturesResponse, error) { - out := new(ListFeaturesResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ListFeatures", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ListStores(ctx context.Context, in *ListStoresRequest, opts ...grpc.CallOption) (*ListStoresResponse, error) { - out := new(ListStoresResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ListStores", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ApplyEntity(ctx context.Context, in *ApplyEntityRequest, opts ...grpc.CallOption) (*ApplyEntityResponse, error) { - out := new(ApplyEntityResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ApplyEntity", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ListEntities(ctx context.Context, in *ListEntitiesRequest, opts ...grpc.CallOption) (*ListEntitiesResponse, error) { - out := new(ListEntitiesResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ListEntities", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) UpdateStore(ctx context.Context, in *UpdateStoreRequest, opts ...grpc.CallOption) (*UpdateStoreResponse, error) { - out := new(UpdateStoreResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/UpdateStore", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) CreateProject(ctx context.Context, in *CreateProjectRequest, opts ...grpc.CallOption) (*CreateProjectResponse, error) { - out := new(CreateProjectResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/CreateProject", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ArchiveProject(ctx context.Context, in *ArchiveProjectRequest, opts ...grpc.CallOption) (*ArchiveProjectResponse, error) { - out := new(ArchiveProjectResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ArchiveProject", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ListProjects(ctx context.Context, in *ListProjectsRequest, opts ...grpc.CallOption) (*ListProjectsResponse, error) { - out := new(ListProjectsResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ListProjects", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ApplyFeatureTable(ctx context.Context, in *ApplyFeatureTableRequest, opts ...grpc.CallOption) (*ApplyFeatureTableResponse, error) { - out := new(ApplyFeatureTableResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ApplyFeatureTable", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) ListFeatureTables(ctx context.Context, in *ListFeatureTablesRequest, opts ...grpc.CallOption) (*ListFeatureTablesResponse, error) { - out := new(ListFeatureTablesResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/ListFeatureTables", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) GetFeatureTable(ctx context.Context, in *GetFeatureTableRequest, opts ...grpc.CallOption) (*GetFeatureTableResponse, error) { - out := new(GetFeatureTableResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/GetFeatureTable", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *coreServiceClient) DeleteFeatureTable(ctx context.Context, in *DeleteFeatureTableRequest, opts ...grpc.CallOption) (*DeleteFeatureTableResponse, error) { - out := new(DeleteFeatureTableResponse) - err := c.cc.Invoke(ctx, "/feast.core.CoreService/DeleteFeatureTable", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// CoreServiceServer is the server API for CoreService service. -type CoreServiceServer interface { - // Retrieve version information about this Feast deployment - GetFeastCoreVersion(context.Context, *GetFeastCoreVersionRequest) (*GetFeastCoreVersionResponse, error) - // Returns a specific entity - GetEntity(context.Context, *GetEntityRequest) (*GetEntityResponse, error) - // Returns all feature references and respective features matching that filter. If none are found - // an empty map will be returned - // If no filter is provided in the request, the response will contain all the features - // currently stored in the default project. - ListFeatures(context.Context, *ListFeaturesRequest) (*ListFeaturesResponse, error) - // Retrieve store details given a filter. - // - // Returns all stores matching that filter. If none are found, an empty list will be returned. - // If no filter is provided in the request, the response will contain all the stores currently - // stored in the registry. - ListStores(context.Context, *ListStoresRequest) (*ListStoresResponse, error) - // Create or update and existing entity. - // - // This function is idempotent - it will not create a new entity if schema does not change. - // Schema changes will update the entity if the changes are valid. - // Following changes are not valid: - // - Changes to name - // - Changes to type - ApplyEntity(context.Context, *ApplyEntityRequest) (*ApplyEntityResponse, error) - // Returns all entity references and respective entities matching that filter. If none are found - // an empty map will be returned - // If no filter is provided in the request, the response will contain all the entities - // currently stored in the default project. - ListEntities(context.Context, *ListEntitiesRequest) (*ListEntitiesResponse, error) - // Updates core with the configuration of the store. - // - // If the changes are valid, core will return the given store configuration in response, and - // start or update the necessary feature population jobs for the updated store. - UpdateStore(context.Context, *UpdateStoreRequest) (*UpdateStoreResponse, error) - // Creates a project. Projects serve as namespaces within which resources like features will be - // created. Feature table names as must be unique within a project while field (Feature/Entity) names - // must be unique within a Feature Table. Project names themselves must be globally unique. - CreateProject(context.Context, *CreateProjectRequest) (*CreateProjectResponse, error) - // Archives a project. Archived projects will continue to exist and function, but won't be visible - // through the Core API. Any existing ingestion or serving requests will continue to function, - // but will result in warning messages being logged. It is not possible to unarchive a project - // through the Core API - ArchiveProject(context.Context, *ArchiveProjectRequest) (*ArchiveProjectResponse, error) - // Lists all projects active projects. - ListProjects(context.Context, *ListProjectsRequest) (*ListProjectsResponse, error) - // Create or update an existing feature table. - // This function is idempotent - it will not create a new feature table if the schema does not change. - // Schema changes will update the feature table if the changes are valid. - // All changes except the following are valid: - // - Changes to feature table name. - // - Changes to entities - // - Changes to feature name and type - ApplyFeatureTable(context.Context, *ApplyFeatureTableRequest) (*ApplyFeatureTableResponse, error) - // List feature tables that match a given filter. - // Returns the references of the Feature Tables matching that filter. If none are found, - // an empty list will be returned. - // If no filter is provided in the request, the response will match all the feature - // tables currently stored in the registry. - ListFeatureTables(context.Context, *ListFeatureTablesRequest) (*ListFeatureTablesResponse, error) - // Returns a specific feature table - GetFeatureTable(context.Context, *GetFeatureTableRequest) (*GetFeatureTableResponse, error) - // Delete a specific feature table - DeleteFeatureTable(context.Context, *DeleteFeatureTableRequest) (*DeleteFeatureTableResponse, error) -} - -// UnimplementedCoreServiceServer can be embedded to have forward compatible implementations. -type UnimplementedCoreServiceServer struct { -} - -func (*UnimplementedCoreServiceServer) GetFeastCoreVersion(context.Context, *GetFeastCoreVersionRequest) (*GetFeastCoreVersionResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetFeastCoreVersion not implemented") -} -func (*UnimplementedCoreServiceServer) GetEntity(context.Context, *GetEntityRequest) (*GetEntityResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetEntity not implemented") -} -func (*UnimplementedCoreServiceServer) ListFeatures(context.Context, *ListFeaturesRequest) (*ListFeaturesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListFeatures not implemented") -} -func (*UnimplementedCoreServiceServer) ListStores(context.Context, *ListStoresRequest) (*ListStoresResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListStores not implemented") -} -func (*UnimplementedCoreServiceServer) ApplyEntity(context.Context, *ApplyEntityRequest) (*ApplyEntityResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ApplyEntity not implemented") -} -func (*UnimplementedCoreServiceServer) ListEntities(context.Context, *ListEntitiesRequest) (*ListEntitiesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListEntities not implemented") -} -func (*UnimplementedCoreServiceServer) UpdateStore(context.Context, *UpdateStoreRequest) (*UpdateStoreResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateStore not implemented") -} -func (*UnimplementedCoreServiceServer) CreateProject(context.Context, *CreateProjectRequest) (*CreateProjectResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateProject not implemented") -} -func (*UnimplementedCoreServiceServer) ArchiveProject(context.Context, *ArchiveProjectRequest) (*ArchiveProjectResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ArchiveProject not implemented") -} -func (*UnimplementedCoreServiceServer) ListProjects(context.Context, *ListProjectsRequest) (*ListProjectsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListProjects not implemented") -} -func (*UnimplementedCoreServiceServer) ApplyFeatureTable(context.Context, *ApplyFeatureTableRequest) (*ApplyFeatureTableResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ApplyFeatureTable not implemented") -} -func (*UnimplementedCoreServiceServer) ListFeatureTables(context.Context, *ListFeatureTablesRequest) (*ListFeatureTablesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListFeatureTables not implemented") -} -func (*UnimplementedCoreServiceServer) GetFeatureTable(context.Context, *GetFeatureTableRequest) (*GetFeatureTableResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetFeatureTable not implemented") -} -func (*UnimplementedCoreServiceServer) DeleteFeatureTable(context.Context, *DeleteFeatureTableRequest) (*DeleteFeatureTableResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteFeatureTable not implemented") -} - -func RegisterCoreServiceServer(s *grpc.Server, srv CoreServiceServer) { - s.RegisterService(&_CoreService_serviceDesc, srv) -} - -func _CoreService_GetFeastCoreVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetFeastCoreVersionRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).GetFeastCoreVersion(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/GetFeastCoreVersion", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).GetFeastCoreVersion(ctx, req.(*GetFeastCoreVersionRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_GetEntity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetEntityRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).GetEntity(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/GetEntity", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).GetEntity(ctx, req.(*GetEntityRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ListFeatures_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListFeaturesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ListFeatures(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ListFeatures", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ListFeatures(ctx, req.(*ListFeaturesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ListStores_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListStoresRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ListStores(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ListStores", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ListStores(ctx, req.(*ListStoresRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ApplyEntity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ApplyEntityRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ApplyEntity(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ApplyEntity", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ApplyEntity(ctx, req.(*ApplyEntityRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ListEntities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListEntitiesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ListEntities(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ListEntities", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ListEntities(ctx, req.(*ListEntitiesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_UpdateStore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UpdateStoreRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).UpdateStore(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/UpdateStore", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).UpdateStore(ctx, req.(*UpdateStoreRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_CreateProject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateProjectRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).CreateProject(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/CreateProject", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).CreateProject(ctx, req.(*CreateProjectRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ArchiveProject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ArchiveProjectRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ArchiveProject(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ArchiveProject", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ArchiveProject(ctx, req.(*ArchiveProjectRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ListProjects_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListProjectsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ListProjects(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ListProjects", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ListProjects(ctx, req.(*ListProjectsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ApplyFeatureTable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ApplyFeatureTableRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ApplyFeatureTable(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ApplyFeatureTable", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ApplyFeatureTable(ctx, req.(*ApplyFeatureTableRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_ListFeatureTables_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListFeatureTablesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).ListFeatureTables(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/ListFeatureTables", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).ListFeatureTables(ctx, req.(*ListFeatureTablesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_GetFeatureTable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetFeatureTableRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).GetFeatureTable(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/GetFeatureTable", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).GetFeatureTable(ctx, req.(*GetFeatureTableRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _CoreService_DeleteFeatureTable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteFeatureTableRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CoreServiceServer).DeleteFeatureTable(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.CoreService/DeleteFeatureTable", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CoreServiceServer).DeleteFeatureTable(ctx, req.(*DeleteFeatureTableRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _CoreService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "feast.core.CoreService", - HandlerType: (*CoreServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetFeastCoreVersion", - Handler: _CoreService_GetFeastCoreVersion_Handler, - }, - { - MethodName: "GetEntity", - Handler: _CoreService_GetEntity_Handler, - }, - { - MethodName: "ListFeatures", - Handler: _CoreService_ListFeatures_Handler, - }, - { - MethodName: "ListStores", - Handler: _CoreService_ListStores_Handler, - }, - { - MethodName: "ApplyEntity", - Handler: _CoreService_ApplyEntity_Handler, - }, - { - MethodName: "ListEntities", - Handler: _CoreService_ListEntities_Handler, - }, - { - MethodName: "UpdateStore", - Handler: _CoreService_UpdateStore_Handler, - }, - { - MethodName: "CreateProject", - Handler: _CoreService_CreateProject_Handler, - }, - { - MethodName: "ArchiveProject", - Handler: _CoreService_ArchiveProject_Handler, - }, - { - MethodName: "ListProjects", - Handler: _CoreService_ListProjects_Handler, - }, - { - MethodName: "ApplyFeatureTable", - Handler: _CoreService_ApplyFeatureTable_Handler, - }, - { - MethodName: "ListFeatureTables", - Handler: _CoreService_ListFeatureTables_Handler, - }, - { - MethodName: "GetFeatureTable", - Handler: _CoreService_GetFeatureTable_Handler, - }, - { - MethodName: "DeleteFeatureTable", - Handler: _CoreService_DeleteFeatureTable_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "feast/core/CoreService.proto", -} diff --git a/sdk/go/protos/feast/core/DataFormat.pb.go b/sdk/go/protos/feast/core/DataFormat.pb.go deleted file mode 100644 index 64c4ec80714..00000000000 --- a/sdk/go/protos/feast/core/DataFormat.pb.go +++ /dev/null @@ -1,489 +0,0 @@ -// -// Copyright 2020 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/core/DataFormat.proto - -package core - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Defines the file format encoding the features/entity data in files -type FileFormat struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Format: - // *FileFormat_ParquetFormat_ - Format isFileFormat_Format `protobuf_oneof:"format"` -} - -func (x *FileFormat) Reset() { - *x = FileFormat{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataFormat_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FileFormat) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FileFormat) ProtoMessage() {} - -func (x *FileFormat) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataFormat_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FileFormat.ProtoReflect.Descriptor instead. -func (*FileFormat) Descriptor() ([]byte, []int) { - return file_feast_core_DataFormat_proto_rawDescGZIP(), []int{0} -} - -func (m *FileFormat) GetFormat() isFileFormat_Format { - if m != nil { - return m.Format - } - return nil -} - -func (x *FileFormat) GetParquetFormat() *FileFormat_ParquetFormat { - if x, ok := x.GetFormat().(*FileFormat_ParquetFormat_); ok { - return x.ParquetFormat - } - return nil -} - -type isFileFormat_Format interface { - isFileFormat_Format() -} - -type FileFormat_ParquetFormat_ struct { - ParquetFormat *FileFormat_ParquetFormat `protobuf:"bytes,1,opt,name=parquet_format,json=parquetFormat,proto3,oneof"` -} - -func (*FileFormat_ParquetFormat_) isFileFormat_Format() {} - -// Defines the data format encoding features/entity data in data streams -type StreamFormat struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Specifies the data format and format specific options - // - // Types that are assignable to Format: - // *StreamFormat_AvroFormat_ - // *StreamFormat_ProtoFormat_ - Format isStreamFormat_Format `protobuf_oneof:"format"` -} - -func (x *StreamFormat) Reset() { - *x = StreamFormat{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataFormat_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StreamFormat) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StreamFormat) ProtoMessage() {} - -func (x *StreamFormat) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataFormat_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StreamFormat.ProtoReflect.Descriptor instead. -func (*StreamFormat) Descriptor() ([]byte, []int) { - return file_feast_core_DataFormat_proto_rawDescGZIP(), []int{1} -} - -func (m *StreamFormat) GetFormat() isStreamFormat_Format { - if m != nil { - return m.Format - } - return nil -} - -func (x *StreamFormat) GetAvroFormat() *StreamFormat_AvroFormat { - if x, ok := x.GetFormat().(*StreamFormat_AvroFormat_); ok { - return x.AvroFormat - } - return nil -} - -func (x *StreamFormat) GetProtoFormat() *StreamFormat_ProtoFormat { - if x, ok := x.GetFormat().(*StreamFormat_ProtoFormat_); ok { - return x.ProtoFormat - } - return nil -} - -type isStreamFormat_Format interface { - isStreamFormat_Format() -} - -type StreamFormat_AvroFormat_ struct { - AvroFormat *StreamFormat_AvroFormat `protobuf:"bytes,1,opt,name=avro_format,json=avroFormat,proto3,oneof"` -} - -type StreamFormat_ProtoFormat_ struct { - ProtoFormat *StreamFormat_ProtoFormat `protobuf:"bytes,2,opt,name=proto_format,json=protoFormat,proto3,oneof"` -} - -func (*StreamFormat_AvroFormat_) isStreamFormat_Format() {} - -func (*StreamFormat_ProtoFormat_) isStreamFormat_Format() {} - -// Defines options for the Parquet data format -type FileFormat_ParquetFormat struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *FileFormat_ParquetFormat) Reset() { - *x = FileFormat_ParquetFormat{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataFormat_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FileFormat_ParquetFormat) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FileFormat_ParquetFormat) ProtoMessage() {} - -func (x *FileFormat_ParquetFormat) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataFormat_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FileFormat_ParquetFormat.ProtoReflect.Descriptor instead. -func (*FileFormat_ParquetFormat) Descriptor() ([]byte, []int) { - return file_feast_core_DataFormat_proto_rawDescGZIP(), []int{0, 0} -} - -// Defines options for the protobuf data format -type StreamFormat_ProtoFormat struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Classpath to the generated Java Protobuf class that can be used to decode - // Feature data from the obtained stream message - ClassPath string `protobuf:"bytes,1,opt,name=class_path,json=classPath,proto3" json:"class_path,omitempty"` -} - -func (x *StreamFormat_ProtoFormat) Reset() { - *x = StreamFormat_ProtoFormat{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataFormat_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StreamFormat_ProtoFormat) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StreamFormat_ProtoFormat) ProtoMessage() {} - -func (x *StreamFormat_ProtoFormat) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataFormat_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StreamFormat_ProtoFormat.ProtoReflect.Descriptor instead. -func (*StreamFormat_ProtoFormat) Descriptor() ([]byte, []int) { - return file_feast_core_DataFormat_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *StreamFormat_ProtoFormat) GetClassPath() string { - if x != nil { - return x.ClassPath - } - return "" -} - -// Defines options for the avro data format -type StreamFormat_AvroFormat struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional if used in a File DataSource as schema is embedded in avro file. - // Specifies the schema of the Avro message as JSON string. - SchemaJson string `protobuf:"bytes,1,opt,name=schema_json,json=schemaJson,proto3" json:"schema_json,omitempty"` -} - -func (x *StreamFormat_AvroFormat) Reset() { - *x = StreamFormat_AvroFormat{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataFormat_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StreamFormat_AvroFormat) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StreamFormat_AvroFormat) ProtoMessage() {} - -func (x *StreamFormat_AvroFormat) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataFormat_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StreamFormat_AvroFormat.ProtoReflect.Descriptor instead. -func (*StreamFormat_AvroFormat) Descriptor() ([]byte, []int) { - return file_feast_core_DataFormat_proto_rawDescGZIP(), []int{1, 1} -} - -func (x *StreamFormat_AvroFormat) GetSchemaJson() string { - if x != nil { - return x.SchemaJson - } - return "" -} - -var File_feast_core_DataFormat_proto protoreflect.FileDescriptor - -var file_feast_core_DataFormat_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x44, 0x61, 0x74, - 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x76, 0x0a, 0x0a, 0x46, 0x69, 0x6c, - 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4d, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x71, 0x75, - 0x65, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x71, 0x75, 0x65, 0x74, 0x46, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x70, 0x61, 0x72, 0x71, 0x75, 0x65, 0x74, - 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x1a, 0x0f, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x71, 0x75, 0x65, - 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x22, 0x88, 0x02, 0x0a, 0x0c, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x12, 0x46, 0x0a, 0x0b, 0x61, 0x76, 0x72, 0x6f, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x2e, 0x41, 0x76, 0x72, 0x6f, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x48, 0x00, 0x52, 0x0a, - 0x61, 0x76, 0x72, 0x6f, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x49, 0x0a, 0x0c, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x46, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x1a, 0x2c, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x46, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x50, - 0x61, 0x74, 0x68, 0x1a, 0x2d, 0x0a, 0x0a, 0x41, 0x76, 0x72, 0x6f, 0x46, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4a, 0x73, - 0x6f, 0x6e, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x58, 0x0a, 0x10, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x42, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, - 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_DataFormat_proto_rawDescOnce sync.Once - file_feast_core_DataFormat_proto_rawDescData = file_feast_core_DataFormat_proto_rawDesc -) - -func file_feast_core_DataFormat_proto_rawDescGZIP() []byte { - file_feast_core_DataFormat_proto_rawDescOnce.Do(func() { - file_feast_core_DataFormat_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_DataFormat_proto_rawDescData) - }) - return file_feast_core_DataFormat_proto_rawDescData -} - -var file_feast_core_DataFormat_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_feast_core_DataFormat_proto_goTypes = []interface{}{ - (*FileFormat)(nil), // 0: feast.core.FileFormat - (*StreamFormat)(nil), // 1: feast.core.StreamFormat - (*FileFormat_ParquetFormat)(nil), // 2: feast.core.FileFormat.ParquetFormat - (*StreamFormat_ProtoFormat)(nil), // 3: feast.core.StreamFormat.ProtoFormat - (*StreamFormat_AvroFormat)(nil), // 4: feast.core.StreamFormat.AvroFormat -} -var file_feast_core_DataFormat_proto_depIdxs = []int32{ - 2, // 0: feast.core.FileFormat.parquet_format:type_name -> feast.core.FileFormat.ParquetFormat - 4, // 1: feast.core.StreamFormat.avro_format:type_name -> feast.core.StreamFormat.AvroFormat - 3, // 2: feast.core.StreamFormat.proto_format:type_name -> feast.core.StreamFormat.ProtoFormat - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_feast_core_DataFormat_proto_init() } -func file_feast_core_DataFormat_proto_init() { - if File_feast_core_DataFormat_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_core_DataFormat_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileFormat); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataFormat_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StreamFormat); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataFormat_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileFormat_ParquetFormat); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataFormat_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StreamFormat_ProtoFormat); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataFormat_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StreamFormat_AvroFormat); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_core_DataFormat_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*FileFormat_ParquetFormat_)(nil), - } - file_feast_core_DataFormat_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*StreamFormat_AvroFormat_)(nil), - (*StreamFormat_ProtoFormat_)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_DataFormat_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_DataFormat_proto_goTypes, - DependencyIndexes: file_feast_core_DataFormat_proto_depIdxs, - MessageInfos: file_feast_core_DataFormat_proto_msgTypes, - }.Build() - File_feast_core_DataFormat_proto = out.File - file_feast_core_DataFormat_proto_rawDesc = nil - file_feast_core_DataFormat_proto_goTypes = nil - file_feast_core_DataFormat_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/DataSource.pb.go b/sdk/go/protos/feast/core/DataSource.pb.go deleted file mode 100644 index d0d42c66dea..00000000000 --- a/sdk/go/protos/feast/core/DataSource.pb.go +++ /dev/null @@ -1,1211 +0,0 @@ -// -// Copyright 2020 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/core/DataSource.proto - -package core - -import ( - types "github.com/feast-dev/feast/sdk/go/protos/feast/types" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Type of Data Source. -// Next available id: 9 -type DataSource_SourceType int32 - -const ( - DataSource_INVALID DataSource_SourceType = 0 - DataSource_BATCH_FILE DataSource_SourceType = 1 - DataSource_BATCH_SNOWFLAKE DataSource_SourceType = 8 - DataSource_BATCH_BIGQUERY DataSource_SourceType = 2 - DataSource_BATCH_REDSHIFT DataSource_SourceType = 5 - DataSource_STREAM_KAFKA DataSource_SourceType = 3 - DataSource_STREAM_KINESIS DataSource_SourceType = 4 - DataSource_CUSTOM_SOURCE DataSource_SourceType = 6 - DataSource_REQUEST_SOURCE DataSource_SourceType = 7 -) - -// Enum value maps for DataSource_SourceType. -var ( - DataSource_SourceType_name = map[int32]string{ - 0: "INVALID", - 1: "BATCH_FILE", - 8: "BATCH_SNOWFLAKE", - 2: "BATCH_BIGQUERY", - 5: "BATCH_REDSHIFT", - 3: "STREAM_KAFKA", - 4: "STREAM_KINESIS", - 6: "CUSTOM_SOURCE", - 7: "REQUEST_SOURCE", - } - DataSource_SourceType_value = map[string]int32{ - "INVALID": 0, - "BATCH_FILE": 1, - "BATCH_SNOWFLAKE": 8, - "BATCH_BIGQUERY": 2, - "BATCH_REDSHIFT": 5, - "STREAM_KAFKA": 3, - "STREAM_KINESIS": 4, - "CUSTOM_SOURCE": 6, - "REQUEST_SOURCE": 7, - } -) - -func (x DataSource_SourceType) Enum() *DataSource_SourceType { - p := new(DataSource_SourceType) - *p = x - return p -} - -func (x DataSource_SourceType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (DataSource_SourceType) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_DataSource_proto_enumTypes[0].Descriptor() -} - -func (DataSource_SourceType) Type() protoreflect.EnumType { - return &file_feast_core_DataSource_proto_enumTypes[0] -} - -func (x DataSource_SourceType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use DataSource_SourceType.Descriptor instead. -func (DataSource_SourceType) EnumDescriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 0} -} - -// Defines a Data Source that can be used source Feature data -type DataSource struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type DataSource_SourceType `protobuf:"varint,1,opt,name=type,proto3,enum=feast.core.DataSource_SourceType" json:"type,omitempty"` - // Defines mapping between fields in the sourced data - // and fields in parent FeatureTable. - FieldMapping map[string]string `protobuf:"bytes,2,rep,name=field_mapping,json=fieldMapping,proto3" json:"field_mapping,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // Must specify event timestamp column name - EventTimestampColumn string `protobuf:"bytes,3,opt,name=event_timestamp_column,json=eventTimestampColumn,proto3" json:"event_timestamp_column,omitempty"` - // (Optional) Specify partition column - // useful for file sources - DatePartitionColumn string `protobuf:"bytes,4,opt,name=date_partition_column,json=datePartitionColumn,proto3" json:"date_partition_column,omitempty"` - // Must specify creation timestamp column name - CreatedTimestampColumn string `protobuf:"bytes,5,opt,name=created_timestamp_column,json=createdTimestampColumn,proto3" json:"created_timestamp_column,omitempty"` - // This is an internal field that is represents the python class for the data source object a proto object represents. - // This should be set by feast, and not by users. - DataSourceClassType string `protobuf:"bytes,17,opt,name=data_source_class_type,json=dataSourceClassType,proto3" json:"data_source_class_type,omitempty"` - // DataSource options. - // - // Types that are assignable to Options: - // *DataSource_FileOptions_ - // *DataSource_BigqueryOptions - // *DataSource_KafkaOptions_ - // *DataSource_KinesisOptions_ - // *DataSource_RedshiftOptions_ - // *DataSource_RequestDataOptions_ - // *DataSource_CustomOptions - // *DataSource_SnowflakeOptions_ - Options isDataSource_Options `protobuf_oneof:"options"` -} - -func (x *DataSource) Reset() { - *x = DataSource{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource) ProtoMessage() {} - -func (x *DataSource) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource.ProtoReflect.Descriptor instead. -func (*DataSource) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0} -} - -func (x *DataSource) GetType() DataSource_SourceType { - if x != nil { - return x.Type - } - return DataSource_INVALID -} - -func (x *DataSource) GetFieldMapping() map[string]string { - if x != nil { - return x.FieldMapping - } - return nil -} - -func (x *DataSource) GetEventTimestampColumn() string { - if x != nil { - return x.EventTimestampColumn - } - return "" -} - -func (x *DataSource) GetDatePartitionColumn() string { - if x != nil { - return x.DatePartitionColumn - } - return "" -} - -func (x *DataSource) GetCreatedTimestampColumn() string { - if x != nil { - return x.CreatedTimestampColumn - } - return "" -} - -func (x *DataSource) GetDataSourceClassType() string { - if x != nil { - return x.DataSourceClassType - } - return "" -} - -func (m *DataSource) GetOptions() isDataSource_Options { - if m != nil { - return m.Options - } - return nil -} - -func (x *DataSource) GetFileOptions() *DataSource_FileOptions { - if x, ok := x.GetOptions().(*DataSource_FileOptions_); ok { - return x.FileOptions - } - return nil -} - -func (x *DataSource) GetBigqueryOptions() *DataSource_BigQueryOptions { - if x, ok := x.GetOptions().(*DataSource_BigqueryOptions); ok { - return x.BigqueryOptions - } - return nil -} - -func (x *DataSource) GetKafkaOptions() *DataSource_KafkaOptions { - if x, ok := x.GetOptions().(*DataSource_KafkaOptions_); ok { - return x.KafkaOptions - } - return nil -} - -func (x *DataSource) GetKinesisOptions() *DataSource_KinesisOptions { - if x, ok := x.GetOptions().(*DataSource_KinesisOptions_); ok { - return x.KinesisOptions - } - return nil -} - -func (x *DataSource) GetRedshiftOptions() *DataSource_RedshiftOptions { - if x, ok := x.GetOptions().(*DataSource_RedshiftOptions_); ok { - return x.RedshiftOptions - } - return nil -} - -func (x *DataSource) GetRequestDataOptions() *DataSource_RequestDataOptions { - if x, ok := x.GetOptions().(*DataSource_RequestDataOptions_); ok { - return x.RequestDataOptions - } - return nil -} - -func (x *DataSource) GetCustomOptions() *DataSource_CustomSourceOptions { - if x, ok := x.GetOptions().(*DataSource_CustomOptions); ok { - return x.CustomOptions - } - return nil -} - -func (x *DataSource) GetSnowflakeOptions() *DataSource_SnowflakeOptions { - if x, ok := x.GetOptions().(*DataSource_SnowflakeOptions_); ok { - return x.SnowflakeOptions - } - return nil -} - -type isDataSource_Options interface { - isDataSource_Options() -} - -type DataSource_FileOptions_ struct { - FileOptions *DataSource_FileOptions `protobuf:"bytes,11,opt,name=file_options,json=fileOptions,proto3,oneof"` -} - -type DataSource_BigqueryOptions struct { - BigqueryOptions *DataSource_BigQueryOptions `protobuf:"bytes,12,opt,name=bigquery_options,json=bigqueryOptions,proto3,oneof"` -} - -type DataSource_KafkaOptions_ struct { - KafkaOptions *DataSource_KafkaOptions `protobuf:"bytes,13,opt,name=kafka_options,json=kafkaOptions,proto3,oneof"` -} - -type DataSource_KinesisOptions_ struct { - KinesisOptions *DataSource_KinesisOptions `protobuf:"bytes,14,opt,name=kinesis_options,json=kinesisOptions,proto3,oneof"` -} - -type DataSource_RedshiftOptions_ struct { - RedshiftOptions *DataSource_RedshiftOptions `protobuf:"bytes,15,opt,name=redshift_options,json=redshiftOptions,proto3,oneof"` -} - -type DataSource_RequestDataOptions_ struct { - RequestDataOptions *DataSource_RequestDataOptions `protobuf:"bytes,18,opt,name=request_data_options,json=requestDataOptions,proto3,oneof"` -} - -type DataSource_CustomOptions struct { - CustomOptions *DataSource_CustomSourceOptions `protobuf:"bytes,16,opt,name=custom_options,json=customOptions,proto3,oneof"` -} - -type DataSource_SnowflakeOptions_ struct { - SnowflakeOptions *DataSource_SnowflakeOptions `protobuf:"bytes,19,opt,name=snowflake_options,json=snowflakeOptions,proto3,oneof"` -} - -func (*DataSource_FileOptions_) isDataSource_Options() {} - -func (*DataSource_BigqueryOptions) isDataSource_Options() {} - -func (*DataSource_KafkaOptions_) isDataSource_Options() {} - -func (*DataSource_KinesisOptions_) isDataSource_Options() {} - -func (*DataSource_RedshiftOptions_) isDataSource_Options() {} - -func (*DataSource_RequestDataOptions_) isDataSource_Options() {} - -func (*DataSource_CustomOptions) isDataSource_Options() {} - -func (*DataSource_SnowflakeOptions_) isDataSource_Options() {} - -// Defines options for DataSource that sources features from a file -type DataSource_FileOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - FileFormat *FileFormat `protobuf:"bytes,1,opt,name=file_format,json=fileFormat,proto3" json:"file_format,omitempty"` - // Target URL of file to retrieve and source features from. - // s3://path/to/file for AWS S3 storage - // gs://path/to/file for GCP GCS storage - // file:///path/to/file for local storage - FileUrl string `protobuf:"bytes,2,opt,name=file_url,json=fileUrl,proto3" json:"file_url,omitempty"` - // override AWS S3 storage endpoint with custom S3 endpoint - S3EndpointOverride string `protobuf:"bytes,3,opt,name=s3_endpoint_override,json=s3EndpointOverride,proto3" json:"s3_endpoint_override,omitempty"` -} - -func (x *DataSource_FileOptions) Reset() { - *x = DataSource_FileOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_FileOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_FileOptions) ProtoMessage() {} - -func (x *DataSource_FileOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_FileOptions.ProtoReflect.Descriptor instead. -func (*DataSource_FileOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 1} -} - -func (x *DataSource_FileOptions) GetFileFormat() *FileFormat { - if x != nil { - return x.FileFormat - } - return nil -} - -func (x *DataSource_FileOptions) GetFileUrl() string { - if x != nil { - return x.FileUrl - } - return "" -} - -func (x *DataSource_FileOptions) GetS3EndpointOverride() string { - if x != nil { - return x.S3EndpointOverride - } - return "" -} - -// Defines options for DataSource that sources features from a BigQuery Query -type DataSource_BigQueryOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Full table reference in the form of [project:dataset.table] - TableRef string `protobuf:"bytes,1,opt,name=table_ref,json=tableRef,proto3" json:"table_ref,omitempty"` - // SQL query that returns a table containing feature data. Must contain an event_timestamp column, and respective - // entity columns - Query string `protobuf:"bytes,2,opt,name=query,proto3" json:"query,omitempty"` -} - -func (x *DataSource_BigQueryOptions) Reset() { - *x = DataSource_BigQueryOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_BigQueryOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_BigQueryOptions) ProtoMessage() {} - -func (x *DataSource_BigQueryOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_BigQueryOptions.ProtoReflect.Descriptor instead. -func (*DataSource_BigQueryOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 2} -} - -func (x *DataSource_BigQueryOptions) GetTableRef() string { - if x != nil { - return x.TableRef - } - return "" -} - -func (x *DataSource_BigQueryOptions) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -// Defines options for DataSource that sources features from Kafka messages. -// Each message should be a Protobuf that can be decoded with the generated -// Java Protobuf class at the given class path -type DataSource_KafkaOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Comma separated list of Kafka bootstrap servers. Used for feature tables without a defined source host[:port]] - BootstrapServers string `protobuf:"bytes,1,opt,name=bootstrap_servers,json=bootstrapServers,proto3" json:"bootstrap_servers,omitempty"` - // Kafka topic to collect feature data from. - Topic string `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"` - // Defines the stream data format encoding feature/entity data in Kafka messages. - MessageFormat *StreamFormat `protobuf:"bytes,3,opt,name=message_format,json=messageFormat,proto3" json:"message_format,omitempty"` -} - -func (x *DataSource_KafkaOptions) Reset() { - *x = DataSource_KafkaOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_KafkaOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_KafkaOptions) ProtoMessage() {} - -func (x *DataSource_KafkaOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_KafkaOptions.ProtoReflect.Descriptor instead. -func (*DataSource_KafkaOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 3} -} - -func (x *DataSource_KafkaOptions) GetBootstrapServers() string { - if x != nil { - return x.BootstrapServers - } - return "" -} - -func (x *DataSource_KafkaOptions) GetTopic() string { - if x != nil { - return x.Topic - } - return "" -} - -func (x *DataSource_KafkaOptions) GetMessageFormat() *StreamFormat { - if x != nil { - return x.MessageFormat - } - return nil -} - -// Defines options for DataSource that sources features from Kinesis records. -// Each record should be a Protobuf that can be decoded with the generated -// Java Protobuf class at the given class path -type DataSource_KinesisOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // AWS region of the Kinesis stream - Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` - // Name of the Kinesis stream to obtain feature data from. - StreamName string `protobuf:"bytes,2,opt,name=stream_name,json=streamName,proto3" json:"stream_name,omitempty"` - // Defines the data format encoding the feature/entity data in Kinesis records. - // Kinesis Data Sources support Avro and Proto as data formats. - RecordFormat *StreamFormat `protobuf:"bytes,3,opt,name=record_format,json=recordFormat,proto3" json:"record_format,omitempty"` -} - -func (x *DataSource_KinesisOptions) Reset() { - *x = DataSource_KinesisOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_KinesisOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_KinesisOptions) ProtoMessage() {} - -func (x *DataSource_KinesisOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_KinesisOptions.ProtoReflect.Descriptor instead. -func (*DataSource_KinesisOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 4} -} - -func (x *DataSource_KinesisOptions) GetRegion() string { - if x != nil { - return x.Region - } - return "" -} - -func (x *DataSource_KinesisOptions) GetStreamName() string { - if x != nil { - return x.StreamName - } - return "" -} - -func (x *DataSource_KinesisOptions) GetRecordFormat() *StreamFormat { - if x != nil { - return x.RecordFormat - } - return nil -} - -// Defines options for DataSource that sources features from a Redshift Query -type DataSource_RedshiftOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Redshift table name - Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` - // SQL query that returns a table containing feature data. Must contain an event_timestamp column, and respective - // entity columns - Query string `protobuf:"bytes,2,opt,name=query,proto3" json:"query,omitempty"` - // Redshift schema name - Schema string `protobuf:"bytes,3,opt,name=schema,proto3" json:"schema,omitempty"` -} - -func (x *DataSource_RedshiftOptions) Reset() { - *x = DataSource_RedshiftOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_RedshiftOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_RedshiftOptions) ProtoMessage() {} - -func (x *DataSource_RedshiftOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_RedshiftOptions.ProtoReflect.Descriptor instead. -func (*DataSource_RedshiftOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 5} -} - -func (x *DataSource_RedshiftOptions) GetTable() string { - if x != nil { - return x.Table - } - return "" -} - -func (x *DataSource_RedshiftOptions) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *DataSource_RedshiftOptions) GetSchema() string { - if x != nil { - return x.Schema - } - return "" -} - -// Defines options for DataSource that sources features from a Snowflake Query -type DataSource_SnowflakeOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Snowflake table name - Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` - // SQL query that returns a table containing feature data. Must contain an event_timestamp column, and respective - // entity columns - Query string `protobuf:"bytes,2,opt,name=query,proto3" json:"query,omitempty"` - // Snowflake schema name - Schema string `protobuf:"bytes,3,opt,name=schema,proto3" json:"schema,omitempty"` - // Snowflake schema name - Database string `protobuf:"bytes,4,opt,name=database,proto3" json:"database,omitempty"` -} - -func (x *DataSource_SnowflakeOptions) Reset() { - *x = DataSource_SnowflakeOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_SnowflakeOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_SnowflakeOptions) ProtoMessage() {} - -func (x *DataSource_SnowflakeOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_SnowflakeOptions.ProtoReflect.Descriptor instead. -func (*DataSource_SnowflakeOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 6} -} - -func (x *DataSource_SnowflakeOptions) GetTable() string { - if x != nil { - return x.Table - } - return "" -} - -func (x *DataSource_SnowflakeOptions) GetQuery() string { - if x != nil { - return x.Query - } - return "" -} - -func (x *DataSource_SnowflakeOptions) GetSchema() string { - if x != nil { - return x.Schema - } - return "" -} - -func (x *DataSource_SnowflakeOptions) GetDatabase() string { - if x != nil { - return x.Database - } - return "" -} - -// Defines configuration for custom third-party data sources. -type DataSource_CustomSourceOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Serialized configuration information for the data source. The implementer of the custom data source is - // responsible for serializing and deserializing data from bytes - Configuration []byte `protobuf:"bytes,1,opt,name=configuration,proto3" json:"configuration,omitempty"` -} - -func (x *DataSource_CustomSourceOptions) Reset() { - *x = DataSource_CustomSourceOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_CustomSourceOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_CustomSourceOptions) ProtoMessage() {} - -func (x *DataSource_CustomSourceOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_CustomSourceOptions.ProtoReflect.Descriptor instead. -func (*DataSource_CustomSourceOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 7} -} - -func (x *DataSource_CustomSourceOptions) GetConfiguration() []byte { - if x != nil { - return x.Configuration - } - return nil -} - -// Defines options for DataSource that sources features from request data -type DataSource_RequestDataOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the request data source - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Mapping of feature name to type - Schema map[string]types.ValueType_Enum `protobuf:"bytes,2,rep,name=schema,proto3" json:"schema,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=feast.types.ValueType_Enum"` -} - -func (x *DataSource_RequestDataOptions) Reset() { - *x = DataSource_RequestDataOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_DataSource_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataSource_RequestDataOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataSource_RequestDataOptions) ProtoMessage() {} - -func (x *DataSource_RequestDataOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_DataSource_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataSource_RequestDataOptions.ProtoReflect.Descriptor instead. -func (*DataSource_RequestDataOptions) Descriptor() ([]byte, []int) { - return file_feast_core_DataSource_proto_rawDescGZIP(), []int{0, 8} -} - -func (x *DataSource_RequestDataOptions) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *DataSource_RequestDataOptions) GetSchema() map[string]types.ValueType_Enum { - if x != nil { - return x.Schema - } - return nil -} - -var File_feast_core_DataSource_proto protoreflect.FileDescriptor - -var file_feast_core_DataSource_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x44, 0x61, 0x74, - 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x1b, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x44, 0x61, 0x74, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xe6, 0x11, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x35, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x4d, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x16, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, - 0x75, 0x6d, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x64, 0x61, 0x74, 0x65, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x38, - 0x0a, 0x18, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x16, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x61, 0x74, 0x61, - 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x47, 0x0a, - 0x0c, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x66, 0x69, 0x6c, 0x65, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x53, 0x0a, 0x10, 0x62, 0x69, 0x67, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x42, 0x69, 0x67, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x0f, 0x62, 0x69, 0x67, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4a, 0x0a, 0x0d, 0x6b, - 0x61, 0x66, 0x6b, 0x61, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x6b, 0x61, 0x66, 0x6b, 0x61, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x50, 0x0a, 0x0f, 0x6b, 0x69, 0x6e, 0x65, 0x73, - 0x69, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4b, 0x69, 0x6e, 0x65, 0x73, 0x69, 0x73, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x0e, 0x6b, 0x69, 0x6e, 0x65, 0x73, - 0x69, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x53, 0x0a, 0x10, 0x72, 0x65, 0x64, - 0x73, 0x68, 0x69, 0x66, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0f, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x64, 0x73, - 0x68, 0x69, 0x66, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x0f, 0x72, - 0x65, 0x64, 0x73, 0x68, 0x69, 0x66, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5d, - 0x0a, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x53, 0x0a, - 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x48, 0x00, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x56, 0x0a, 0x11, 0x73, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x5f, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x10, 0x73, 0x6e, 0x6f, 0x77, 0x66, 0x6c, - 0x61, 0x6b, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x93, 0x01, 0x0a, 0x0b, - 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x66, - 0x69, 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x69, - 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x46, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x6c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x72, 0x6c, 0x12, - 0x30, 0x0a, 0x14, 0x73, 0x33, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, - 0x33, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x1a, 0x44, 0x0a, 0x0f, 0x42, 0x69, 0x67, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, - 0x66, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x92, 0x01, 0x0a, 0x0c, 0x4b, 0x61, 0x66, 0x6b, - 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x62, 0x6f, 0x6f, 0x74, - 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x3f, 0x0a, 0x0e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0d, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x1a, 0x88, 0x01, 0x0a, - 0x0e, 0x4b, 0x69, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x6f, - 0x72, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0c, 0x72, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x1a, 0x55, 0x0a, 0x0f, 0x52, 0x65, 0x64, 0x73, 0x68, - 0x69, 0x66, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x72, - 0x0a, 0x10, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x1a, 0x3b, 0x0a, 0x13, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, - 0xcf, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x73, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x56, 0x0a, 0x0b, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0xb3, 0x01, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, - 0x0a, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x13, 0x0a, - 0x0f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x53, 0x4e, 0x4f, 0x57, 0x46, 0x4c, 0x41, 0x4b, 0x45, - 0x10, 0x08, 0x12, 0x12, 0x0a, 0x0e, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x42, 0x49, 0x47, 0x51, - 0x55, 0x45, 0x52, 0x59, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, - 0x52, 0x45, 0x44, 0x53, 0x48, 0x49, 0x46, 0x54, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, - 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4b, 0x41, 0x46, 0x4b, 0x41, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, - 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4b, 0x49, 0x4e, 0x45, 0x53, 0x49, 0x53, 0x10, 0x04, - 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, 0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x07, 0x42, 0x09, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x0b, 0x42, 0x58, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0f, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, - 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, - 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_DataSource_proto_rawDescOnce sync.Once - file_feast_core_DataSource_proto_rawDescData = file_feast_core_DataSource_proto_rawDesc -) - -func file_feast_core_DataSource_proto_rawDescGZIP() []byte { - file_feast_core_DataSource_proto_rawDescOnce.Do(func() { - file_feast_core_DataSource_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_DataSource_proto_rawDescData) - }) - return file_feast_core_DataSource_proto_rawDescData -} - -var file_feast_core_DataSource_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_feast_core_DataSource_proto_msgTypes = make([]protoimpl.MessageInfo, 11) -var file_feast_core_DataSource_proto_goTypes = []interface{}{ - (DataSource_SourceType)(0), // 0: feast.core.DataSource.SourceType - (*DataSource)(nil), // 1: feast.core.DataSource - nil, // 2: feast.core.DataSource.FieldMappingEntry - (*DataSource_FileOptions)(nil), // 3: feast.core.DataSource.FileOptions - (*DataSource_BigQueryOptions)(nil), // 4: feast.core.DataSource.BigQueryOptions - (*DataSource_KafkaOptions)(nil), // 5: feast.core.DataSource.KafkaOptions - (*DataSource_KinesisOptions)(nil), // 6: feast.core.DataSource.KinesisOptions - (*DataSource_RedshiftOptions)(nil), // 7: feast.core.DataSource.RedshiftOptions - (*DataSource_SnowflakeOptions)(nil), // 8: feast.core.DataSource.SnowflakeOptions - (*DataSource_CustomSourceOptions)(nil), // 9: feast.core.DataSource.CustomSourceOptions - (*DataSource_RequestDataOptions)(nil), // 10: feast.core.DataSource.RequestDataOptions - nil, // 11: feast.core.DataSource.RequestDataOptions.SchemaEntry - (*FileFormat)(nil), // 12: feast.core.FileFormat - (*StreamFormat)(nil), // 13: feast.core.StreamFormat - (types.ValueType_Enum)(0), // 14: feast.types.ValueType.Enum -} -var file_feast_core_DataSource_proto_depIdxs = []int32{ - 0, // 0: feast.core.DataSource.type:type_name -> feast.core.DataSource.SourceType - 2, // 1: feast.core.DataSource.field_mapping:type_name -> feast.core.DataSource.FieldMappingEntry - 3, // 2: feast.core.DataSource.file_options:type_name -> feast.core.DataSource.FileOptions - 4, // 3: feast.core.DataSource.bigquery_options:type_name -> feast.core.DataSource.BigQueryOptions - 5, // 4: feast.core.DataSource.kafka_options:type_name -> feast.core.DataSource.KafkaOptions - 6, // 5: feast.core.DataSource.kinesis_options:type_name -> feast.core.DataSource.KinesisOptions - 7, // 6: feast.core.DataSource.redshift_options:type_name -> feast.core.DataSource.RedshiftOptions - 10, // 7: feast.core.DataSource.request_data_options:type_name -> feast.core.DataSource.RequestDataOptions - 9, // 8: feast.core.DataSource.custom_options:type_name -> feast.core.DataSource.CustomSourceOptions - 8, // 9: feast.core.DataSource.snowflake_options:type_name -> feast.core.DataSource.SnowflakeOptions - 12, // 10: feast.core.DataSource.FileOptions.file_format:type_name -> feast.core.FileFormat - 13, // 11: feast.core.DataSource.KafkaOptions.message_format:type_name -> feast.core.StreamFormat - 13, // 12: feast.core.DataSource.KinesisOptions.record_format:type_name -> feast.core.StreamFormat - 11, // 13: feast.core.DataSource.RequestDataOptions.schema:type_name -> feast.core.DataSource.RequestDataOptions.SchemaEntry - 14, // 14: feast.core.DataSource.RequestDataOptions.SchemaEntry.value:type_name -> feast.types.ValueType.Enum - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_feast_core_DataSource_proto_init() } -func file_feast_core_DataSource_proto_init() { - if File_feast_core_DataSource_proto != nil { - return - } - file_feast_core_DataFormat_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_core_DataSource_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_FileOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_BigQueryOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_KafkaOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_KinesisOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_RedshiftOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_SnowflakeOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_CustomSourceOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_DataSource_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSource_RequestDataOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_core_DataSource_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*DataSource_FileOptions_)(nil), - (*DataSource_BigqueryOptions)(nil), - (*DataSource_KafkaOptions_)(nil), - (*DataSource_KinesisOptions_)(nil), - (*DataSource_RedshiftOptions_)(nil), - (*DataSource_RequestDataOptions_)(nil), - (*DataSource_CustomOptions)(nil), - (*DataSource_SnowflakeOptions_)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_DataSource_proto_rawDesc, - NumEnums: 1, - NumMessages: 11, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_DataSource_proto_goTypes, - DependencyIndexes: file_feast_core_DataSource_proto_depIdxs, - EnumInfos: file_feast_core_DataSource_proto_enumTypes, - MessageInfos: file_feast_core_DataSource_proto_msgTypes, - }.Build() - File_feast_core_DataSource_proto = out.File - file_feast_core_DataSource_proto_rawDesc = nil - file_feast_core_DataSource_proto_goTypes = nil - file_feast_core_DataSource_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/Entity.pb.go b/sdk/go/protos/feast/core/Entity.pb.go deleted file mode 100644 index 245f724e0a2..00000000000 --- a/sdk/go/protos/feast/core/Entity.pb.go +++ /dev/null @@ -1,395 +0,0 @@ -// -// * Copyright 2020 The Feast Authors -// * -// * 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 -// * -// * https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/core/Entity.proto - -package core - -import ( - types "github.com/feast-dev/feast/sdk/go/protos/feast/types" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Entity struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // User-specified specifications of this entity. - Spec *EntitySpecV2 `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` - // System-populated metadata for this entity. - Meta *EntityMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` -} - -func (x *Entity) Reset() { - *x = Entity{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Entity_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Entity) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Entity) ProtoMessage() {} - -func (x *Entity) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Entity_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Entity.ProtoReflect.Descriptor instead. -func (*Entity) Descriptor() ([]byte, []int) { - return file_feast_core_Entity_proto_rawDescGZIP(), []int{0} -} - -func (x *Entity) GetSpec() *EntitySpecV2 { - if x != nil { - return x.Spec - } - return nil -} - -func (x *Entity) GetMeta() *EntityMeta { - if x != nil { - return x.Meta - } - return nil -} - -type EntitySpecV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the entity. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Name of Feast project that this feature table belongs to. - Project string `protobuf:"bytes,9,opt,name=project,proto3" json:"project,omitempty"` - // Type of the entity. - ValueType types.ValueType_Enum `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=feast.types.ValueType_Enum" json:"value_type,omitempty"` - // Description of the entity. - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - // Join key for the entity (i.e. name of the column the entity maps to). - JoinKey string `protobuf:"bytes,4,opt,name=join_key,json=joinKey,proto3" json:"join_key,omitempty"` - // User defined metadata - Labels map[string]string `protobuf:"bytes,8,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *EntitySpecV2) Reset() { - *x = EntitySpecV2{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Entity_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EntitySpecV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EntitySpecV2) ProtoMessage() {} - -func (x *EntitySpecV2) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Entity_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EntitySpecV2.ProtoReflect.Descriptor instead. -func (*EntitySpecV2) Descriptor() ([]byte, []int) { - return file_feast_core_Entity_proto_rawDescGZIP(), []int{1} -} - -func (x *EntitySpecV2) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *EntitySpecV2) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *EntitySpecV2) GetValueType() types.ValueType_Enum { - if x != nil { - return x.ValueType - } - return types.ValueType_Enum(0) -} - -func (x *EntitySpecV2) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *EntitySpecV2) GetJoinKey() string { - if x != nil { - return x.JoinKey - } - return "" -} - -func (x *EntitySpecV2) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -type EntityMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=created_timestamp,json=createdTimestamp,proto3" json:"created_timestamp,omitempty"` - LastUpdatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=last_updated_timestamp,json=lastUpdatedTimestamp,proto3" json:"last_updated_timestamp,omitempty"` -} - -func (x *EntityMeta) Reset() { - *x = EntityMeta{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Entity_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EntityMeta) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EntityMeta) ProtoMessage() {} - -func (x *EntityMeta) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Entity_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EntityMeta.ProtoReflect.Descriptor instead. -func (*EntityMeta) Descriptor() ([]byte, []int) { - return file_feast_core_Entity_proto_rawDescGZIP(), []int{2} -} - -func (x *EntityMeta) GetCreatedTimestamp() *timestamppb.Timestamp { - if x != nil { - return x.CreatedTimestamp - } - return nil -} - -func (x *EntityMeta) GetLastUpdatedTimestamp() *timestamppb.Timestamp { - if x != nil { - return x.LastUpdatedTimestamp - } - return nil -} - -var File_feast_core_Entity_proto protoreflect.FileDescriptor - -var file_feast_core_Entity_proto_rawDesc = []byte{ - 0x0a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x45, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x62, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x2c, 0x0a, 0x04, 0x73, 0x70, 0x65, - 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x70, 0x65, 0x63, 0x56, - 0x32, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2a, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, - 0x65, 0x74, 0x61, 0x22, 0xae, 0x02, 0x0a, 0x0c, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x70, - 0x65, 0x63, 0x56, 0x32, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, - 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x19, 0x0a, 0x08, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6a, 0x6f, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x06, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, - 0x70, 0x65, 0x63, 0x56, 0x32, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa7, 0x01, 0x0a, 0x0a, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, - 0x65, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x50, 0x0a, 0x16, - 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x54, - 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x42, 0x0b, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, - 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, - 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, - 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_Entity_proto_rawDescOnce sync.Once - file_feast_core_Entity_proto_rawDescData = file_feast_core_Entity_proto_rawDesc -) - -func file_feast_core_Entity_proto_rawDescGZIP() []byte { - file_feast_core_Entity_proto_rawDescOnce.Do(func() { - file_feast_core_Entity_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_Entity_proto_rawDescData) - }) - return file_feast_core_Entity_proto_rawDescData -} - -var file_feast_core_Entity_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_feast_core_Entity_proto_goTypes = []interface{}{ - (*Entity)(nil), // 0: feast.core.Entity - (*EntitySpecV2)(nil), // 1: feast.core.EntitySpecV2 - (*EntityMeta)(nil), // 2: feast.core.EntityMeta - nil, // 3: feast.core.EntitySpecV2.LabelsEntry - (types.ValueType_Enum)(0), // 4: feast.types.ValueType.Enum - (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp -} -var file_feast_core_Entity_proto_depIdxs = []int32{ - 1, // 0: feast.core.Entity.spec:type_name -> feast.core.EntitySpecV2 - 2, // 1: feast.core.Entity.meta:type_name -> feast.core.EntityMeta - 4, // 2: feast.core.EntitySpecV2.value_type:type_name -> feast.types.ValueType.Enum - 3, // 3: feast.core.EntitySpecV2.labels:type_name -> feast.core.EntitySpecV2.LabelsEntry - 5, // 4: feast.core.EntityMeta.created_timestamp:type_name -> google.protobuf.Timestamp - 5, // 5: feast.core.EntityMeta.last_updated_timestamp:type_name -> google.protobuf.Timestamp - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name -} - -func init() { file_feast_core_Entity_proto_init() } -func file_feast_core_Entity_proto_init() { - if File_feast_core_Entity_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_core_Entity_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Entity); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_Entity_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EntitySpecV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_Entity_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EntityMeta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_Entity_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_Entity_proto_goTypes, - DependencyIndexes: file_feast_core_Entity_proto_depIdxs, - MessageInfos: file_feast_core_Entity_proto_msgTypes, - }.Build() - File_feast_core_Entity_proto = out.File - file_feast_core_Entity_proto_rawDesc = nil - file_feast_core_Entity_proto_goTypes = nil - file_feast_core_Entity_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/Feature.pb.go b/sdk/go/protos/feast/core/Feature.pb.go deleted file mode 100644 index a30fafb9d37..00000000000 --- a/sdk/go/protos/feast/core/Feature.pb.go +++ /dev/null @@ -1,200 +0,0 @@ -// -// Copyright 2020 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/core/Feature.proto - -package core - -import ( - types "github.com/feast-dev/feast/sdk/go/protos/feast/types" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type FeatureSpecV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the feature. Not updatable. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Value type of the feature. Not updatable. - ValueType types.ValueType_Enum `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=feast.types.ValueType_Enum" json:"value_type,omitempty"` - // Labels for user defined metadata on a feature - Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *FeatureSpecV2) Reset() { - *x = FeatureSpecV2{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Feature_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureSpecV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureSpecV2) ProtoMessage() {} - -func (x *FeatureSpecV2) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Feature_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureSpecV2.ProtoReflect.Descriptor instead. -func (*FeatureSpecV2) Descriptor() ([]byte, []int) { - return file_feast_core_Feature_proto_rawDescGZIP(), []int{0} -} - -func (x *FeatureSpecV2) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *FeatureSpecV2) GetValueType() types.ValueType_Enum { - if x != nil { - return x.ValueType - } - return types.ValueType_Enum(0) -} - -func (x *FeatureSpecV2) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -var File_feast_core_Feature_proto protoreflect.FileDescriptor - -var file_feast_core_Feature_proto_rawDesc = []byte{ - 0x0a, 0x18, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xd9, 0x01, 0x0a, 0x0d, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x56, - 0x32, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x25, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x56, 0x32, 0x2e, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x55, 0x0a, 0x10, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, - 0x0c, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, - 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, - 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_Feature_proto_rawDescOnce sync.Once - file_feast_core_Feature_proto_rawDescData = file_feast_core_Feature_proto_rawDesc -) - -func file_feast_core_Feature_proto_rawDescGZIP() []byte { - file_feast_core_Feature_proto_rawDescOnce.Do(func() { - file_feast_core_Feature_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_Feature_proto_rawDescData) - }) - return file_feast_core_Feature_proto_rawDescData -} - -var file_feast_core_Feature_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_feast_core_Feature_proto_goTypes = []interface{}{ - (*FeatureSpecV2)(nil), // 0: feast.core.FeatureSpecV2 - nil, // 1: feast.core.FeatureSpecV2.LabelsEntry - (types.ValueType_Enum)(0), // 2: feast.types.ValueType.Enum -} -var file_feast_core_Feature_proto_depIdxs = []int32{ - 2, // 0: feast.core.FeatureSpecV2.value_type:type_name -> feast.types.ValueType.Enum - 1, // 1: feast.core.FeatureSpecV2.labels:type_name -> feast.core.FeatureSpecV2.LabelsEntry - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_feast_core_Feature_proto_init() } -func file_feast_core_Feature_proto_init() { - if File_feast_core_Feature_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_core_Feature_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSpecV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_Feature_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_Feature_proto_goTypes, - DependencyIndexes: file_feast_core_Feature_proto_depIdxs, - MessageInfos: file_feast_core_Feature_proto_msgTypes, - }.Build() - File_feast_core_Feature_proto = out.File - file_feast_core_Feature_proto_rawDesc = nil - file_feast_core_Feature_proto_goTypes = nil - file_feast_core_Feature_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/FeatureSet.pb.go b/sdk/go/protos/feast/core/FeatureSet.pb.go deleted file mode 100644 index 520c4881be5..00000000000 --- a/sdk/go/protos/feast/core/FeatureSet.pb.go +++ /dev/null @@ -1,1141 +0,0 @@ -// -// * Copyright 2019 The Feast Authors -// * -// * 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 -// * -// * https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.10.0 -// source: feast/core/FeatureSet.proto - -package core - -import ( - types "github.com/feast-dev/feast/sdk/go/protos/feast/types" - v0 "github.com/feast-dev/feast/sdk/go/protos/tensorflow_metadata/proto/v0" - proto "github.com/golang/protobuf/proto" - duration "github.com/golang/protobuf/ptypes/duration" - timestamp "github.com/golang/protobuf/ptypes/timestamp" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 FeatureSetStatus int32 - -const ( - FeatureSetStatus_STATUS_INVALID FeatureSetStatus = 0 - FeatureSetStatus_STATUS_PENDING FeatureSetStatus = 1 - FeatureSetStatus_STATUS_JOB_STARTING FeatureSetStatus = 3 - FeatureSetStatus_STATUS_READY FeatureSetStatus = 2 -) - -// Enum value maps for FeatureSetStatus. -var ( - FeatureSetStatus_name = map[int32]string{ - 0: "STATUS_INVALID", - 1: "STATUS_PENDING", - 3: "STATUS_JOB_STARTING", - 2: "STATUS_READY", - } - FeatureSetStatus_value = map[string]int32{ - "STATUS_INVALID": 0, - "STATUS_PENDING": 1, - "STATUS_JOB_STARTING": 3, - "STATUS_READY": 2, - } -) - -func (x FeatureSetStatus) Enum() *FeatureSetStatus { - p := new(FeatureSetStatus) - *p = x - return p -} - -func (x FeatureSetStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (FeatureSetStatus) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_FeatureSet_proto_enumTypes[0].Descriptor() -} - -func (FeatureSetStatus) Type() protoreflect.EnumType { - return &file_feast_core_FeatureSet_proto_enumTypes[0] -} - -func (x FeatureSetStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use FeatureSetStatus.Descriptor instead. -func (FeatureSetStatus) EnumDescriptor() ([]byte, []int) { - return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{0} -} - -type FeatureSetJobDeliveryStatus int32 - -const ( - FeatureSetJobDeliveryStatus_STATUS_IN_PROGRESS FeatureSetJobDeliveryStatus = 0 - FeatureSetJobDeliveryStatus_STATUS_DELIVERED FeatureSetJobDeliveryStatus = 1 -) - -// Enum value maps for FeatureSetJobDeliveryStatus. -var ( - FeatureSetJobDeliveryStatus_name = map[int32]string{ - 0: "STATUS_IN_PROGRESS", - 1: "STATUS_DELIVERED", - } - FeatureSetJobDeliveryStatus_value = map[string]int32{ - "STATUS_IN_PROGRESS": 0, - "STATUS_DELIVERED": 1, - } -) - -func (x FeatureSetJobDeliveryStatus) Enum() *FeatureSetJobDeliveryStatus { - p := new(FeatureSetJobDeliveryStatus) - *p = x - return p -} - -func (x FeatureSetJobDeliveryStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (FeatureSetJobDeliveryStatus) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_FeatureSet_proto_enumTypes[1].Descriptor() -} - -func (FeatureSetJobDeliveryStatus) Type() protoreflect.EnumType { - return &file_feast_core_FeatureSet_proto_enumTypes[1] -} - -func (x FeatureSetJobDeliveryStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use FeatureSetJobDeliveryStatus.Descriptor instead. -func (FeatureSetJobDeliveryStatus) EnumDescriptor() ([]byte, []int) { - return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{1} -} - -type FeatureSet struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // User-specified specifications of this feature set. - Spec *FeatureSetSpec `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` - // System-populated metadata for this feature set. - Meta *FeatureSetMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` -} - -func (x *FeatureSet) Reset() { - *x = FeatureSet{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureSet_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureSet) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureSet) ProtoMessage() {} - -func (x *FeatureSet) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureSet_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureSet.ProtoReflect.Descriptor instead. -func (*FeatureSet) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{0} -} - -func (x *FeatureSet) GetSpec() *FeatureSetSpec { - if x != nil { - return x.Spec - } - return nil -} - -func (x *FeatureSet) GetMeta() *FeatureSetMeta { - if x != nil { - return x.Meta - } - return nil -} - -type FeatureSetSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of project that this feature set belongs to. - Project string `protobuf:"bytes,7,opt,name=project,proto3" json:"project,omitempty"` - // Name of the feature set. Must be unique. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // List of entities contained within this featureSet. - // This allows the feature to be used during joins between feature sets. - // If the featureSet is ingested into a store that supports keys, this value - // will be made a key. - Entities []*EntitySpec `protobuf:"bytes,3,rep,name=entities,proto3" json:"entities,omitempty"` - // List of features contained within this featureSet. - Features []*FeatureSpec `protobuf:"bytes,4,rep,name=features,proto3" json:"features,omitempty"` - // Features in this feature set will only be retrieved if they are found - // after [time - max_age]. Missing or older feature values will be returned - // as nulls and indicated to end user - MaxAge *duration.Duration `protobuf:"bytes,5,opt,name=max_age,json=maxAge,proto3" json:"max_age,omitempty"` - // Optional. Source on which feature rows can be found. - // If not set, source will be set to the default value configured in Feast Core. - Source *Source `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` - // User defined metadata - Labels map[string]string `protobuf:"bytes,8,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // Read-only self-incrementing version that increases monotonically - // when changes are made to a feature set - Version int32 `protobuf:"varint,9,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *FeatureSetSpec) Reset() { - *x = FeatureSetSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureSet_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureSetSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureSetSpec) ProtoMessage() {} - -func (x *FeatureSetSpec) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureSet_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureSetSpec.ProtoReflect.Descriptor instead. -func (*FeatureSetSpec) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{1} -} - -func (x *FeatureSetSpec) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *FeatureSetSpec) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *FeatureSetSpec) GetEntities() []*EntitySpec { - if x != nil { - return x.Entities - } - return nil -} - -func (x *FeatureSetSpec) GetFeatures() []*FeatureSpec { - if x != nil { - return x.Features - } - return nil -} - -func (x *FeatureSetSpec) GetMaxAge() *duration.Duration { - if x != nil { - return x.MaxAge - } - return nil -} - -func (x *FeatureSetSpec) GetSource() *Source { - if x != nil { - return x.Source - } - return nil -} - -func (x *FeatureSetSpec) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -func (x *FeatureSetSpec) GetVersion() int32 { - if x != nil { - return x.Version - } - return 0 -} - -type EntitySpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the entity. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Value type of the entity. - ValueType types.ValueType_Enum `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=feast.types.ValueType_Enum" json:"value_type,omitempty"` -} - -func (x *EntitySpec) Reset() { - *x = EntitySpec{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureSet_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EntitySpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EntitySpec) ProtoMessage() {} - -func (x *EntitySpec) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureSet_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EntitySpec.ProtoReflect.Descriptor instead. -func (*EntitySpec) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{2} -} - -func (x *EntitySpec) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *EntitySpec) GetValueType() types.ValueType_Enum { - if x != nil { - return x.ValueType - } - return types.ValueType_INVALID -} - -type FeatureSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the feature. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Value type of the feature. - ValueType types.ValueType_Enum `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=feast.types.ValueType_Enum" json:"value_type,omitempty"` - // Labels for user defined metadata on a feature - Labels map[string]string `protobuf:"bytes,16,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // Types that are assignable to PresenceConstraints: - // *FeatureSpec_Presence - // *FeatureSpec_GroupPresence - PresenceConstraints isFeatureSpec_PresenceConstraints `protobuf_oneof:"presence_constraints"` - // The shape of the feature which governs the number of values that appear in - // each example. - // - // Types that are assignable to ShapeType: - // *FeatureSpec_Shape - // *FeatureSpec_ValueCount - ShapeType isFeatureSpec_ShapeType `protobuf_oneof:"shape_type"` - // Domain for the values of the feature. - // - // Types that are assignable to DomainInfo: - // *FeatureSpec_Domain - // *FeatureSpec_IntDomain - // *FeatureSpec_FloatDomain - // *FeatureSpec_StringDomain - // *FeatureSpec_BoolDomain - // *FeatureSpec_StructDomain - // *FeatureSpec_NaturalLanguageDomain - // *FeatureSpec_ImageDomain - // *FeatureSpec_MidDomain - // *FeatureSpec_UrlDomain - // *FeatureSpec_TimeDomain - // *FeatureSpec_TimeOfDayDomain - DomainInfo isFeatureSpec_DomainInfo `protobuf_oneof:"domain_info"` -} - -func (x *FeatureSpec) Reset() { - *x = FeatureSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureSet_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureSpec) ProtoMessage() {} - -func (x *FeatureSpec) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureSet_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureSpec.ProtoReflect.Descriptor instead. -func (*FeatureSpec) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{3} -} - -func (x *FeatureSpec) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *FeatureSpec) GetValueType() types.ValueType_Enum { - if x != nil { - return x.ValueType - } - return types.ValueType_INVALID -} - -func (x *FeatureSpec) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -func (m *FeatureSpec) GetPresenceConstraints() isFeatureSpec_PresenceConstraints { - if m != nil { - return m.PresenceConstraints - } - return nil -} - -func (x *FeatureSpec) GetPresence() *v0.FeaturePresence { - if x, ok := x.GetPresenceConstraints().(*FeatureSpec_Presence); ok { - return x.Presence - } - return nil -} - -func (x *FeatureSpec) GetGroupPresence() *v0.FeaturePresenceWithinGroup { - if x, ok := x.GetPresenceConstraints().(*FeatureSpec_GroupPresence); ok { - return x.GroupPresence - } - return nil -} - -func (m *FeatureSpec) GetShapeType() isFeatureSpec_ShapeType { - if m != nil { - return m.ShapeType - } - return nil -} - -func (x *FeatureSpec) GetShape() *v0.FixedShape { - if x, ok := x.GetShapeType().(*FeatureSpec_Shape); ok { - return x.Shape - } - return nil -} - -func (x *FeatureSpec) GetValueCount() *v0.ValueCount { - if x, ok := x.GetShapeType().(*FeatureSpec_ValueCount); ok { - return x.ValueCount - } - return nil -} - -func (m *FeatureSpec) GetDomainInfo() isFeatureSpec_DomainInfo { - if m != nil { - return m.DomainInfo - } - return nil -} - -func (x *FeatureSpec) GetDomain() string { - if x, ok := x.GetDomainInfo().(*FeatureSpec_Domain); ok { - return x.Domain - } - return "" -} - -func (x *FeatureSpec) GetIntDomain() *v0.IntDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_IntDomain); ok { - return x.IntDomain - } - return nil -} - -func (x *FeatureSpec) GetFloatDomain() *v0.FloatDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_FloatDomain); ok { - return x.FloatDomain - } - return nil -} - -func (x *FeatureSpec) GetStringDomain() *v0.StringDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_StringDomain); ok { - return x.StringDomain - } - return nil -} - -func (x *FeatureSpec) GetBoolDomain() *v0.BoolDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_BoolDomain); ok { - return x.BoolDomain - } - return nil -} - -func (x *FeatureSpec) GetStructDomain() *v0.StructDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_StructDomain); ok { - return x.StructDomain - } - return nil -} - -func (x *FeatureSpec) GetNaturalLanguageDomain() *v0.NaturalLanguageDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_NaturalLanguageDomain); ok { - return x.NaturalLanguageDomain - } - return nil -} - -func (x *FeatureSpec) GetImageDomain() *v0.ImageDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_ImageDomain); ok { - return x.ImageDomain - } - return nil -} - -func (x *FeatureSpec) GetMidDomain() *v0.MIDDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_MidDomain); ok { - return x.MidDomain - } - return nil -} - -func (x *FeatureSpec) GetUrlDomain() *v0.URLDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_UrlDomain); ok { - return x.UrlDomain - } - return nil -} - -func (x *FeatureSpec) GetTimeDomain() *v0.TimeDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_TimeDomain); ok { - return x.TimeDomain - } - return nil -} - -func (x *FeatureSpec) GetTimeOfDayDomain() *v0.TimeOfDayDomain { - if x, ok := x.GetDomainInfo().(*FeatureSpec_TimeOfDayDomain); ok { - return x.TimeOfDayDomain - } - return nil -} - -type isFeatureSpec_PresenceConstraints interface { - isFeatureSpec_PresenceConstraints() -} - -type FeatureSpec_Presence struct { - // Constraints on the presence of this feature in the examples. - Presence *v0.FeaturePresence `protobuf:"bytes,30,opt,name=presence,proto3,oneof"` -} - -type FeatureSpec_GroupPresence struct { - // Only used in the context of a "group" context, e.g., inside a sequence. - GroupPresence *v0.FeaturePresenceWithinGroup `protobuf:"bytes,31,opt,name=group_presence,json=groupPresence,proto3,oneof"` -} - -func (*FeatureSpec_Presence) isFeatureSpec_PresenceConstraints() {} - -func (*FeatureSpec_GroupPresence) isFeatureSpec_PresenceConstraints() {} - -type isFeatureSpec_ShapeType interface { - isFeatureSpec_ShapeType() -} - -type FeatureSpec_Shape struct { - // The feature has a fixed shape corresponding to a multi-dimensional - // tensor. - Shape *v0.FixedShape `protobuf:"bytes,32,opt,name=shape,proto3,oneof"` -} - -type FeatureSpec_ValueCount struct { - // The feature doesn't have a well defined shape. All we know are limits on - // the minimum and maximum number of values. - ValueCount *v0.ValueCount `protobuf:"bytes,33,opt,name=value_count,json=valueCount,proto3,oneof"` -} - -func (*FeatureSpec_Shape) isFeatureSpec_ShapeType() {} - -func (*FeatureSpec_ValueCount) isFeatureSpec_ShapeType() {} - -type isFeatureSpec_DomainInfo interface { - isFeatureSpec_DomainInfo() -} - -type FeatureSpec_Domain struct { - // Reference to a domain defined at the schema level. - Domain string `protobuf:"bytes,34,opt,name=domain,proto3,oneof"` -} - -type FeatureSpec_IntDomain struct { - // Inline definitions of domains. - IntDomain *v0.IntDomain `protobuf:"bytes,35,opt,name=int_domain,json=intDomain,proto3,oneof"` -} - -type FeatureSpec_FloatDomain struct { - FloatDomain *v0.FloatDomain `protobuf:"bytes,36,opt,name=float_domain,json=floatDomain,proto3,oneof"` -} - -type FeatureSpec_StringDomain struct { - StringDomain *v0.StringDomain `protobuf:"bytes,37,opt,name=string_domain,json=stringDomain,proto3,oneof"` -} - -type FeatureSpec_BoolDomain struct { - BoolDomain *v0.BoolDomain `protobuf:"bytes,38,opt,name=bool_domain,json=boolDomain,proto3,oneof"` -} - -type FeatureSpec_StructDomain struct { - StructDomain *v0.StructDomain `protobuf:"bytes,39,opt,name=struct_domain,json=structDomain,proto3,oneof"` -} - -type FeatureSpec_NaturalLanguageDomain struct { - // Supported semantic domains. - NaturalLanguageDomain *v0.NaturalLanguageDomain `protobuf:"bytes,40,opt,name=natural_language_domain,json=naturalLanguageDomain,proto3,oneof"` -} - -type FeatureSpec_ImageDomain struct { - ImageDomain *v0.ImageDomain `protobuf:"bytes,41,opt,name=image_domain,json=imageDomain,proto3,oneof"` -} - -type FeatureSpec_MidDomain struct { - MidDomain *v0.MIDDomain `protobuf:"bytes,42,opt,name=mid_domain,json=midDomain,proto3,oneof"` -} - -type FeatureSpec_UrlDomain struct { - UrlDomain *v0.URLDomain `protobuf:"bytes,43,opt,name=url_domain,json=urlDomain,proto3,oneof"` -} - -type FeatureSpec_TimeDomain struct { - TimeDomain *v0.TimeDomain `protobuf:"bytes,44,opt,name=time_domain,json=timeDomain,proto3,oneof"` -} - -type FeatureSpec_TimeOfDayDomain struct { - TimeOfDayDomain *v0.TimeOfDayDomain `protobuf:"bytes,45,opt,name=time_of_day_domain,json=timeOfDayDomain,proto3,oneof"` -} - -func (*FeatureSpec_Domain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_IntDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_FloatDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_StringDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_BoolDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_StructDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_NaturalLanguageDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_ImageDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_MidDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_UrlDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_TimeDomain) isFeatureSpec_DomainInfo() {} - -func (*FeatureSpec_TimeOfDayDomain) isFeatureSpec_DomainInfo() {} - -type FeatureSetMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Created timestamp of this specific feature set. - CreatedTimestamp *timestamp.Timestamp `protobuf:"bytes,1,opt,name=created_timestamp,json=createdTimestamp,proto3" json:"created_timestamp,omitempty"` - // Status of the feature set. - // Used to indicate whether the feature set is ready for consumption or ingestion. - // Currently supports 2 states: - // 1) STATUS_PENDING - A feature set is in pending state if Feast has not spun up the jobs - // necessary to push rows for this feature set to stores subscribing to this feature set. - // 2) STATUS_READY - Feature set is ready for consumption or ingestion - Status FeatureSetStatus `protobuf:"varint,2,opt,name=status,proto3,enum=feast.core.FeatureSetStatus" json:"status,omitempty"` -} - -func (x *FeatureSetMeta) Reset() { - *x = FeatureSetMeta{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureSet_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureSetMeta) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureSetMeta) ProtoMessage() {} - -func (x *FeatureSetMeta) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureSet_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureSetMeta.ProtoReflect.Descriptor instead. -func (*FeatureSetMeta) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureSet_proto_rawDescGZIP(), []int{4} -} - -func (x *FeatureSetMeta) GetCreatedTimestamp() *timestamp.Timestamp { - if x != nil { - return x.CreatedTimestamp - } - return nil -} - -func (x *FeatureSetMeta) GetStatus() FeatureSetStatus { - if x != nil { - return x.Status - } - return FeatureSetStatus_STATUS_INVALID -} - -var File_feast_core_FeatureSet_proto protoreflect.FileDescriptor - -var file_feast_core_FeatureSet_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6c, 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, - 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xa2, 0x03, 0x0a, 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x70, 0x65, 0x63, - 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x08, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, - 0x32, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6d, 0x61, 0x78, - 0x41, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x3e, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, - 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x5c, 0x0a, 0x0a, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x0a, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0xa0, 0x0b, 0x0a, 0x0b, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x0a, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x09, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, - 0x63, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x45, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, - 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, - 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, - 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, - 0x48, 0x00, 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0e, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x1f, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x57, 0x69, 0x74, - 0x68, 0x69, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x73, 0x68, 0x61, - 0x70, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, 0x70, 0x65, 0x48, 0x01, 0x52, 0x05, - 0x73, 0x68, 0x61, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x48, 0x01, - 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x06, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x5f, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, - 0x09, 0x69, 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x48, 0x0a, 0x0c, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0b, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x48, 0x02, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x12, 0x45, 0x0a, 0x0b, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x42, 0x6f, 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0a, 0x62, 0x6f, - 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x67, 0x0a, 0x17, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, - 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x4e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x15, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, - 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x48, - 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x29, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6d, - 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0b, 0x69, 0x6d, 0x61, - 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x6d, 0x69, 0x64, 0x5f, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4d, 0x49, 0x44, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, - 0x02, 0x52, 0x09, 0x6d, 0x69, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, - 0x75, 0x72, 0x6c, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x55, 0x52, 0x4c, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x09, 0x75, 0x72, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x12, 0x45, 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, - 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0a, 0x74, 0x69, 0x6d, - 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x56, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, - 0x6f, 0x66, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x2d, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0f, - 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, - 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x16, 0x0a, 0x14, 0x70, 0x72, - 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, - 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x4a, - 0x04, 0x08, 0x03, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x11, 0x10, 0x1e, 0x22, 0x8f, 0x01, 0x0a, 0x0e, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x47, - 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x65, 0x0a, - 0x10, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, - 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, - 0x54, 0x55, 0x53, 0x5f, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, - 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, 0x41, - 0x44, 0x59, 0x10, 0x02, 0x2a, 0x4b, 0x0a, 0x1b, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, - 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x45, 0x44, 0x10, - 0x01, 0x42, 0x58, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, - 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_FeatureSet_proto_rawDescOnce sync.Once - file_feast_core_FeatureSet_proto_rawDescData = file_feast_core_FeatureSet_proto_rawDesc -) - -func file_feast_core_FeatureSet_proto_rawDescGZIP() []byte { - file_feast_core_FeatureSet_proto_rawDescOnce.Do(func() { - file_feast_core_FeatureSet_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_FeatureSet_proto_rawDescData) - }) - return file_feast_core_FeatureSet_proto_rawDescData -} - -var file_feast_core_FeatureSet_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_feast_core_FeatureSet_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_feast_core_FeatureSet_proto_goTypes = []interface{}{ - (FeatureSetStatus)(0), // 0: feast.core.FeatureSetStatus - (FeatureSetJobDeliveryStatus)(0), // 1: feast.core.FeatureSetJobDeliveryStatus - (*FeatureSet)(nil), // 2: feast.core.FeatureSet - (*FeatureSetSpec)(nil), // 3: feast.core.FeatureSetSpec - (*EntitySpec)(nil), // 4: feast.core.EntitySpec - (*FeatureSpec)(nil), // 5: feast.core.FeatureSpec - (*FeatureSetMeta)(nil), // 6: feast.core.FeatureSetMeta - nil, // 7: feast.core.FeatureSetSpec.LabelsEntry - nil, // 8: feast.core.FeatureSpec.LabelsEntry - (*duration.Duration)(nil), // 9: google.protobuf.Duration - (*Source)(nil), // 10: feast.core.Source - (types.ValueType_Enum)(0), // 11: feast.types.ValueType.Enum - (*v0.FeaturePresence)(nil), // 12: tensorflow.metadata.v0.FeaturePresence - (*v0.FeaturePresenceWithinGroup)(nil), // 13: tensorflow.metadata.v0.FeaturePresenceWithinGroup - (*v0.FixedShape)(nil), // 14: tensorflow.metadata.v0.FixedShape - (*v0.ValueCount)(nil), // 15: tensorflow.metadata.v0.ValueCount - (*v0.IntDomain)(nil), // 16: tensorflow.metadata.v0.IntDomain - (*v0.FloatDomain)(nil), // 17: tensorflow.metadata.v0.FloatDomain - (*v0.StringDomain)(nil), // 18: tensorflow.metadata.v0.StringDomain - (*v0.BoolDomain)(nil), // 19: tensorflow.metadata.v0.BoolDomain - (*v0.StructDomain)(nil), // 20: tensorflow.metadata.v0.StructDomain - (*v0.NaturalLanguageDomain)(nil), // 21: tensorflow.metadata.v0.NaturalLanguageDomain - (*v0.ImageDomain)(nil), // 22: tensorflow.metadata.v0.ImageDomain - (*v0.MIDDomain)(nil), // 23: tensorflow.metadata.v0.MIDDomain - (*v0.URLDomain)(nil), // 24: tensorflow.metadata.v0.URLDomain - (*v0.TimeDomain)(nil), // 25: tensorflow.metadata.v0.TimeDomain - (*v0.TimeOfDayDomain)(nil), // 26: tensorflow.metadata.v0.TimeOfDayDomain - (*timestamp.Timestamp)(nil), // 27: google.protobuf.Timestamp -} -var file_feast_core_FeatureSet_proto_depIdxs = []int32{ - 3, // 0: feast.core.FeatureSet.spec:type_name -> feast.core.FeatureSetSpec - 6, // 1: feast.core.FeatureSet.meta:type_name -> feast.core.FeatureSetMeta - 4, // 2: feast.core.FeatureSetSpec.entities:type_name -> feast.core.EntitySpec - 5, // 3: feast.core.FeatureSetSpec.features:type_name -> feast.core.FeatureSpec - 9, // 4: feast.core.FeatureSetSpec.max_age:type_name -> google.protobuf.Duration - 10, // 5: feast.core.FeatureSetSpec.source:type_name -> feast.core.Source - 7, // 6: feast.core.FeatureSetSpec.labels:type_name -> feast.core.FeatureSetSpec.LabelsEntry - 11, // 7: feast.core.EntitySpec.value_type:type_name -> feast.types.ValueType.Enum - 11, // 8: feast.core.FeatureSpec.value_type:type_name -> feast.types.ValueType.Enum - 8, // 9: feast.core.FeatureSpec.labels:type_name -> feast.core.FeatureSpec.LabelsEntry - 12, // 10: feast.core.FeatureSpec.presence:type_name -> tensorflow.metadata.v0.FeaturePresence - 13, // 11: feast.core.FeatureSpec.group_presence:type_name -> tensorflow.metadata.v0.FeaturePresenceWithinGroup - 14, // 12: feast.core.FeatureSpec.shape:type_name -> tensorflow.metadata.v0.FixedShape - 15, // 13: feast.core.FeatureSpec.value_count:type_name -> tensorflow.metadata.v0.ValueCount - 16, // 14: feast.core.FeatureSpec.int_domain:type_name -> tensorflow.metadata.v0.IntDomain - 17, // 15: feast.core.FeatureSpec.float_domain:type_name -> tensorflow.metadata.v0.FloatDomain - 18, // 16: feast.core.FeatureSpec.string_domain:type_name -> tensorflow.metadata.v0.StringDomain - 19, // 17: feast.core.FeatureSpec.bool_domain:type_name -> tensorflow.metadata.v0.BoolDomain - 20, // 18: feast.core.FeatureSpec.struct_domain:type_name -> tensorflow.metadata.v0.StructDomain - 21, // 19: feast.core.FeatureSpec.natural_language_domain:type_name -> tensorflow.metadata.v0.NaturalLanguageDomain - 22, // 20: feast.core.FeatureSpec.image_domain:type_name -> tensorflow.metadata.v0.ImageDomain - 23, // 21: feast.core.FeatureSpec.mid_domain:type_name -> tensorflow.metadata.v0.MIDDomain - 24, // 22: feast.core.FeatureSpec.url_domain:type_name -> tensorflow.metadata.v0.URLDomain - 25, // 23: feast.core.FeatureSpec.time_domain:type_name -> tensorflow.metadata.v0.TimeDomain - 26, // 24: feast.core.FeatureSpec.time_of_day_domain:type_name -> tensorflow.metadata.v0.TimeOfDayDomain - 27, // 25: feast.core.FeatureSetMeta.created_timestamp:type_name -> google.protobuf.Timestamp - 0, // 26: feast.core.FeatureSetMeta.status:type_name -> feast.core.FeatureSetStatus - 27, // [27:27] is the sub-list for method output_type - 27, // [27:27] is the sub-list for method input_type - 27, // [27:27] is the sub-list for extension type_name - 27, // [27:27] is the sub-list for extension extendee - 0, // [0:27] is the sub-list for field type_name -} - -func init() { file_feast_core_FeatureSet_proto_init() } -func file_feast_core_FeatureSet_proto_init() { - if File_feast_core_FeatureSet_proto != nil { - return - } - file_feast_core_Source_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_core_FeatureSet_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSet); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_FeatureSet_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSetSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_FeatureSet_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EntitySpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_FeatureSet_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_FeatureSet_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSetMeta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_core_FeatureSet_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*FeatureSpec_Presence)(nil), - (*FeatureSpec_GroupPresence)(nil), - (*FeatureSpec_Shape)(nil), - (*FeatureSpec_ValueCount)(nil), - (*FeatureSpec_Domain)(nil), - (*FeatureSpec_IntDomain)(nil), - (*FeatureSpec_FloatDomain)(nil), - (*FeatureSpec_StringDomain)(nil), - (*FeatureSpec_BoolDomain)(nil), - (*FeatureSpec_StructDomain)(nil), - (*FeatureSpec_NaturalLanguageDomain)(nil), - (*FeatureSpec_ImageDomain)(nil), - (*FeatureSpec_MidDomain)(nil), - (*FeatureSpec_UrlDomain)(nil), - (*FeatureSpec_TimeDomain)(nil), - (*FeatureSpec_TimeOfDayDomain)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_FeatureSet_proto_rawDesc, - NumEnums: 2, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_FeatureSet_proto_goTypes, - DependencyIndexes: file_feast_core_FeatureSet_proto_depIdxs, - EnumInfos: file_feast_core_FeatureSet_proto_enumTypes, - MessageInfos: file_feast_core_FeatureSet_proto_msgTypes, - }.Build() - File_feast_core_FeatureSet_proto = out.File - file_feast_core_FeatureSet_proto_rawDesc = nil - file_feast_core_FeatureSet_proto_goTypes = nil - file_feast_core_FeatureSet_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/FeatureSetReference.pb.go b/sdk/go/protos/feast/core/FeatureSetReference.pb.go deleted file mode 100644 index ca640aa0fb3..00000000000 --- a/sdk/go/protos/feast/core/FeatureSetReference.pb.go +++ /dev/null @@ -1,183 +0,0 @@ -// -// Copyright 2020 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.10.0 -// source: feast/core/FeatureSetReference.proto - -package core - -import ( - proto "github.com/golang/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 - -// Defines a composite key that refers to a unique FeatureSet -type FeatureSetReference struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the project - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - // Name of the FeatureSet - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *FeatureSetReference) Reset() { - *x = FeatureSetReference{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureSetReference_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureSetReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureSetReference) ProtoMessage() {} - -func (x *FeatureSetReference) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureSetReference_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureSetReference.ProtoReflect.Descriptor instead. -func (*FeatureSetReference) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureSetReference_proto_rawDescGZIP(), []int{0} -} - -func (x *FeatureSetReference) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *FeatureSetReference) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -var File_feast_core_FeatureSetReference_proto protoreflect.FileDescriptor - -var file_feast_core_FeatureSetReference_proto_rawDesc = []byte{ - 0x0a, 0x24, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x22, 0x49, 0x0a, 0x13, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x42, 0x61, 0x0a, - 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x42, 0x18, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, - 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_FeatureSetReference_proto_rawDescOnce sync.Once - file_feast_core_FeatureSetReference_proto_rawDescData = file_feast_core_FeatureSetReference_proto_rawDesc -) - -func file_feast_core_FeatureSetReference_proto_rawDescGZIP() []byte { - file_feast_core_FeatureSetReference_proto_rawDescOnce.Do(func() { - file_feast_core_FeatureSetReference_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_FeatureSetReference_proto_rawDescData) - }) - return file_feast_core_FeatureSetReference_proto_rawDescData -} - -var file_feast_core_FeatureSetReference_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_feast_core_FeatureSetReference_proto_goTypes = []interface{}{ - (*FeatureSetReference)(nil), // 0: feast.core.FeatureSetReference -} -var file_feast_core_FeatureSetReference_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_feast_core_FeatureSetReference_proto_init() } -func file_feast_core_FeatureSetReference_proto_init() { - if File_feast_core_FeatureSetReference_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_core_FeatureSetReference_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSetReference); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_FeatureSetReference_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_FeatureSetReference_proto_goTypes, - DependencyIndexes: file_feast_core_FeatureSetReference_proto_depIdxs, - MessageInfos: file_feast_core_FeatureSetReference_proto_msgTypes, - }.Build() - File_feast_core_FeatureSetReference_proto = out.File - file_feast_core_FeatureSetReference_proto_rawDesc = nil - file_feast_core_FeatureSetReference_proto_goTypes = nil - file_feast_core_FeatureSetReference_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/FeatureTable.pb.go b/sdk/go/protos/feast/core/FeatureTable.pb.go deleted file mode 100644 index 144d46d8e2b..00000000000 --- a/sdk/go/protos/feast/core/FeatureTable.pb.go +++ /dev/null @@ -1,467 +0,0 @@ -// -// Copyright 2020 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/core/FeatureTable.proto - -package core - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type FeatureTable struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // User-specified specifications of this feature table. - Spec *FeatureTableSpec `protobuf:"bytes,1,opt,name=spec,proto3" json:"spec,omitempty"` - // System-populated metadata for this feature table. - Meta *FeatureTableMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` -} - -func (x *FeatureTable) Reset() { - *x = FeatureTable{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureTable_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureTable) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureTable) ProtoMessage() {} - -func (x *FeatureTable) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureTable_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureTable.ProtoReflect.Descriptor instead. -func (*FeatureTable) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureTable_proto_rawDescGZIP(), []int{0} -} - -func (x *FeatureTable) GetSpec() *FeatureTableSpec { - if x != nil { - return x.Spec - } - return nil -} - -func (x *FeatureTable) GetMeta() *FeatureTableMeta { - if x != nil { - return x.Meta - } - return nil -} - -type FeatureTableSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the feature table. Must be unique. Not updated. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Name of Feast project that this feature table belongs to. - Project string `protobuf:"bytes,9,opt,name=project,proto3" json:"project,omitempty"` - // List names of entities to associate with the Features defined in this - // Feature Table. Not updatable. - Entities []string `protobuf:"bytes,3,rep,name=entities,proto3" json:"entities,omitempty"` - // List of features specifications for each feature defined with this feature table. - Features []*FeatureSpecV2 `protobuf:"bytes,4,rep,name=features,proto3" json:"features,omitempty"` - // User defined metadata - Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // Features in this feature table can only be retrieved from online serving - // younger than max age. Age is measured as the duration of time between - // the feature's event timestamp and when the feature is retrieved - // Feature values outside max age will be returned as unset values and indicated to end user - MaxAge *durationpb.Duration `protobuf:"bytes,6,opt,name=max_age,json=maxAge,proto3" json:"max_age,omitempty"` - // Batch/Offline DataSource to source batch/offline feature data. - // Only batch DataSource can be specified - // (ie source type should start with 'BATCH_') - BatchSource *DataSource `protobuf:"bytes,7,opt,name=batch_source,json=batchSource,proto3" json:"batch_source,omitempty"` - // Stream/Online DataSource to source stream/online feature data. - // Only stream DataSource can be specified - // (ie source type should start with 'STREAM_') - StreamSource *DataSource `protobuf:"bytes,8,opt,name=stream_source,json=streamSource,proto3" json:"stream_source,omitempty"` -} - -func (x *FeatureTableSpec) Reset() { - *x = FeatureTableSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureTable_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureTableSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureTableSpec) ProtoMessage() {} - -func (x *FeatureTableSpec) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureTable_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureTableSpec.ProtoReflect.Descriptor instead. -func (*FeatureTableSpec) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureTable_proto_rawDescGZIP(), []int{1} -} - -func (x *FeatureTableSpec) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *FeatureTableSpec) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *FeatureTableSpec) GetEntities() []string { - if x != nil { - return x.Entities - } - return nil -} - -func (x *FeatureTableSpec) GetFeatures() []*FeatureSpecV2 { - if x != nil { - return x.Features - } - return nil -} - -func (x *FeatureTableSpec) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -func (x *FeatureTableSpec) GetMaxAge() *durationpb.Duration { - if x != nil { - return x.MaxAge - } - return nil -} - -func (x *FeatureTableSpec) GetBatchSource() *DataSource { - if x != nil { - return x.BatchSource - } - return nil -} - -func (x *FeatureTableSpec) GetStreamSource() *DataSource { - if x != nil { - return x.StreamSource - } - return nil -} - -type FeatureTableMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Time where this Feature Table is created - CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=created_timestamp,json=createdTimestamp,proto3" json:"created_timestamp,omitempty"` - // Time where this Feature Table is last updated - LastUpdatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=last_updated_timestamp,json=lastUpdatedTimestamp,proto3" json:"last_updated_timestamp,omitempty"` - // Auto incrementing revision no. of this Feature Table - Revision int64 `protobuf:"varint,3,opt,name=revision,proto3" json:"revision,omitempty"` - // Hash entities, features, batch_source and stream_source to inform JobService if - // jobs should be restarted should hash change - Hash string `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` -} - -func (x *FeatureTableMeta) Reset() { - *x = FeatureTableMeta{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_FeatureTable_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureTableMeta) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureTableMeta) ProtoMessage() {} - -func (x *FeatureTableMeta) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_FeatureTable_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureTableMeta.ProtoReflect.Descriptor instead. -func (*FeatureTableMeta) Descriptor() ([]byte, []int) { - return file_feast_core_FeatureTable_proto_rawDescGZIP(), []int{2} -} - -func (x *FeatureTableMeta) GetCreatedTimestamp() *timestamppb.Timestamp { - if x != nil { - return x.CreatedTimestamp - } - return nil -} - -func (x *FeatureTableMeta) GetLastUpdatedTimestamp() *timestamppb.Timestamp { - if x != nil { - return x.LastUpdatedTimestamp - } - return nil -} - -func (x *FeatureTableMeta) GetRevision() int64 { - if x != nil { - return x.Revision - } - return 0 -} - -func (x *FeatureTableMeta) GetHash() string { - if x != nil { - return x.Hash - } - return "" -} - -var File_feast_core_FeatureTable_proto protoreflect.FileDescriptor - -var file_feast_core_FeatureTable_proto_rawDesc = []byte{ - 0x0a, 0x1d, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x72, 0x0a, 0x0c, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, - 0x62, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, - 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x30, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xbc, 0x03, 0x0a, 0x10, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x70, 0x65, - 0x63, 0x56, 0x32, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x40, 0x0a, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, - 0x32, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6d, 0x61, 0x78, - 0x41, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3b, - 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0c, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdd, 0x01, 0x0a, 0x10, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x11, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x12, 0x50, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x42, 0x5a, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x11, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, - 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, - 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_FeatureTable_proto_rawDescOnce sync.Once - file_feast_core_FeatureTable_proto_rawDescData = file_feast_core_FeatureTable_proto_rawDesc -) - -func file_feast_core_FeatureTable_proto_rawDescGZIP() []byte { - file_feast_core_FeatureTable_proto_rawDescOnce.Do(func() { - file_feast_core_FeatureTable_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_FeatureTable_proto_rawDescData) - }) - return file_feast_core_FeatureTable_proto_rawDescData -} - -var file_feast_core_FeatureTable_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_feast_core_FeatureTable_proto_goTypes = []interface{}{ - (*FeatureTable)(nil), // 0: feast.core.FeatureTable - (*FeatureTableSpec)(nil), // 1: feast.core.FeatureTableSpec - (*FeatureTableMeta)(nil), // 2: feast.core.FeatureTableMeta - nil, // 3: feast.core.FeatureTableSpec.LabelsEntry - (*FeatureSpecV2)(nil), // 4: feast.core.FeatureSpecV2 - (*durationpb.Duration)(nil), // 5: google.protobuf.Duration - (*DataSource)(nil), // 6: feast.core.DataSource - (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp -} -var file_feast_core_FeatureTable_proto_depIdxs = []int32{ - 1, // 0: feast.core.FeatureTable.spec:type_name -> feast.core.FeatureTableSpec - 2, // 1: feast.core.FeatureTable.meta:type_name -> feast.core.FeatureTableMeta - 4, // 2: feast.core.FeatureTableSpec.features:type_name -> feast.core.FeatureSpecV2 - 3, // 3: feast.core.FeatureTableSpec.labels:type_name -> feast.core.FeatureTableSpec.LabelsEntry - 5, // 4: feast.core.FeatureTableSpec.max_age:type_name -> google.protobuf.Duration - 6, // 5: feast.core.FeatureTableSpec.batch_source:type_name -> feast.core.DataSource - 6, // 6: feast.core.FeatureTableSpec.stream_source:type_name -> feast.core.DataSource - 7, // 7: feast.core.FeatureTableMeta.created_timestamp:type_name -> google.protobuf.Timestamp - 7, // 8: feast.core.FeatureTableMeta.last_updated_timestamp:type_name -> google.protobuf.Timestamp - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name -} - -func init() { file_feast_core_FeatureTable_proto_init() } -func file_feast_core_FeatureTable_proto_init() { - if File_feast_core_FeatureTable_proto != nil { - return - } - file_feast_core_DataSource_proto_init() - file_feast_core_Feature_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_core_FeatureTable_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureTable); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_FeatureTable_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureTableSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_FeatureTable_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureTableMeta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_FeatureTable_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_FeatureTable_proto_goTypes, - DependencyIndexes: file_feast_core_FeatureTable_proto_depIdxs, - MessageInfos: file_feast_core_FeatureTable_proto_msgTypes, - }.Build() - File_feast_core_FeatureTable_proto = out.File - file_feast_core_FeatureTable_proto_rawDesc = nil - file_feast_core_FeatureTable_proto_goTypes = nil - file_feast_core_FeatureTable_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/IngestionJob.pb.go b/sdk/go/protos/feast/core/IngestionJob.pb.go deleted file mode 100644 index a716bdf0893..00000000000 --- a/sdk/go/protos/feast/core/IngestionJob.pb.go +++ /dev/null @@ -1,506 +0,0 @@ -// -// Copyright 2020 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.10.0 -// source: feast/core/IngestionJob.proto - -package core - -import ( - proto "github.com/golang/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 - -// Status of a Feast Ingestion Job -type IngestionJobStatus int32 - -const ( - // Job status is not known. - IngestionJobStatus_UNKNOWN IngestionJobStatus = 0 - // Import job is submitted to runner and currently pending for executing - IngestionJobStatus_PENDING IngestionJobStatus = 1 - // Import job is currently running in the runner - IngestionJobStatus_RUNNING IngestionJobStatus = 2 - // Runner's reported the import job has completed (applicable to batch job) - IngestionJobStatus_COMPLETED IngestionJobStatus = 3 - // When user sent abort command, but it's still running - IngestionJobStatus_ABORTING IngestionJobStatus = 4 - // User initiated abort job - IngestionJobStatus_ABORTED IngestionJobStatus = 5 - // Runner's reported that the import job failed to run or there is a failure during job - IngestionJobStatus_ERROR IngestionJobStatus = 6 - // job has been suspended and waiting for cleanup - IngestionJobStatus_SUSPENDING IngestionJobStatus = 7 - // job has been suspended - IngestionJobStatus_SUSPENDED IngestionJobStatus = 8 -) - -// Enum value maps for IngestionJobStatus. -var ( - IngestionJobStatus_name = map[int32]string{ - 0: "UNKNOWN", - 1: "PENDING", - 2: "RUNNING", - 3: "COMPLETED", - 4: "ABORTING", - 5: "ABORTED", - 6: "ERROR", - 7: "SUSPENDING", - 8: "SUSPENDED", - } - IngestionJobStatus_value = map[string]int32{ - "UNKNOWN": 0, - "PENDING": 1, - "RUNNING": 2, - "COMPLETED": 3, - "ABORTING": 4, - "ABORTED": 5, - "ERROR": 6, - "SUSPENDING": 7, - "SUSPENDED": 8, - } -) - -func (x IngestionJobStatus) Enum() *IngestionJobStatus { - p := new(IngestionJobStatus) - *p = x - return p -} - -func (x IngestionJobStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (IngestionJobStatus) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_IngestionJob_proto_enumTypes[0].Descriptor() -} - -func (IngestionJobStatus) Type() protoreflect.EnumType { - return &file_feast_core_IngestionJob_proto_enumTypes[0] -} - -func (x IngestionJobStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use IngestionJobStatus.Descriptor instead. -func (IngestionJobStatus) EnumDescriptor() ([]byte, []int) { - return file_feast_core_IngestionJob_proto_rawDescGZIP(), []int{0} -} - -// Represents Feast Injestion Job -type IngestionJob struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Job ID assigned by Feast - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - // External job ID specific to the runner. - // For DirectRunner jobs, this is identical to id. For DataflowRunner jobs, this refers to the Dataflow job ID. - ExternalId string `protobuf:"bytes,2,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty"` - Status IngestionJobStatus `protobuf:"varint,3,opt,name=status,proto3,enum=feast.core.IngestionJobStatus" json:"status,omitempty"` - // Source this job is reading from. - Source *Source `protobuf:"bytes,5,opt,name=source,proto3" json:"source,omitempty"` - // Store this job is writing to. - Stores []*Store `protobuf:"bytes,6,rep,name=stores,proto3" json:"stores,omitempty"` - // List of Feature Set References - FeatureSetReferences []*FeatureSetReference `protobuf:"bytes,7,rep,name=feature_set_references,json=featureSetReferences,proto3" json:"feature_set_references,omitempty"` -} - -func (x *IngestionJob) Reset() { - *x = IngestionJob{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_IngestionJob_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IngestionJob) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IngestionJob) ProtoMessage() {} - -func (x *IngestionJob) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_IngestionJob_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IngestionJob.ProtoReflect.Descriptor instead. -func (*IngestionJob) Descriptor() ([]byte, []int) { - return file_feast_core_IngestionJob_proto_rawDescGZIP(), []int{0} -} - -func (x *IngestionJob) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *IngestionJob) GetExternalId() string { - if x != nil { - return x.ExternalId - } - return "" -} - -func (x *IngestionJob) GetStatus() IngestionJobStatus { - if x != nil { - return x.Status - } - return IngestionJobStatus_UNKNOWN -} - -func (x *IngestionJob) GetSource() *Source { - if x != nil { - return x.Source - } - return nil -} - -func (x *IngestionJob) GetStores() []*Store { - if x != nil { - return x.Stores - } - return nil -} - -func (x *IngestionJob) GetFeatureSetReferences() []*FeatureSetReference { - if x != nil { - return x.FeatureSetReferences - } - return nil -} - -// Config for bi-directional communication channel between Core Service and Ingestion Job -type SpecsStreamingUpdateConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // out-channel for publishing new FeatureSetSpecs (by Core). - // IngestionJob use it as source of existing FeatureSetSpecs and new real-time updates - Source *KafkaSourceConfig `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"` - // ack-channel for sending acknowledgments when new FeatureSetSpecs is installed in Job - Ack *KafkaSourceConfig `protobuf:"bytes,2,opt,name=ack,proto3" json:"ack,omitempty"` -} - -func (x *SpecsStreamingUpdateConfig) Reset() { - *x = SpecsStreamingUpdateConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_IngestionJob_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SpecsStreamingUpdateConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SpecsStreamingUpdateConfig) ProtoMessage() {} - -func (x *SpecsStreamingUpdateConfig) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_IngestionJob_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SpecsStreamingUpdateConfig.ProtoReflect.Descriptor instead. -func (*SpecsStreamingUpdateConfig) Descriptor() ([]byte, []int) { - return file_feast_core_IngestionJob_proto_rawDescGZIP(), []int{1} -} - -func (x *SpecsStreamingUpdateConfig) GetSource() *KafkaSourceConfig { - if x != nil { - return x.Source - } - return nil -} - -func (x *SpecsStreamingUpdateConfig) GetAck() *KafkaSourceConfig { - if x != nil { - return x.Ack - } - return nil -} - -type FeatureSetSpecAck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - FeatureSetReference string `protobuf:"bytes,1,opt,name=feature_set_reference,json=featureSetReference,proto3" json:"feature_set_reference,omitempty"` - FeatureSetVersion int32 `protobuf:"varint,2,opt,name=feature_set_version,json=featureSetVersion,proto3" json:"feature_set_version,omitempty"` - JobName string `protobuf:"bytes,3,opt,name=job_name,json=jobName,proto3" json:"job_name,omitempty"` -} - -func (x *FeatureSetSpecAck) Reset() { - *x = FeatureSetSpecAck{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_IngestionJob_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureSetSpecAck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureSetSpecAck) ProtoMessage() {} - -func (x *FeatureSetSpecAck) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_IngestionJob_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureSetSpecAck.ProtoReflect.Descriptor instead. -func (*FeatureSetSpecAck) Descriptor() ([]byte, []int) { - return file_feast_core_IngestionJob_proto_rawDescGZIP(), []int{2} -} - -func (x *FeatureSetSpecAck) GetFeatureSetReference() string { - if x != nil { - return x.FeatureSetReference - } - return "" -} - -func (x *FeatureSetSpecAck) GetFeatureSetVersion() int32 { - if x != nil { - return x.FeatureSetVersion - } - return 0 -} - -func (x *FeatureSetSpecAck) GetJobName() string { - if x != nil { - return x.JobName - } - return "" -} - -var File_feast_core_IngestionJob_proto protoreflect.FileDescriptor - -var file_feast_core_IngestionJob_proto_rawDesc = []byte{ - 0x0a, 0x1d, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x49, 0x6e, 0x67, - 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x24, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x16, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0xab, 0x02, 0x0a, 0x0c, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, - 0x4a, 0x6f, 0x62, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x06, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x06, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x73, 0x12, 0x55, 0x0a, 0x16, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, - 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x52, 0x14, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, - 0x22, 0x84, 0x01, 0x0a, 0x1a, 0x53, 0x70, 0x65, 0x63, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x35, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x66, - 0x6b, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x03, 0x61, 0x63, 0x6b, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x03, 0x61, 0x63, 0x6b, 0x22, 0x92, 0x01, 0x0a, 0x11, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x53, 0x70, 0x65, 0x63, 0x41, 0x63, 0x6b, 0x12, 0x32, 0x0a, - 0x15, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x74, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6a, 0x6f, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0x8f, 0x01, 0x0a, - 0x12, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, 0x0a, - 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, - 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x42, 0x4f, - 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x42, 0x4f, 0x52, 0x54, - 0x45, 0x44, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x06, 0x12, - 0x0e, 0x0a, 0x0a, 0x53, 0x55, 0x53, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x12, - 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x53, 0x50, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x08, 0x42, 0x5a, - 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x42, 0x11, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_feast_core_IngestionJob_proto_rawDescOnce sync.Once - file_feast_core_IngestionJob_proto_rawDescData = file_feast_core_IngestionJob_proto_rawDesc -) - -func file_feast_core_IngestionJob_proto_rawDescGZIP() []byte { - file_feast_core_IngestionJob_proto_rawDescOnce.Do(func() { - file_feast_core_IngestionJob_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_IngestionJob_proto_rawDescData) - }) - return file_feast_core_IngestionJob_proto_rawDescData -} - -var file_feast_core_IngestionJob_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_feast_core_IngestionJob_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_feast_core_IngestionJob_proto_goTypes = []interface{}{ - (IngestionJobStatus)(0), // 0: feast.core.IngestionJobStatus - (*IngestionJob)(nil), // 1: feast.core.IngestionJob - (*SpecsStreamingUpdateConfig)(nil), // 2: feast.core.SpecsStreamingUpdateConfig - (*FeatureSetSpecAck)(nil), // 3: feast.core.FeatureSetSpecAck - (*Source)(nil), // 4: feast.core.Source - (*Store)(nil), // 5: feast.core.Store - (*FeatureSetReference)(nil), // 6: feast.core.FeatureSetReference - (*KafkaSourceConfig)(nil), // 7: feast.core.KafkaSourceConfig -} -var file_feast_core_IngestionJob_proto_depIdxs = []int32{ - 0, // 0: feast.core.IngestionJob.status:type_name -> feast.core.IngestionJobStatus - 4, // 1: feast.core.IngestionJob.source:type_name -> feast.core.Source - 5, // 2: feast.core.IngestionJob.stores:type_name -> feast.core.Store - 6, // 3: feast.core.IngestionJob.feature_set_references:type_name -> feast.core.FeatureSetReference - 7, // 4: feast.core.SpecsStreamingUpdateConfig.source:type_name -> feast.core.KafkaSourceConfig - 7, // 5: feast.core.SpecsStreamingUpdateConfig.ack:type_name -> feast.core.KafkaSourceConfig - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name -} - -func init() { file_feast_core_IngestionJob_proto_init() } -func file_feast_core_IngestionJob_proto_init() { - if File_feast_core_IngestionJob_proto != nil { - return - } - file_feast_core_FeatureSetReference_proto_init() - file_feast_core_Store_proto_init() - file_feast_core_Source_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_core_IngestionJob_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IngestionJob); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_IngestionJob_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SpecsStreamingUpdateConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_IngestionJob_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSetSpecAck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_IngestionJob_proto_rawDesc, - NumEnums: 1, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_IngestionJob_proto_goTypes, - DependencyIndexes: file_feast_core_IngestionJob_proto_depIdxs, - EnumInfos: file_feast_core_IngestionJob_proto_enumTypes, - MessageInfos: file_feast_core_IngestionJob_proto_msgTypes, - }.Build() - File_feast_core_IngestionJob_proto = out.File - file_feast_core_IngestionJob_proto_rawDesc = nil - file_feast_core_IngestionJob_proto_goTypes = nil - file_feast_core_IngestionJob_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/JobService.pb.go b/sdk/go/protos/feast/core/JobService.pb.go deleted file mode 100644 index 221c530bb37..00000000000 --- a/sdk/go/protos/feast/core/JobService.pb.go +++ /dev/null @@ -1,1789 +0,0 @@ -// -// Copyright 2018 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.12.4 -// source: feast/core/JobService.proto - -package core - -import ( - context "context" - proto "github.com/golang/protobuf/proto" - timestamp "github.com/golang/protobuf/ptypes/timestamp" - 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" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 JobType int32 - -const ( - JobType_INVALID_JOB JobType = 0 - JobType_BATCH_INGESTION_JOB JobType = 1 - JobType_STREAM_INGESTION_JOB JobType = 2 - JobType_RETRIEVAL_JOB JobType = 4 -) - -// Enum value maps for JobType. -var ( - JobType_name = map[int32]string{ - 0: "INVALID_JOB", - 1: "BATCH_INGESTION_JOB", - 2: "STREAM_INGESTION_JOB", - 4: "RETRIEVAL_JOB", - } - JobType_value = map[string]int32{ - "INVALID_JOB": 0, - "BATCH_INGESTION_JOB": 1, - "STREAM_INGESTION_JOB": 2, - "RETRIEVAL_JOB": 4, - } -) - -func (x JobType) Enum() *JobType { - p := new(JobType) - *p = x - return p -} - -func (x JobType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (JobType) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_JobService_proto_enumTypes[0].Descriptor() -} - -func (JobType) Type() protoreflect.EnumType { - return &file_feast_core_JobService_proto_enumTypes[0] -} - -func (x JobType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use JobType.Descriptor instead. -func (JobType) EnumDescriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{0} -} - -type JobStatus int32 - -const ( - JobStatus_JOB_STATUS_INVALID JobStatus = 0 - // The Job has be registered and waiting to get scheduled to run - JobStatus_JOB_STATUS_PENDING JobStatus = 1 - // The Job is currently processing its task - JobStatus_JOB_STATUS_RUNNING JobStatus = 2 - // The Job has successfully completed its task - JobStatus_JOB_STATUS_DONE JobStatus = 3 - // The Job has encountered an error while processing its task - JobStatus_JOB_STATUS_ERROR JobStatus = 4 -) - -// Enum value maps for JobStatus. -var ( - JobStatus_name = map[int32]string{ - 0: "JOB_STATUS_INVALID", - 1: "JOB_STATUS_PENDING", - 2: "JOB_STATUS_RUNNING", - 3: "JOB_STATUS_DONE", - 4: "JOB_STATUS_ERROR", - } - JobStatus_value = map[string]int32{ - "JOB_STATUS_INVALID": 0, - "JOB_STATUS_PENDING": 1, - "JOB_STATUS_RUNNING": 2, - "JOB_STATUS_DONE": 3, - "JOB_STATUS_ERROR": 4, - } -) - -func (x JobStatus) Enum() *JobStatus { - p := new(JobStatus) - *p = x - return p -} - -func (x JobStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (JobStatus) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_JobService_proto_enumTypes[1].Descriptor() -} - -func (JobStatus) Type() protoreflect.EnumType { - return &file_feast_core_JobService_proto_enumTypes[1] -} - -func (x JobStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use JobStatus.Descriptor instead. -func (JobStatus) EnumDescriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{1} -} - -type Job struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Identifier of the Job - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - // Type of the Job - Type JobType `protobuf:"varint,2,opt,name=type,proto3,enum=feast.core.JobType" json:"type,omitempty"` - // Current job status - Status JobStatus `protobuf:"varint,3,opt,name=status,proto3,enum=feast.core.JobStatus" json:"status,omitempty"` - // Deterministic hash of the Job - Hash string `protobuf:"bytes,8,opt,name=hash,proto3" json:"hash,omitempty"` - // JobType specific metadata on the job - // - // Types that are assignable to Meta: - // *Job_Retrieval - // *Job_BatchIngestion - // *Job_StreamIngestion - Meta isJob_Meta `protobuf_oneof:"meta"` -} - -func (x *Job) Reset() { - *x = Job{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Job) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Job) ProtoMessage() {} - -func (x *Job) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Job.ProtoReflect.Descriptor instead. -func (*Job) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{0} -} - -func (x *Job) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Job) GetType() JobType { - if x != nil { - return x.Type - } - return JobType_INVALID_JOB -} - -func (x *Job) GetStatus() JobStatus { - if x != nil { - return x.Status - } - return JobStatus_JOB_STATUS_INVALID -} - -func (x *Job) GetHash() string { - if x != nil { - return x.Hash - } - return "" -} - -func (m *Job) GetMeta() isJob_Meta { - if m != nil { - return m.Meta - } - return nil -} - -func (x *Job) GetRetrieval() *Job_RetrievalJobMeta { - if x, ok := x.GetMeta().(*Job_Retrieval); ok { - return x.Retrieval - } - return nil -} - -func (x *Job) GetBatchIngestion() *Job_OfflineToOnlineMeta { - if x, ok := x.GetMeta().(*Job_BatchIngestion); ok { - return x.BatchIngestion - } - return nil -} - -func (x *Job) GetStreamIngestion() *Job_StreamToOnlineMeta { - if x, ok := x.GetMeta().(*Job_StreamIngestion); ok { - return x.StreamIngestion - } - return nil -} - -type isJob_Meta interface { - isJob_Meta() -} - -type Job_Retrieval struct { - Retrieval *Job_RetrievalJobMeta `protobuf:"bytes,5,opt,name=retrieval,proto3,oneof"` -} - -type Job_BatchIngestion struct { - BatchIngestion *Job_OfflineToOnlineMeta `protobuf:"bytes,6,opt,name=batch_ingestion,json=batchIngestion,proto3,oneof"` -} - -type Job_StreamIngestion struct { - StreamIngestion *Job_StreamToOnlineMeta `protobuf:"bytes,7,opt,name=stream_ingestion,json=streamIngestion,proto3,oneof"` -} - -func (*Job_Retrieval) isJob_Meta() {} - -func (*Job_BatchIngestion) isJob_Meta() {} - -func (*Job_StreamIngestion) isJob_Meta() {} - -// Ingest data from offline store into online store -type StartOfflineToOnlineIngestionJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Feature table to ingest - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - TableName string `protobuf:"bytes,2,opt,name=table_name,json=tableName,proto3" json:"table_name,omitempty"` - // Start of time range for source data from offline store - StartDate *timestamp.Timestamp `protobuf:"bytes,3,opt,name=start_date,json=startDate,proto3" json:"start_date,omitempty"` - // End of time range for source data from offline store - EndDate *timestamp.Timestamp `protobuf:"bytes,4,opt,name=end_date,json=endDate,proto3" json:"end_date,omitempty"` -} - -func (x *StartOfflineToOnlineIngestionJobRequest) Reset() { - *x = StartOfflineToOnlineIngestionJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartOfflineToOnlineIngestionJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartOfflineToOnlineIngestionJobRequest) ProtoMessage() {} - -func (x *StartOfflineToOnlineIngestionJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartOfflineToOnlineIngestionJobRequest.ProtoReflect.Descriptor instead. -func (*StartOfflineToOnlineIngestionJobRequest) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{1} -} - -func (x *StartOfflineToOnlineIngestionJobRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *StartOfflineToOnlineIngestionJobRequest) GetTableName() string { - if x != nil { - return x.TableName - } - return "" -} - -func (x *StartOfflineToOnlineIngestionJobRequest) GetStartDate() *timestamp.Timestamp { - if x != nil { - return x.StartDate - } - return nil -} - -func (x *StartOfflineToOnlineIngestionJobRequest) GetEndDate() *timestamp.Timestamp { - if x != nil { - return x.EndDate - } - return nil -} - -type StartOfflineToOnlineIngestionJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Job ID assigned by Feast - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *StartOfflineToOnlineIngestionJobResponse) Reset() { - *x = StartOfflineToOnlineIngestionJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartOfflineToOnlineIngestionJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartOfflineToOnlineIngestionJobResponse) ProtoMessage() {} - -func (x *StartOfflineToOnlineIngestionJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartOfflineToOnlineIngestionJobResponse.ProtoReflect.Descriptor instead. -func (*StartOfflineToOnlineIngestionJobResponse) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{2} -} - -func (x *StartOfflineToOnlineIngestionJobResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type GetHistoricalFeaturesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of feature references that are being retrieved - FeatureRefs []string `protobuf:"bytes,1,rep,name=feature_refs,json=featureRefs,proto3" json:"feature_refs,omitempty"` - // Batch DataSource that can be used to obtain entity values for historical retrieval. - // For each entity value, a feature value will be retrieved for that value/timestamp - // Only 'BATCH_*' source types are supported. - // Currently only BATCH_FILE source type is supported. - EntitySource *DataSource `protobuf:"bytes,2,opt,name=entity_source,json=entitySource,proto3" json:"entity_source,omitempty"` - // Optional field to specify project name override. If specified, uses the - // given project for retrieval. Overrides the projects specified in - // Feature References if both are specified. - Project string `protobuf:"bytes,3,opt,name=project,proto3" json:"project,omitempty"` - // Specifies the path in a bucket to write the exported feature data files - // Export to AWS S3 - s3://path/to/features - // Export to GCP GCS - gs://path/to/features - OutputLocation string `protobuf:"bytes,4,opt,name=output_location,json=outputLocation,proto3" json:"output_location,omitempty"` - // Specify format name for output, eg. parquet - OutputFormat string `protobuf:"bytes,5,opt,name=output_format,json=outputFormat,proto3" json:"output_format,omitempty"` -} - -func (x *GetHistoricalFeaturesRequest) Reset() { - *x = GetHistoricalFeaturesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetHistoricalFeaturesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetHistoricalFeaturesRequest) ProtoMessage() {} - -func (x *GetHistoricalFeaturesRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetHistoricalFeaturesRequest.ProtoReflect.Descriptor instead. -func (*GetHistoricalFeaturesRequest) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{3} -} - -func (x *GetHistoricalFeaturesRequest) GetFeatureRefs() []string { - if x != nil { - return x.FeatureRefs - } - return nil -} - -func (x *GetHistoricalFeaturesRequest) GetEntitySource() *DataSource { - if x != nil { - return x.EntitySource - } - return nil -} - -func (x *GetHistoricalFeaturesRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *GetHistoricalFeaturesRequest) GetOutputLocation() string { - if x != nil { - return x.OutputLocation - } - return "" -} - -func (x *GetHistoricalFeaturesRequest) GetOutputFormat() string { - if x != nil { - return x.OutputFormat - } - return "" -} - -type GetHistoricalFeaturesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Export Job with ID assigned by Feast - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - OutputFileUri string `protobuf:"bytes,2,opt,name=output_file_uri,json=outputFileUri,proto3" json:"output_file_uri,omitempty"` -} - -func (x *GetHistoricalFeaturesResponse) Reset() { - *x = GetHistoricalFeaturesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetHistoricalFeaturesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetHistoricalFeaturesResponse) ProtoMessage() {} - -func (x *GetHistoricalFeaturesResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetHistoricalFeaturesResponse.ProtoReflect.Descriptor instead. -func (*GetHistoricalFeaturesResponse) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{4} -} - -func (x *GetHistoricalFeaturesResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *GetHistoricalFeaturesResponse) GetOutputFileUri() string { - if x != nil { - return x.OutputFileUri - } - return "" -} - -type StartStreamToOnlineIngestionJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Feature table to ingest - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - TableName string `protobuf:"bytes,2,opt,name=table_name,json=tableName,proto3" json:"table_name,omitempty"` -} - -func (x *StartStreamToOnlineIngestionJobRequest) Reset() { - *x = StartStreamToOnlineIngestionJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartStreamToOnlineIngestionJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartStreamToOnlineIngestionJobRequest) ProtoMessage() {} - -func (x *StartStreamToOnlineIngestionJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartStreamToOnlineIngestionJobRequest.ProtoReflect.Descriptor instead. -func (*StartStreamToOnlineIngestionJobRequest) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{5} -} - -func (x *StartStreamToOnlineIngestionJobRequest) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *StartStreamToOnlineIngestionJobRequest) GetTableName() string { - if x != nil { - return x.TableName - } - return "" -} - -type StartStreamToOnlineIngestionJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Job ID assigned by Feast - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *StartStreamToOnlineIngestionJobResponse) Reset() { - *x = StartStreamToOnlineIngestionJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartStreamToOnlineIngestionJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartStreamToOnlineIngestionJobResponse) ProtoMessage() {} - -func (x *StartStreamToOnlineIngestionJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartStreamToOnlineIngestionJobResponse.ProtoReflect.Descriptor instead. -func (*StartStreamToOnlineIngestionJobResponse) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{6} -} - -func (x *StartStreamToOnlineIngestionJobResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -type ListJobsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - IncludeTerminated bool `protobuf:"varint,1,opt,name=include_terminated,json=includeTerminated,proto3" json:"include_terminated,omitempty"` -} - -func (x *ListJobsRequest) Reset() { - *x = ListJobsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListJobsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListJobsRequest) ProtoMessage() {} - -func (x *ListJobsRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListJobsRequest.ProtoReflect.Descriptor instead. -func (*ListJobsRequest) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{7} -} - -func (x *ListJobsRequest) GetIncludeTerminated() bool { - if x != nil { - return x.IncludeTerminated - } - return false -} - -type ListJobsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Jobs []*Job `protobuf:"bytes,1,rep,name=jobs,proto3" json:"jobs,omitempty"` -} - -func (x *ListJobsResponse) Reset() { - *x = ListJobsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListJobsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListJobsResponse) ProtoMessage() {} - -func (x *ListJobsResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListJobsResponse.ProtoReflect.Descriptor instead. -func (*ListJobsResponse) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{8} -} - -func (x *ListJobsResponse) GetJobs() []*Job { - if x != nil { - return x.Jobs - } - return nil -} - -type GetJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` -} - -func (x *GetJobRequest) Reset() { - *x = GetJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetJobRequest) ProtoMessage() {} - -func (x *GetJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetJobRequest.ProtoReflect.Descriptor instead. -func (*GetJobRequest) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{9} -} - -func (x *GetJobRequest) GetJobId() string { - if x != nil { - return x.JobId - } - return "" -} - -type GetJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Job *Job `protobuf:"bytes,1,opt,name=job,proto3" json:"job,omitempty"` -} - -func (x *GetJobResponse) Reset() { - *x = GetJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetJobResponse) ProtoMessage() {} - -func (x *GetJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetJobResponse.ProtoReflect.Descriptor instead. -func (*GetJobResponse) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{10} -} - -func (x *GetJobResponse) GetJob() *Job { - if x != nil { - return x.Job - } - return nil -} - -type CancelJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` -} - -func (x *CancelJobRequest) Reset() { - *x = CancelJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CancelJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelJobRequest) ProtoMessage() {} - -func (x *CancelJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelJobRequest.ProtoReflect.Descriptor instead. -func (*CancelJobRequest) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{11} -} - -func (x *CancelJobRequest) GetJobId() string { - if x != nil { - return x.JobId - } - return "" -} - -type CancelJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *CancelJobResponse) Reset() { - *x = CancelJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CancelJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelJobResponse) ProtoMessage() {} - -func (x *CancelJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelJobResponse.ProtoReflect.Descriptor instead. -func (*CancelJobResponse) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{12} -} - -type Job_RetrievalJobMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - OutputLocation string `protobuf:"bytes,4,opt,name=output_location,json=outputLocation,proto3" json:"output_location,omitempty"` -} - -func (x *Job_RetrievalJobMeta) Reset() { - *x = Job_RetrievalJobMeta{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Job_RetrievalJobMeta) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Job_RetrievalJobMeta) ProtoMessage() {} - -func (x *Job_RetrievalJobMeta) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Job_RetrievalJobMeta.ProtoReflect.Descriptor instead. -func (*Job_RetrievalJobMeta) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{0, 0} -} - -func (x *Job_RetrievalJobMeta) GetOutputLocation() string { - if x != nil { - return x.OutputLocation - } - return "" -} - -type Job_OfflineToOnlineMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Job_OfflineToOnlineMeta) Reset() { - *x = Job_OfflineToOnlineMeta{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Job_OfflineToOnlineMeta) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Job_OfflineToOnlineMeta) ProtoMessage() {} - -func (x *Job_OfflineToOnlineMeta) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Job_OfflineToOnlineMeta.ProtoReflect.Descriptor instead. -func (*Job_OfflineToOnlineMeta) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{0, 1} -} - -type Job_StreamToOnlineMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Job_StreamToOnlineMeta) Reset() { - *x = Job_StreamToOnlineMeta{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_JobService_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Job_StreamToOnlineMeta) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Job_StreamToOnlineMeta) ProtoMessage() {} - -func (x *Job_StreamToOnlineMeta) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_JobService_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Job_StreamToOnlineMeta.ProtoReflect.Descriptor instead. -func (*Job_StreamToOnlineMeta) Descriptor() ([]byte, []int) { - return file_feast_core_JobService_proto_rawDescGZIP(), []int{0, 2} -} - -var File_feast_core_JobService_proto protoreflect.FileDescriptor - -var file_feast_core_JobService_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x4a, 0x6f, 0x62, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, 0x03, 0x0a, 0x03, 0x4a, 0x6f, 0x62, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x27, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x40, 0x0a, 0x09, 0x72, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x2e, - 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x61, 0x6c, 0x4a, 0x6f, 0x62, 0x4d, 0x65, 0x74, 0x61, - 0x48, 0x00, 0x52, 0x09, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x61, 0x6c, 0x12, 0x4e, 0x0a, - 0x0f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x2e, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x54, - 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x62, - 0x61, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4f, 0x0a, - 0x10, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, - 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0f, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x3b, - 0x0a, 0x10, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x61, 0x6c, 0x4a, 0x6f, 0x62, 0x4d, 0x65, - 0x74, 0x61, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x15, 0x0a, 0x13, 0x4f, - 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x1a, 0x14, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x6f, 0x4f, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x42, 0x06, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, - 0x22, 0xd4, 0x01, 0x0a, 0x27, 0x53, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, - 0x65, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, - 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, - 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, - 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, - 0x65, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x22, 0x3a, 0x0a, 0x28, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, - 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x22, 0xe6, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x69, 0x63, 0x61, 0x6c, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, - 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x65, 0x66, 0x73, 0x12, 0x3b, 0x0a, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0c, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x27, - 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x57, 0x0a, 0x1d, - 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, - 0x0f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x69, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x46, 0x69, - 0x6c, 0x65, 0x55, 0x72, 0x69, 0x22, 0x61, 0x0a, 0x26, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x67, 0x65, - 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x27, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, - 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x22, 0x40, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x61, 0x74, 0x65, 0x64, 0x22, 0x37, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x6a, 0x6f, 0x62, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, 0x26, - 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x33, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, 0x22, 0x29, 0x0a, 0x10, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x60, 0x0a, 0x07, 0x4a, - 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, - 0x44, 0x5f, 0x4a, 0x4f, 0x42, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x42, 0x41, 0x54, 0x43, 0x48, - 0x5f, 0x49, 0x4e, 0x47, 0x45, 0x53, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4a, 0x4f, 0x42, 0x10, 0x01, - 0x12, 0x18, 0x0a, 0x14, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x49, 0x4e, 0x47, 0x45, 0x53, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4a, 0x4f, 0x42, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, - 0x54, 0x52, 0x49, 0x45, 0x56, 0x41, 0x4c, 0x5f, 0x4a, 0x4f, 0x42, 0x10, 0x04, 0x2a, 0x7e, 0x0a, - 0x09, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, - 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, - 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4a, 0x4f, - 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, - 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4a, 0x4f, 0x42, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x4a, 0x4f, 0x42, 0x5f, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x32, 0xe9, 0x04, - 0x0a, 0x0a, 0x4a, 0x6f, 0x62, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8d, 0x01, 0x0a, - 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x6f, 0x4f, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, - 0x62, 0x12, 0x33, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, - 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, - 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x15, - 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x29, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x1f, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, - 0x6e, 0x65, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x32, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, - 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x6f, 0x4f, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x4a, - 0x6f, 0x62, 0x73, 0x12, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, - 0x0a, 0x09, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4a, 0x6f, 0x62, 0x12, 0x1c, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4a, - 0x6f, 0x62, 0x12, 0x19, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x58, 0x0a, 0x10, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0f, 0x4a, - 0x6f, 0x62, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, - 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, - 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_JobService_proto_rawDescOnce sync.Once - file_feast_core_JobService_proto_rawDescData = file_feast_core_JobService_proto_rawDesc -) - -func file_feast_core_JobService_proto_rawDescGZIP() []byte { - file_feast_core_JobService_proto_rawDescOnce.Do(func() { - file_feast_core_JobService_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_JobService_proto_rawDescData) - }) - return file_feast_core_JobService_proto_rawDescData -} - -var file_feast_core_JobService_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_feast_core_JobService_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_feast_core_JobService_proto_goTypes = []interface{}{ - (JobType)(0), // 0: feast.core.JobType - (JobStatus)(0), // 1: feast.core.JobStatus - (*Job)(nil), // 2: feast.core.Job - (*StartOfflineToOnlineIngestionJobRequest)(nil), // 3: feast.core.StartOfflineToOnlineIngestionJobRequest - (*StartOfflineToOnlineIngestionJobResponse)(nil), // 4: feast.core.StartOfflineToOnlineIngestionJobResponse - (*GetHistoricalFeaturesRequest)(nil), // 5: feast.core.GetHistoricalFeaturesRequest - (*GetHistoricalFeaturesResponse)(nil), // 6: feast.core.GetHistoricalFeaturesResponse - (*StartStreamToOnlineIngestionJobRequest)(nil), // 7: feast.core.StartStreamToOnlineIngestionJobRequest - (*StartStreamToOnlineIngestionJobResponse)(nil), // 8: feast.core.StartStreamToOnlineIngestionJobResponse - (*ListJobsRequest)(nil), // 9: feast.core.ListJobsRequest - (*ListJobsResponse)(nil), // 10: feast.core.ListJobsResponse - (*GetJobRequest)(nil), // 11: feast.core.GetJobRequest - (*GetJobResponse)(nil), // 12: feast.core.GetJobResponse - (*CancelJobRequest)(nil), // 13: feast.core.CancelJobRequest - (*CancelJobResponse)(nil), // 14: feast.core.CancelJobResponse - (*Job_RetrievalJobMeta)(nil), // 15: feast.core.Job.RetrievalJobMeta - (*Job_OfflineToOnlineMeta)(nil), // 16: feast.core.Job.OfflineToOnlineMeta - (*Job_StreamToOnlineMeta)(nil), // 17: feast.core.Job.StreamToOnlineMeta - (*timestamp.Timestamp)(nil), // 18: google.protobuf.Timestamp - (*DataSource)(nil), // 19: feast.core.DataSource -} -var file_feast_core_JobService_proto_depIdxs = []int32{ - 0, // 0: feast.core.Job.type:type_name -> feast.core.JobType - 1, // 1: feast.core.Job.status:type_name -> feast.core.JobStatus - 15, // 2: feast.core.Job.retrieval:type_name -> feast.core.Job.RetrievalJobMeta - 16, // 3: feast.core.Job.batch_ingestion:type_name -> feast.core.Job.OfflineToOnlineMeta - 17, // 4: feast.core.Job.stream_ingestion:type_name -> feast.core.Job.StreamToOnlineMeta - 18, // 5: feast.core.StartOfflineToOnlineIngestionJobRequest.start_date:type_name -> google.protobuf.Timestamp - 18, // 6: feast.core.StartOfflineToOnlineIngestionJobRequest.end_date:type_name -> google.protobuf.Timestamp - 19, // 7: feast.core.GetHistoricalFeaturesRequest.entity_source:type_name -> feast.core.DataSource - 2, // 8: feast.core.ListJobsResponse.jobs:type_name -> feast.core.Job - 2, // 9: feast.core.GetJobResponse.job:type_name -> feast.core.Job - 3, // 10: feast.core.JobService.StartOfflineToOnlineIngestionJob:input_type -> feast.core.StartOfflineToOnlineIngestionJobRequest - 5, // 11: feast.core.JobService.GetHistoricalFeatures:input_type -> feast.core.GetHistoricalFeaturesRequest - 7, // 12: feast.core.JobService.StartStreamToOnlineIngestionJob:input_type -> feast.core.StartStreamToOnlineIngestionJobRequest - 9, // 13: feast.core.JobService.ListJobs:input_type -> feast.core.ListJobsRequest - 13, // 14: feast.core.JobService.CancelJob:input_type -> feast.core.CancelJobRequest - 11, // 15: feast.core.JobService.GetJob:input_type -> feast.core.GetJobRequest - 4, // 16: feast.core.JobService.StartOfflineToOnlineIngestionJob:output_type -> feast.core.StartOfflineToOnlineIngestionJobResponse - 6, // 17: feast.core.JobService.GetHistoricalFeatures:output_type -> feast.core.GetHistoricalFeaturesResponse - 8, // 18: feast.core.JobService.StartStreamToOnlineIngestionJob:output_type -> feast.core.StartStreamToOnlineIngestionJobResponse - 10, // 19: feast.core.JobService.ListJobs:output_type -> feast.core.ListJobsResponse - 14, // 20: feast.core.JobService.CancelJob:output_type -> feast.core.CancelJobResponse - 12, // 21: feast.core.JobService.GetJob:output_type -> feast.core.GetJobResponse - 16, // [16:22] is the sub-list for method output_type - 10, // [10:16] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name -} - -func init() { file_feast_core_JobService_proto_init() } -func file_feast_core_JobService_proto_init() { - if File_feast_core_JobService_proto != nil { - return - } - file_feast_core_DataSource_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_core_JobService_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Job); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartOfflineToOnlineIngestionJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartOfflineToOnlineIngestionJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetHistoricalFeaturesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetHistoricalFeaturesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartStreamToOnlineIngestionJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartStreamToOnlineIngestionJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListJobsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListJobsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CancelJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CancelJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Job_RetrievalJobMeta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Job_OfflineToOnlineMeta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_JobService_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Job_StreamToOnlineMeta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_core_JobService_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Job_Retrieval)(nil), - (*Job_BatchIngestion)(nil), - (*Job_StreamIngestion)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_JobService_proto_rawDesc, - NumEnums: 2, - NumMessages: 16, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_feast_core_JobService_proto_goTypes, - DependencyIndexes: file_feast_core_JobService_proto_depIdxs, - EnumInfos: file_feast_core_JobService_proto_enumTypes, - MessageInfos: file_feast_core_JobService_proto_msgTypes, - }.Build() - File_feast_core_JobService_proto = out.File - file_feast_core_JobService_proto_rawDesc = nil - file_feast_core_JobService_proto_goTypes = nil - file_feast_core_JobService_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 - -// JobServiceClient is the client API for JobService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type JobServiceClient interface { - // Start job to ingest data from offline store into online store - StartOfflineToOnlineIngestionJob(ctx context.Context, in *StartOfflineToOnlineIngestionJobRequest, opts ...grpc.CallOption) (*StartOfflineToOnlineIngestionJobResponse, error) - // Produce a training dataset, return a job id that will provide a file reference - GetHistoricalFeatures(ctx context.Context, in *GetHistoricalFeaturesRequest, opts ...grpc.CallOption) (*GetHistoricalFeaturesResponse, error) - // Start job to ingest data from stream into online store - StartStreamToOnlineIngestionJob(ctx context.Context, in *StartStreamToOnlineIngestionJobRequest, opts ...grpc.CallOption) (*StartStreamToOnlineIngestionJobResponse, error) - // List all types of jobs - ListJobs(ctx context.Context, in *ListJobsRequest, opts ...grpc.CallOption) (*ListJobsResponse, error) - // Cancel a single job - CancelJob(ctx context.Context, in *CancelJobRequest, opts ...grpc.CallOption) (*CancelJobResponse, error) - // Get details of a single job - GetJob(ctx context.Context, in *GetJobRequest, opts ...grpc.CallOption) (*GetJobResponse, error) -} - -type jobServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewJobServiceClient(cc grpc.ClientConnInterface) JobServiceClient { - return &jobServiceClient{cc} -} - -func (c *jobServiceClient) StartOfflineToOnlineIngestionJob(ctx context.Context, in *StartOfflineToOnlineIngestionJobRequest, opts ...grpc.CallOption) (*StartOfflineToOnlineIngestionJobResponse, error) { - out := new(StartOfflineToOnlineIngestionJobResponse) - err := c.cc.Invoke(ctx, "/feast.core.JobService/StartOfflineToOnlineIngestionJob", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) GetHistoricalFeatures(ctx context.Context, in *GetHistoricalFeaturesRequest, opts ...grpc.CallOption) (*GetHistoricalFeaturesResponse, error) { - out := new(GetHistoricalFeaturesResponse) - err := c.cc.Invoke(ctx, "/feast.core.JobService/GetHistoricalFeatures", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) StartStreamToOnlineIngestionJob(ctx context.Context, in *StartStreamToOnlineIngestionJobRequest, opts ...grpc.CallOption) (*StartStreamToOnlineIngestionJobResponse, error) { - out := new(StartStreamToOnlineIngestionJobResponse) - err := c.cc.Invoke(ctx, "/feast.core.JobService/StartStreamToOnlineIngestionJob", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) ListJobs(ctx context.Context, in *ListJobsRequest, opts ...grpc.CallOption) (*ListJobsResponse, error) { - out := new(ListJobsResponse) - err := c.cc.Invoke(ctx, "/feast.core.JobService/ListJobs", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) CancelJob(ctx context.Context, in *CancelJobRequest, opts ...grpc.CallOption) (*CancelJobResponse, error) { - out := new(CancelJobResponse) - err := c.cc.Invoke(ctx, "/feast.core.JobService/CancelJob", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) GetJob(ctx context.Context, in *GetJobRequest, opts ...grpc.CallOption) (*GetJobResponse, error) { - out := new(GetJobResponse) - err := c.cc.Invoke(ctx, "/feast.core.JobService/GetJob", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// JobServiceServer is the server API for JobService service. -type JobServiceServer interface { - // Start job to ingest data from offline store into online store - StartOfflineToOnlineIngestionJob(context.Context, *StartOfflineToOnlineIngestionJobRequest) (*StartOfflineToOnlineIngestionJobResponse, error) - // Produce a training dataset, return a job id that will provide a file reference - GetHistoricalFeatures(context.Context, *GetHistoricalFeaturesRequest) (*GetHistoricalFeaturesResponse, error) - // Start job to ingest data from stream into online store - StartStreamToOnlineIngestionJob(context.Context, *StartStreamToOnlineIngestionJobRequest) (*StartStreamToOnlineIngestionJobResponse, error) - // List all types of jobs - ListJobs(context.Context, *ListJobsRequest) (*ListJobsResponse, error) - // Cancel a single job - CancelJob(context.Context, *CancelJobRequest) (*CancelJobResponse, error) - // Get details of a single job - GetJob(context.Context, *GetJobRequest) (*GetJobResponse, error) -} - -// UnimplementedJobServiceServer can be embedded to have forward compatible implementations. -type UnimplementedJobServiceServer struct { -} - -func (*UnimplementedJobServiceServer) StartOfflineToOnlineIngestionJob(context.Context, *StartOfflineToOnlineIngestionJobRequest) (*StartOfflineToOnlineIngestionJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method StartOfflineToOnlineIngestionJob not implemented") -} -func (*UnimplementedJobServiceServer) GetHistoricalFeatures(context.Context, *GetHistoricalFeaturesRequest) (*GetHistoricalFeaturesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetHistoricalFeatures not implemented") -} -func (*UnimplementedJobServiceServer) StartStreamToOnlineIngestionJob(context.Context, *StartStreamToOnlineIngestionJobRequest) (*StartStreamToOnlineIngestionJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method StartStreamToOnlineIngestionJob not implemented") -} -func (*UnimplementedJobServiceServer) ListJobs(context.Context, *ListJobsRequest) (*ListJobsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListJobs not implemented") -} -func (*UnimplementedJobServiceServer) CancelJob(context.Context, *CancelJobRequest) (*CancelJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CancelJob not implemented") -} -func (*UnimplementedJobServiceServer) GetJob(context.Context, *GetJobRequest) (*GetJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetJob not implemented") -} - -func RegisterJobServiceServer(s *grpc.Server, srv JobServiceServer) { - s.RegisterService(&_JobService_serviceDesc, srv) -} - -func _JobService_StartOfflineToOnlineIngestionJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(StartOfflineToOnlineIngestionJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).StartOfflineToOnlineIngestionJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.JobService/StartOfflineToOnlineIngestionJob", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).StartOfflineToOnlineIngestionJob(ctx, req.(*StartOfflineToOnlineIngestionJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_GetHistoricalFeatures_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetHistoricalFeaturesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).GetHistoricalFeatures(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.JobService/GetHistoricalFeatures", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).GetHistoricalFeatures(ctx, req.(*GetHistoricalFeaturesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_StartStreamToOnlineIngestionJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(StartStreamToOnlineIngestionJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).StartStreamToOnlineIngestionJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.JobService/StartStreamToOnlineIngestionJob", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).StartStreamToOnlineIngestionJob(ctx, req.(*StartStreamToOnlineIngestionJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_ListJobs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListJobsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).ListJobs(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.JobService/ListJobs", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).ListJobs(ctx, req.(*ListJobsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_CancelJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CancelJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).CancelJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.JobService/CancelJob", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).CancelJob(ctx, req.(*CancelJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_GetJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).GetJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.core.JobService/GetJob", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).GetJob(ctx, req.(*GetJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _JobService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "feast.core.JobService", - HandlerType: (*JobServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "StartOfflineToOnlineIngestionJob", - Handler: _JobService_StartOfflineToOnlineIngestionJob_Handler, - }, - { - MethodName: "GetHistoricalFeatures", - Handler: _JobService_GetHistoricalFeatures_Handler, - }, - { - MethodName: "StartStreamToOnlineIngestionJob", - Handler: _JobService_StartStreamToOnlineIngestionJob_Handler, - }, - { - MethodName: "ListJobs", - Handler: _JobService_ListJobs_Handler, - }, - { - MethodName: "CancelJob", - Handler: _JobService_CancelJob_Handler, - }, - { - MethodName: "GetJob", - Handler: _JobService_GetJob_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "feast/core/JobService.proto", -} diff --git a/sdk/go/protos/feast/core/Runner.pb.go b/sdk/go/protos/feast/core/Runner.pb.go deleted file mode 100644 index 763695f6c8e..00000000000 --- a/sdk/go/protos/feast/core/Runner.pb.go +++ /dev/null @@ -1,467 +0,0 @@ -// -// * Copyright 2020 The Feast Authors -// * -// * 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 -// * -// * https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.10.0 -// source: feast/core/Runner.proto - -package core - -import ( - proto "github.com/golang/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 DirectRunnerConfigOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - //* - // Controls the amount of target parallelism the DirectRunner will use. - // Defaults to the greater of the number of available processors and 3. Must be a value - // greater than zero. - TargetParallelism int32 `protobuf:"varint,1,opt,name=targetParallelism,proto3" json:"targetParallelism,omitempty"` - // BigQuery table specification, e.g. PROJECT_ID:DATASET_ID.PROJECT_ID - DeadLetterTableSpec string `protobuf:"bytes,2,opt,name=deadLetterTableSpec,proto3" json:"deadLetterTableSpec,omitempty"` - // A pipeline level default location for storing temporary files. - // Support Google Cloud Storage locations or local path - TempLocation string `protobuf:"bytes,3,opt,name=tempLocation,proto3" json:"tempLocation,omitempty"` -} - -func (x *DirectRunnerConfigOptions) Reset() { - *x = DirectRunnerConfigOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Runner_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DirectRunnerConfigOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DirectRunnerConfigOptions) ProtoMessage() {} - -func (x *DirectRunnerConfigOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Runner_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DirectRunnerConfigOptions.ProtoReflect.Descriptor instead. -func (*DirectRunnerConfigOptions) Descriptor() ([]byte, []int) { - return file_feast_core_Runner_proto_rawDescGZIP(), []int{0} -} - -func (x *DirectRunnerConfigOptions) GetTargetParallelism() int32 { - if x != nil { - return x.TargetParallelism - } - return 0 -} - -func (x *DirectRunnerConfigOptions) GetDeadLetterTableSpec() string { - if x != nil { - return x.DeadLetterTableSpec - } - return "" -} - -func (x *DirectRunnerConfigOptions) GetTempLocation() string { - if x != nil { - return x.TempLocation - } - return "" -} - -type DataflowRunnerConfigOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Project id to use when launching jobs. - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - // The Google Compute Engine region for creating Dataflow jobs. - Region string `protobuf:"bytes,2,opt,name=region,proto3" json:"region,omitempty"` - // GCP availability zone for operations. - WorkerZone string `protobuf:"bytes,3,opt,name=workerZone,proto3" json:"workerZone,omitempty"` - // Run the job as a specific service account, instead of the default GCE robot. - ServiceAccount string `protobuf:"bytes,4,opt,name=serviceAccount,proto3" json:"serviceAccount,omitempty"` - // GCE network for launching workers. - Network string `protobuf:"bytes,5,opt,name=network,proto3" json:"network,omitempty"` - // GCE subnetwork for launching workers. e.g. regions/asia-east1/subnetworks/mysubnetwork - Subnetwork string `protobuf:"bytes,6,opt,name=subnetwork,proto3" json:"subnetwork,omitempty"` - // Machine type to create Dataflow worker VMs as. - WorkerMachineType string `protobuf:"bytes,7,opt,name=workerMachineType,proto3" json:"workerMachineType,omitempty"` - // The autoscaling algorithm to use for the workerpool. - AutoscalingAlgorithm string `protobuf:"bytes,8,opt,name=autoscalingAlgorithm,proto3" json:"autoscalingAlgorithm,omitempty"` - // Specifies whether worker pools should be started with public IP addresses. - UsePublicIps bool `protobuf:"varint,9,opt,name=usePublicIps,proto3" json:"usePublicIps,omitempty"` - // A pipeline level default location for storing temporary files. Support Google Cloud Storage locations, - // e.g. gs://bucket/object - TempLocation string `protobuf:"bytes,10,opt,name=tempLocation,proto3" json:"tempLocation,omitempty"` - // The maximum number of workers to use for the workerpool. - MaxNumWorkers int32 `protobuf:"varint,11,opt,name=maxNumWorkers,proto3" json:"maxNumWorkers,omitempty"` - // BigQuery table specification, e.g. PROJECT_ID:DATASET_ID.PROJECT_ID - DeadLetterTableSpec string `protobuf:"bytes,12,opt,name=deadLetterTableSpec,proto3" json:"deadLetterTableSpec,omitempty"` - // Labels to apply to the dataflow job - Labels map[string]string `protobuf:"bytes,13,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // Disk size to use on each remote Compute Engine worker instance - DiskSizeGb int32 `protobuf:"varint,14,opt,name=diskSizeGb,proto3" json:"diskSizeGb,omitempty"` - // Run job on Dataflow Streaming Engine instead of creating worker VMs - EnableStreamingEngine bool `protobuf:"varint,15,opt,name=enableStreamingEngine,proto3" json:"enableStreamingEngine,omitempty"` - // Type of persistent disk to be used by workers - WorkerDiskType string `protobuf:"bytes,16,opt,name=workerDiskType,proto3" json:"workerDiskType,omitempty"` - // Kafka consumer configuration properties - KafkaConsumerProperties map[string]string `protobuf:"bytes,17,rep,name=kafkaConsumerProperties,proto3" json:"kafkaConsumerProperties,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *DataflowRunnerConfigOptions) Reset() { - *x = DataflowRunnerConfigOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Runner_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataflowRunnerConfigOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataflowRunnerConfigOptions) ProtoMessage() {} - -func (x *DataflowRunnerConfigOptions) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Runner_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataflowRunnerConfigOptions.ProtoReflect.Descriptor instead. -func (*DataflowRunnerConfigOptions) Descriptor() ([]byte, []int) { - return file_feast_core_Runner_proto_rawDescGZIP(), []int{1} -} - -func (x *DataflowRunnerConfigOptions) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetRegion() string { - if x != nil { - return x.Region - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetWorkerZone() string { - if x != nil { - return x.WorkerZone - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetServiceAccount() string { - if x != nil { - return x.ServiceAccount - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetNetwork() string { - if x != nil { - return x.Network - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetSubnetwork() string { - if x != nil { - return x.Subnetwork - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetWorkerMachineType() string { - if x != nil { - return x.WorkerMachineType - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetAutoscalingAlgorithm() string { - if x != nil { - return x.AutoscalingAlgorithm - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetUsePublicIps() bool { - if x != nil { - return x.UsePublicIps - } - return false -} - -func (x *DataflowRunnerConfigOptions) GetTempLocation() string { - if x != nil { - return x.TempLocation - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetMaxNumWorkers() int32 { - if x != nil { - return x.MaxNumWorkers - } - return 0 -} - -func (x *DataflowRunnerConfigOptions) GetDeadLetterTableSpec() string { - if x != nil { - return x.DeadLetterTableSpec - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -func (x *DataflowRunnerConfigOptions) GetDiskSizeGb() int32 { - if x != nil { - return x.DiskSizeGb - } - return 0 -} - -func (x *DataflowRunnerConfigOptions) GetEnableStreamingEngine() bool { - if x != nil { - return x.EnableStreamingEngine - } - return false -} - -func (x *DataflowRunnerConfigOptions) GetWorkerDiskType() string { - if x != nil { - return x.WorkerDiskType - } - return "" -} - -func (x *DataflowRunnerConfigOptions) GetKafkaConsumerProperties() map[string]string { - if x != nil { - return x.KafkaConsumerProperties - } - return nil -} - -var File_feast_core_Runner_proto protoreflect.FileDescriptor - -var file_feast_core_Runner_proto_rawDesc = []byte{ - 0x0a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x52, 0x75, 0x6e, - 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x19, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x72, - 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x69, 0x73, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x69, 0x73, - 0x6d, 0x12, 0x30, 0x0a, 0x13, 0x64, 0x65, 0x61, 0x64, 0x4c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, - 0x64, 0x65, 0x61, 0x64, 0x4c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, - 0x70, 0x65, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x4c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa5, 0x07, 0x0a, 0x1b, 0x44, 0x61, 0x74, 0x61, - 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x6f, 0x72, - 0x6b, 0x65, 0x72, 0x5a, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x1e, 0x0a, 0x0a, 0x73, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x2c, 0x0a, 0x11, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x14, 0x61, 0x75, 0x74, - 0x6f, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, - 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x61, 0x75, 0x74, 0x6f, 0x73, 0x63, 0x61, - 0x6c, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x22, 0x0a, - 0x0c, 0x75, 0x73, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x70, 0x73, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x70, - 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x4c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x4e, 0x75, 0x6d, 0x57, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, - 0x78, 0x4e, 0x75, 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x64, - 0x65, 0x61, 0x64, 0x4c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, - 0x65, 0x63, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x64, 0x65, 0x61, 0x64, 0x4c, 0x65, - 0x74, 0x74, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x4b, 0x0a, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x66, - 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, - 0x73, 0x6b, 0x53, 0x69, 0x7a, 0x65, 0x47, 0x62, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, - 0x64, 0x69, 0x73, 0x6b, 0x53, 0x69, 0x7a, 0x65, 0x47, 0x62, 0x12, 0x34, 0x0a, 0x15, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x67, - 0x69, 0x6e, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x12, 0x26, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x44, 0x69, 0x73, 0x6b, 0x54, 0x79, - 0x70, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x44, 0x69, 0x73, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x7e, 0x0a, 0x17, 0x6b, 0x61, 0x66, 0x6b, - 0x61, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x69, 0x65, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x66, 0x6c, 0x6f, 0x77, 0x52, - 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x17, 0x6b, 0x61, 0x66, 0x6b, 0x61, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x50, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x1a, 0x4a, 0x0a, 0x1c, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, - 0x54, 0x0a, 0x10, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x42, 0x0b, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, - 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_Runner_proto_rawDescOnce sync.Once - file_feast_core_Runner_proto_rawDescData = file_feast_core_Runner_proto_rawDesc -) - -func file_feast_core_Runner_proto_rawDescGZIP() []byte { - file_feast_core_Runner_proto_rawDescOnce.Do(func() { - file_feast_core_Runner_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_Runner_proto_rawDescData) - }) - return file_feast_core_Runner_proto_rawDescData -} - -var file_feast_core_Runner_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_feast_core_Runner_proto_goTypes = []interface{}{ - (*DirectRunnerConfigOptions)(nil), // 0: feast.core.DirectRunnerConfigOptions - (*DataflowRunnerConfigOptions)(nil), // 1: feast.core.DataflowRunnerConfigOptions - nil, // 2: feast.core.DataflowRunnerConfigOptions.LabelsEntry - nil, // 3: feast.core.DataflowRunnerConfigOptions.KafkaConsumerPropertiesEntry -} -var file_feast_core_Runner_proto_depIdxs = []int32{ - 2, // 0: feast.core.DataflowRunnerConfigOptions.labels:type_name -> feast.core.DataflowRunnerConfigOptions.LabelsEntry - 3, // 1: feast.core.DataflowRunnerConfigOptions.kafkaConsumerProperties:type_name -> feast.core.DataflowRunnerConfigOptions.KafkaConsumerPropertiesEntry - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_feast_core_Runner_proto_init() } -func file_feast_core_Runner_proto_init() { - if File_feast_core_Runner_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_core_Runner_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DirectRunnerConfigOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_Runner_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataflowRunnerConfigOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_Runner_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_Runner_proto_goTypes, - DependencyIndexes: file_feast_core_Runner_proto_depIdxs, - MessageInfos: file_feast_core_Runner_proto_msgTypes, - }.Build() - File_feast_core_Runner_proto = out.File - file_feast_core_Runner_proto_rawDesc = nil - file_feast_core_Runner_proto_goTypes = nil - file_feast_core_Runner_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/Source.pb.go b/sdk/go/protos/feast/core/Source.pb.go deleted file mode 100644 index af7f9783bbf..00000000000 --- a/sdk/go/protos/feast/core/Source.pb.go +++ /dev/null @@ -1,360 +0,0 @@ -// -// * Copyright 2019 The Feast Authors -// * -// * 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 -// * -// * https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.10.0 -// source: feast/core/Source.proto - -package core - -import ( - proto "github.com/golang/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 SourceType int32 - -const ( - SourceType_INVALID SourceType = 0 - SourceType_KAFKA SourceType = 1 -) - -// Enum value maps for SourceType. -var ( - SourceType_name = map[int32]string{ - 0: "INVALID", - 1: "KAFKA", - } - SourceType_value = map[string]int32{ - "INVALID": 0, - "KAFKA": 1, - } -) - -func (x SourceType) Enum() *SourceType { - p := new(SourceType) - *p = x - return p -} - -func (x SourceType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SourceType) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_Source_proto_enumTypes[0].Descriptor() -} - -func (SourceType) Type() protoreflect.EnumType { - return &file_feast_core_Source_proto_enumTypes[0] -} - -func (x SourceType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SourceType.Descriptor instead. -func (SourceType) EnumDescriptor() ([]byte, []int) { - return file_feast_core_Source_proto_rawDescGZIP(), []int{0} -} - -type Source struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The kind of data source Feast should connect to in order to retrieve FeatureRow value - Type SourceType `protobuf:"varint,1,opt,name=type,proto3,enum=feast.core.SourceType" json:"type,omitempty"` - // Source specific configuration - // - // Types that are assignable to SourceConfig: - // *Source_KafkaSourceConfig - SourceConfig isSource_SourceConfig `protobuf_oneof:"source_config"` -} - -func (x *Source) Reset() { - *x = Source{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Source_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Source) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Source) ProtoMessage() {} - -func (x *Source) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Source_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Source.ProtoReflect.Descriptor instead. -func (*Source) Descriptor() ([]byte, []int) { - return file_feast_core_Source_proto_rawDescGZIP(), []int{0} -} - -func (x *Source) GetType() SourceType { - if x != nil { - return x.Type - } - return SourceType_INVALID -} - -func (m *Source) GetSourceConfig() isSource_SourceConfig { - if m != nil { - return m.SourceConfig - } - return nil -} - -func (x *Source) GetKafkaSourceConfig() *KafkaSourceConfig { - if x, ok := x.GetSourceConfig().(*Source_KafkaSourceConfig); ok { - return x.KafkaSourceConfig - } - return nil -} - -type isSource_SourceConfig interface { - isSource_SourceConfig() -} - -type Source_KafkaSourceConfig struct { - KafkaSourceConfig *KafkaSourceConfig `protobuf:"bytes,2,opt,name=kafka_source_config,json=kafkaSourceConfig,proto3,oneof"` -} - -func (*Source_KafkaSourceConfig) isSource_SourceConfig() {} - -type KafkaSourceConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Comma separated list of Kafka bootstrap servers. Used for feature sets without a defined source host[:port]] - BootstrapServers string `protobuf:"bytes,1,opt,name=bootstrap_servers,json=bootstrapServers,proto3" json:"bootstrap_servers,omitempty"` - // Kafka topic to use for feature sets without user defined topics - Topic string `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"` - // Number of Kafka partitions to to use for managed feature stream. - Partitions int32 `protobuf:"varint,3,opt,name=partitions,proto3" json:"partitions,omitempty"` - // Defines the number of copies of managed feature stream Kafka. - ReplicationFactor int32 `protobuf:"varint,4,opt,name=replicationFactor,proto3" json:"replicationFactor,omitempty"` -} - -func (x *KafkaSourceConfig) Reset() { - *x = KafkaSourceConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Source_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KafkaSourceConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KafkaSourceConfig) ProtoMessage() {} - -func (x *KafkaSourceConfig) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Source_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KafkaSourceConfig.ProtoReflect.Descriptor instead. -func (*KafkaSourceConfig) Descriptor() ([]byte, []int) { - return file_feast_core_Source_proto_rawDescGZIP(), []int{1} -} - -func (x *KafkaSourceConfig) GetBootstrapServers() string { - if x != nil { - return x.BootstrapServers - } - return "" -} - -func (x *KafkaSourceConfig) GetTopic() string { - if x != nil { - return x.Topic - } - return "" -} - -func (x *KafkaSourceConfig) GetPartitions() int32 { - if x != nil { - return x.Partitions - } - return 0 -} - -func (x *KafkaSourceConfig) GetReplicationFactor() int32 { - if x != nil { - return x.ReplicationFactor - } - return 0 -} - -var File_feast_core_Source_proto protoreflect.FileDescriptor - -var file_feast_core_Source_proto_rawDesc = []byte{ - 0x0a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x4f, 0x0a, 0x13, - 0x6b, 0x61, 0x66, 0x6b, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x11, 0x6b, 0x61, 0x66, 0x6b, - 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0f, 0x0a, - 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xa4, - 0x01, 0x0a, 0x11, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, - 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x10, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x72, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x11, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x2a, 0x24, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, - 0x12, 0x09, 0x0a, 0x05, 0x4b, 0x41, 0x46, 0x4b, 0x41, 0x10, 0x01, 0x42, 0x54, 0x0a, 0x10, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, - 0x0b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, - 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, - 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_Source_proto_rawDescOnce sync.Once - file_feast_core_Source_proto_rawDescData = file_feast_core_Source_proto_rawDesc -) - -func file_feast_core_Source_proto_rawDescGZIP() []byte { - file_feast_core_Source_proto_rawDescOnce.Do(func() { - file_feast_core_Source_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_Source_proto_rawDescData) - }) - return file_feast_core_Source_proto_rawDescData -} - -var file_feast_core_Source_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_feast_core_Source_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_feast_core_Source_proto_goTypes = []interface{}{ - (SourceType)(0), // 0: feast.core.SourceType - (*Source)(nil), // 1: feast.core.Source - (*KafkaSourceConfig)(nil), // 2: feast.core.KafkaSourceConfig -} -var file_feast_core_Source_proto_depIdxs = []int32{ - 0, // 0: feast.core.Source.type:type_name -> feast.core.SourceType - 2, // 1: feast.core.Source.kafka_source_config:type_name -> feast.core.KafkaSourceConfig - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_feast_core_Source_proto_init() } -func file_feast_core_Source_proto_init() { - if File_feast_core_Source_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_core_Source_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Source); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_Source_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KafkaSourceConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_core_Source_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Source_KafkaSourceConfig)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_Source_proto_rawDesc, - NumEnums: 1, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_Source_proto_goTypes, - DependencyIndexes: file_feast_core_Source_proto_depIdxs, - EnumInfos: file_feast_core_Source_proto_enumTypes, - MessageInfos: file_feast_core_Source_proto_msgTypes, - }.Build() - File_feast_core_Source_proto = out.File - file_feast_core_Source_proto_rawDesc = nil - file_feast_core_Source_proto_goTypes = nil - file_feast_core_Source_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/core/Store.pb.go b/sdk/go/protos/feast/core/Store.pb.go deleted file mode 100644 index c56a4ede6dd..00000000000 --- a/sdk/go/protos/feast/core/Store.pb.go +++ /dev/null @@ -1,743 +0,0 @@ -// -// * Copyright 2019 The Feast Authors -// * -// * 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 -// * -// * https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/core/Store.proto - -package core - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Store_StoreType int32 - -const ( - Store_INVALID Store_StoreType = 0 - // Redis stores a FeatureRow element as a key, value pair. - // - // The Redis data types used (https://redis.io/topics/data-types): - // - key: STRING - // - value: STRING - // - // Encodings: - // - key: byte array of RedisKey (refer to feast.storage.RedisKeyV2) - // - value: Redis hashmap - // - Store_REDIS Store_StoreType = 1 - Store_REDIS_CLUSTER Store_StoreType = 4 -) - -// Enum value maps for Store_StoreType. -var ( - Store_StoreType_name = map[int32]string{ - 0: "INVALID", - 1: "REDIS", - 4: "REDIS_CLUSTER", - } - Store_StoreType_value = map[string]int32{ - "INVALID": 0, - "REDIS": 1, - "REDIS_CLUSTER": 4, - } -) - -func (x Store_StoreType) Enum() *Store_StoreType { - p := new(Store_StoreType) - *p = x - return p -} - -func (x Store_StoreType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Store_StoreType) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_Store_proto_enumTypes[0].Descriptor() -} - -func (Store_StoreType) Type() protoreflect.EnumType { - return &file_feast_core_Store_proto_enumTypes[0] -} - -func (x Store_StoreType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Store_StoreType.Descriptor instead. -func (Store_StoreType) EnumDescriptor() ([]byte, []int) { - return file_feast_core_Store_proto_rawDescGZIP(), []int{0, 0} -} - -// Optional. Priority of nodes when reading from cluster -type Store_RedisClusterConfig_ReadFrom int32 - -const ( - Store_RedisClusterConfig_MASTER Store_RedisClusterConfig_ReadFrom = 0 - Store_RedisClusterConfig_MASTER_PREFERRED Store_RedisClusterConfig_ReadFrom = 1 - Store_RedisClusterConfig_REPLICA Store_RedisClusterConfig_ReadFrom = 2 - Store_RedisClusterConfig_REPLICA_PREFERRED Store_RedisClusterConfig_ReadFrom = 3 -) - -// Enum value maps for Store_RedisClusterConfig_ReadFrom. -var ( - Store_RedisClusterConfig_ReadFrom_name = map[int32]string{ - 0: "MASTER", - 1: "MASTER_PREFERRED", - 2: "REPLICA", - 3: "REPLICA_PREFERRED", - } - Store_RedisClusterConfig_ReadFrom_value = map[string]int32{ - "MASTER": 0, - "MASTER_PREFERRED": 1, - "REPLICA": 2, - "REPLICA_PREFERRED": 3, - } -) - -func (x Store_RedisClusterConfig_ReadFrom) Enum() *Store_RedisClusterConfig_ReadFrom { - p := new(Store_RedisClusterConfig_ReadFrom) - *p = x - return p -} - -func (x Store_RedisClusterConfig_ReadFrom) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Store_RedisClusterConfig_ReadFrom) Descriptor() protoreflect.EnumDescriptor { - return file_feast_core_Store_proto_enumTypes[1].Descriptor() -} - -func (Store_RedisClusterConfig_ReadFrom) Type() protoreflect.EnumType { - return &file_feast_core_Store_proto_enumTypes[1] -} - -func (x Store_RedisClusterConfig_ReadFrom) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Store_RedisClusterConfig_ReadFrom.Descriptor instead. -func (Store_RedisClusterConfig_ReadFrom) EnumDescriptor() ([]byte, []int) { - return file_feast_core_Store_proto_rawDescGZIP(), []int{0, 1, 0} -} - -// Store provides a location where Feast reads and writes feature values. -// Feature values will be written to the Store in the form of FeatureRow elements. -// The way FeatureRow is encoded and decoded when it is written to and read from -// the Store depends on the type of the Store. -// -type Store struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the store. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Type of store. - Type Store_StoreType `protobuf:"varint,2,opt,name=type,proto3,enum=feast.core.Store_StoreType" json:"type,omitempty"` - // Feature sets to subscribe to. - Subscriptions []*Store_Subscription `protobuf:"bytes,4,rep,name=subscriptions,proto3" json:"subscriptions,omitempty"` - // Configuration to connect to the store. Required. - // - // Types that are assignable to Config: - // *Store_RedisConfig_ - // *Store_RedisClusterConfig_ - Config isStore_Config `protobuf_oneof:"config"` -} - -func (x *Store) Reset() { - *x = Store{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Store_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Store) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Store) ProtoMessage() {} - -func (x *Store) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Store_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Store.ProtoReflect.Descriptor instead. -func (*Store) Descriptor() ([]byte, []int) { - return file_feast_core_Store_proto_rawDescGZIP(), []int{0} -} - -func (x *Store) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Store) GetType() Store_StoreType { - if x != nil { - return x.Type - } - return Store_INVALID -} - -func (x *Store) GetSubscriptions() []*Store_Subscription { - if x != nil { - return x.Subscriptions - } - return nil -} - -func (m *Store) GetConfig() isStore_Config { - if m != nil { - return m.Config - } - return nil -} - -func (x *Store) GetRedisConfig() *Store_RedisConfig { - if x, ok := x.GetConfig().(*Store_RedisConfig_); ok { - return x.RedisConfig - } - return nil -} - -func (x *Store) GetRedisClusterConfig() *Store_RedisClusterConfig { - if x, ok := x.GetConfig().(*Store_RedisClusterConfig_); ok { - return x.RedisClusterConfig - } - return nil -} - -type isStore_Config interface { - isStore_Config() -} - -type Store_RedisConfig_ struct { - RedisConfig *Store_RedisConfig `protobuf:"bytes,11,opt,name=redis_config,json=redisConfig,proto3,oneof"` -} - -type Store_RedisClusterConfig_ struct { - RedisClusterConfig *Store_RedisClusterConfig `protobuf:"bytes,14,opt,name=redis_cluster_config,json=redisClusterConfig,proto3,oneof"` -} - -func (*Store_RedisConfig_) isStore_Config() {} - -func (*Store_RedisClusterConfig_) isStore_Config() {} - -type Store_RedisConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - Port int32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` - // Optional. The number of milliseconds to wait before retrying failed Redis connection. - // By default, Feast uses exponential backoff policy and "initial_backoff_ms" sets the initial wait duration. - InitialBackoffMs int32 `protobuf:"varint,3,opt,name=initial_backoff_ms,json=initialBackoffMs,proto3" json:"initial_backoff_ms,omitempty"` - // Optional. Maximum total number of retries for connecting to Redis. Default to zero retries. - MaxRetries int32 `protobuf:"varint,4,opt,name=max_retries,json=maxRetries,proto3" json:"max_retries,omitempty"` - // Optional. How often flush data to redis - FlushFrequencySeconds int32 `protobuf:"varint,5,opt,name=flush_frequency_seconds,json=flushFrequencySeconds,proto3" json:"flush_frequency_seconds,omitempty"` - // Optional. Connect over SSL. - Ssl bool `protobuf:"varint,6,opt,name=ssl,proto3" json:"ssl,omitempty"` -} - -func (x *Store_RedisConfig) Reset() { - *x = Store_RedisConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Store_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Store_RedisConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Store_RedisConfig) ProtoMessage() {} - -func (x *Store_RedisConfig) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Store_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Store_RedisConfig.ProtoReflect.Descriptor instead. -func (*Store_RedisConfig) Descriptor() ([]byte, []int) { - return file_feast_core_Store_proto_rawDescGZIP(), []int{0, 0} -} - -func (x *Store_RedisConfig) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *Store_RedisConfig) GetPort() int32 { - if x != nil { - return x.Port - } - return 0 -} - -func (x *Store_RedisConfig) GetInitialBackoffMs() int32 { - if x != nil { - return x.InitialBackoffMs - } - return 0 -} - -func (x *Store_RedisConfig) GetMaxRetries() int32 { - if x != nil { - return x.MaxRetries - } - return 0 -} - -func (x *Store_RedisConfig) GetFlushFrequencySeconds() int32 { - if x != nil { - return x.FlushFrequencySeconds - } - return 0 -} - -func (x *Store_RedisConfig) GetSsl() bool { - if x != nil { - return x.Ssl - } - return false -} - -type Store_RedisClusterConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of Redis Uri for all the nodes in Redis Cluster, comma separated. Eg. host1:6379, host2:6379 - ConnectionString string `protobuf:"bytes,1,opt,name=connection_string,json=connectionString,proto3" json:"connection_string,omitempty"` - InitialBackoffMs int32 `protobuf:"varint,2,opt,name=initial_backoff_ms,json=initialBackoffMs,proto3" json:"initial_backoff_ms,omitempty"` - MaxRetries int32 `protobuf:"varint,3,opt,name=max_retries,json=maxRetries,proto3" json:"max_retries,omitempty"` - // Optional. How often flush data to redis - FlushFrequencySeconds int32 `protobuf:"varint,4,opt,name=flush_frequency_seconds,json=flushFrequencySeconds,proto3" json:"flush_frequency_seconds,omitempty"` - // Optional. Append a prefix to the Redis Key - KeyPrefix string `protobuf:"bytes,5,opt,name=key_prefix,json=keyPrefix,proto3" json:"key_prefix,omitempty"` - // Optional. Enable fallback to another key prefix if the original key is not present. - // Useful for migrating key prefix without re-ingestion. Disabled by default. - EnableFallback bool `protobuf:"varint,6,opt,name=enable_fallback,json=enableFallback,proto3" json:"enable_fallback,omitempty"` - // Optional. This would be the fallback prefix to use if enable_fallback is true. - FallbackPrefix string `protobuf:"bytes,7,opt,name=fallback_prefix,json=fallbackPrefix,proto3" json:"fallback_prefix,omitempty"` - ReadFrom Store_RedisClusterConfig_ReadFrom `protobuf:"varint,8,opt,name=read_from,json=readFrom,proto3,enum=feast.core.Store_RedisClusterConfig_ReadFrom" json:"read_from,omitempty"` -} - -func (x *Store_RedisClusterConfig) Reset() { - *x = Store_RedisClusterConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Store_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Store_RedisClusterConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Store_RedisClusterConfig) ProtoMessage() {} - -func (x *Store_RedisClusterConfig) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Store_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Store_RedisClusterConfig.ProtoReflect.Descriptor instead. -func (*Store_RedisClusterConfig) Descriptor() ([]byte, []int) { - return file_feast_core_Store_proto_rawDescGZIP(), []int{0, 1} -} - -func (x *Store_RedisClusterConfig) GetConnectionString() string { - if x != nil { - return x.ConnectionString - } - return "" -} - -func (x *Store_RedisClusterConfig) GetInitialBackoffMs() int32 { - if x != nil { - return x.InitialBackoffMs - } - return 0 -} - -func (x *Store_RedisClusterConfig) GetMaxRetries() int32 { - if x != nil { - return x.MaxRetries - } - return 0 -} - -func (x *Store_RedisClusterConfig) GetFlushFrequencySeconds() int32 { - if x != nil { - return x.FlushFrequencySeconds - } - return 0 -} - -func (x *Store_RedisClusterConfig) GetKeyPrefix() string { - if x != nil { - return x.KeyPrefix - } - return "" -} - -func (x *Store_RedisClusterConfig) GetEnableFallback() bool { - if x != nil { - return x.EnableFallback - } - return false -} - -func (x *Store_RedisClusterConfig) GetFallbackPrefix() string { - if x != nil { - return x.FallbackPrefix - } - return "" -} - -func (x *Store_RedisClusterConfig) GetReadFrom() Store_RedisClusterConfig_ReadFrom { - if x != nil { - return x.ReadFrom - } - return Store_RedisClusterConfig_MASTER -} - -type Store_Subscription struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of project that the feature sets belongs to. This can be one of - // - [project_name] - // - * - // If an asterisk is provided, filtering on projects will be disabled. All projects will - // be matched. It is NOT possible to provide an asterisk with a string in order to do - // pattern matching. - Project string `protobuf:"bytes,3,opt,name=project,proto3" json:"project,omitempty"` - // Name of the desired feature set. Asterisks can be used as wildcards in the name. - // Matching on names is only permitted if a specific project is defined. It is disallowed - // If the project name is set to "*" - // e.g. - // - * can be used to match all feature sets - // - my-feature-set* can be used to match all features prefixed by "my-feature-set" - // - my-feature-set-6 can be used to select a single feature set - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // All matches with exclude enabled will be filtered out instead of added - Exclude bool `protobuf:"varint,4,opt,name=exclude,proto3" json:"exclude,omitempty"` -} - -func (x *Store_Subscription) Reset() { - *x = Store_Subscription{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_core_Store_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Store_Subscription) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Store_Subscription) ProtoMessage() {} - -func (x *Store_Subscription) ProtoReflect() protoreflect.Message { - mi := &file_feast_core_Store_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Store_Subscription.ProtoReflect.Descriptor instead. -func (*Store_Subscription) Descriptor() ([]byte, []int) { - return file_feast_core_Store_proto_rawDescGZIP(), []int{0, 2} -} - -func (x *Store_Subscription) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *Store_Subscription) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Store_Subscription) GetExclude() bool { - if x != nil { - return x.Exclude - } - return false -} - -var File_feast_core_Store_proto protoreflect.FileDescriptor - -var file_feast_core_Store_proto_rawDesc = []byte{ - 0x0a, 0x16, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x22, 0x93, 0x09, 0x0a, 0x05, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x1b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x0c, 0x72, 0x65, 0x64, - 0x69, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, - 0x52, 0x0b, 0x72, 0x65, 0x64, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x58, 0x0a, - 0x14, 0x72, 0x65, 0x64, 0x69, 0x73, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x52, - 0x65, 0x64, 0x69, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x64, 0x69, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xce, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x64, 0x69, - 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, - 0x2c, 0x0a, 0x12, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6f, - 0x66, 0x66, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x4d, 0x73, 0x12, 0x1f, 0x0a, - 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x36, - 0x0a, 0x17, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x79, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x15, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x73, 0x6c, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x03, 0x73, 0x73, 0x6c, 0x1a, 0xd7, 0x03, 0x0a, 0x12, 0x52, 0x65, 0x64, - 0x69, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x2c, 0x0a, 0x12, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x5f, - 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, - 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x4d, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, - 0x78, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0a, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x66, - 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x66, 0x6c, - 0x75, 0x73, 0x68, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x50, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x66, 0x61, 0x6c, - 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x27, 0x0a, 0x0f, 0x66, - 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x12, 0x4a, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x66, 0x72, 0x6f, - 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, - 0x61, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x46, 0x72, 0x6f, 0x6d, - 0x22, 0x50, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x0a, 0x0a, 0x06, - 0x4d, 0x41, 0x53, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x41, 0x53, 0x54, - 0x45, 0x52, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x52, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, - 0x0a, 0x07, 0x52, 0x45, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x52, - 0x45, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x52, 0x45, 0x44, - 0x10, 0x03, 0x1a, 0x5c, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, - 0x22, 0x4e, 0x0a, 0x09, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, - 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, - 0x44, 0x49, 0x53, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x43, - 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x10, 0x04, 0x22, 0x04, 0x08, 0x02, 0x10, 0x02, 0x22, 0x04, - 0x08, 0x03, 0x10, 0x03, 0x22, 0x04, 0x08, 0x0c, 0x10, 0x0c, 0x22, 0x04, 0x08, 0x0d, 0x10, 0x0d, - 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x53, 0x0a, 0x10, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x0a, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, - 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_core_Store_proto_rawDescOnce sync.Once - file_feast_core_Store_proto_rawDescData = file_feast_core_Store_proto_rawDesc -) - -func file_feast_core_Store_proto_rawDescGZIP() []byte { - file_feast_core_Store_proto_rawDescOnce.Do(func() { - file_feast_core_Store_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_core_Store_proto_rawDescData) - }) - return file_feast_core_Store_proto_rawDescData -} - -var file_feast_core_Store_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_feast_core_Store_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_feast_core_Store_proto_goTypes = []interface{}{ - (Store_StoreType)(0), // 0: feast.core.Store.StoreType - (Store_RedisClusterConfig_ReadFrom)(0), // 1: feast.core.Store.RedisClusterConfig.ReadFrom - (*Store)(nil), // 2: feast.core.Store - (*Store_RedisConfig)(nil), // 3: feast.core.Store.RedisConfig - (*Store_RedisClusterConfig)(nil), // 4: feast.core.Store.RedisClusterConfig - (*Store_Subscription)(nil), // 5: feast.core.Store.Subscription -} -var file_feast_core_Store_proto_depIdxs = []int32{ - 0, // 0: feast.core.Store.type:type_name -> feast.core.Store.StoreType - 5, // 1: feast.core.Store.subscriptions:type_name -> feast.core.Store.Subscription - 3, // 2: feast.core.Store.redis_config:type_name -> feast.core.Store.RedisConfig - 4, // 3: feast.core.Store.redis_cluster_config:type_name -> feast.core.Store.RedisClusterConfig - 1, // 4: feast.core.Store.RedisClusterConfig.read_from:type_name -> feast.core.Store.RedisClusterConfig.ReadFrom - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_feast_core_Store_proto_init() } -func file_feast_core_Store_proto_init() { - if File_feast_core_Store_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_core_Store_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Store); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_Store_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Store_RedisConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_Store_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Store_RedisClusterConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_core_Store_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Store_Subscription); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_core_Store_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Store_RedisConfig_)(nil), - (*Store_RedisClusterConfig_)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_core_Store_proto_rawDesc, - NumEnums: 2, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_core_Store_proto_goTypes, - DependencyIndexes: file_feast_core_Store_proto_depIdxs, - EnumInfos: file_feast_core_Store_proto_enumTypes, - MessageInfos: file_feast_core_Store_proto_msgTypes, - }.Build() - File_feast_core_Store_proto = out.File - file_feast_core_Store_proto_rawDesc = nil - file_feast_core_Store_proto_goTypes = nil - file_feast_core_Store_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/serving/ServingService.pb.go b/sdk/go/protos/feast/serving/ServingService.pb.go deleted file mode 100644 index 3527c6688ea..00000000000 --- a/sdk/go/protos/feast/serving/ServingService.pb.go +++ /dev/null @@ -1,1180 +0,0 @@ -// -// Copyright 2018 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/serving/ServingService.proto - -package serving - -import ( - context "context" - types "github.com/feast-dev/feast/sdk/go/protos/feast/types" - 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" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type FieldStatus int32 - -const ( - // Status is unset for this field. - FieldStatus_INVALID FieldStatus = 0 - // Field value is present for this field and age is within max age. - FieldStatus_PRESENT FieldStatus = 1 - // Values could be found for entity key and age is within max age, but - // this field value is assigned a value on ingestion into feast. - FieldStatus_NULL_VALUE FieldStatus = 2 - // Entity key did not return any values as they do not exist in Feast. - // This could suggest that the feature values have not yet been ingested - // into feast or the ingestion failed. - FieldStatus_NOT_FOUND FieldStatus = 3 - // Values could be found for entity key, but field values are outside the maximum - // allowable range. - FieldStatus_OUTSIDE_MAX_AGE FieldStatus = 4 -) - -// Enum value maps for FieldStatus. -var ( - FieldStatus_name = map[int32]string{ - 0: "INVALID", - 1: "PRESENT", - 2: "NULL_VALUE", - 3: "NOT_FOUND", - 4: "OUTSIDE_MAX_AGE", - } - FieldStatus_value = map[string]int32{ - "INVALID": 0, - "PRESENT": 1, - "NULL_VALUE": 2, - "NOT_FOUND": 3, - "OUTSIDE_MAX_AGE": 4, - } -) - -func (x FieldStatus) Enum() *FieldStatus { - p := new(FieldStatus) - *p = x - return p -} - -func (x FieldStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (FieldStatus) Descriptor() protoreflect.EnumDescriptor { - return file_feast_serving_ServingService_proto_enumTypes[0].Descriptor() -} - -func (FieldStatus) Type() protoreflect.EnumType { - return &file_feast_serving_ServingService_proto_enumTypes[0] -} - -func (x FieldStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use FieldStatus.Descriptor instead. -func (FieldStatus) EnumDescriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{0} -} - -type GetFeastServingInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetFeastServingInfoRequest) Reset() { - *x = GetFeastServingInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetFeastServingInfoRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetFeastServingInfoRequest) ProtoMessage() {} - -func (x *GetFeastServingInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetFeastServingInfoRequest.ProtoReflect.Descriptor instead. -func (*GetFeastServingInfoRequest) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{0} -} - -type GetFeastServingInfoResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Feast version of this serving deployment. - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *GetFeastServingInfoResponse) Reset() { - *x = GetFeastServingInfoResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetFeastServingInfoResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetFeastServingInfoResponse) ProtoMessage() {} - -func (x *GetFeastServingInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetFeastServingInfoResponse.ProtoReflect.Descriptor instead. -func (*GetFeastServingInfoResponse) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{1} -} - -func (x *GetFeastServingInfoResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type FeatureReferenceV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the Feature View to retrieve the feature from. - FeatureViewName string `protobuf:"bytes,1,opt,name=feature_view_name,json=featureViewName,proto3" json:"feature_view_name,omitempty"` - // Name of the Feature to retrieve the feature from. - FeatureName string `protobuf:"bytes,2,opt,name=feature_name,json=featureName,proto3" json:"feature_name,omitempty"` -} - -func (x *FeatureReferenceV2) Reset() { - *x = FeatureReferenceV2{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureReferenceV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureReferenceV2) ProtoMessage() {} - -func (x *FeatureReferenceV2) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureReferenceV2.ProtoReflect.Descriptor instead. -func (*FeatureReferenceV2) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{2} -} - -func (x *FeatureReferenceV2) GetFeatureViewName() string { - if x != nil { - return x.FeatureViewName - } - return "" -} - -func (x *FeatureReferenceV2) GetFeatureName() string { - if x != nil { - return x.FeatureName - } - return "" -} - -// ToDo (oleksii): remove this message (since it's not used) and move EntityRow on package level -type GetOnlineFeaturesRequestV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of features that are being retrieved - Features []*FeatureReferenceV2 `protobuf:"bytes,4,rep,name=features,proto3" json:"features,omitempty"` - // List of entity rows, containing entity id and timestamp data. - // Used during retrieval of feature rows and for joining feature - // rows into a final dataset - EntityRows []*GetOnlineFeaturesRequestV2_EntityRow `protobuf:"bytes,2,rep,name=entity_rows,json=entityRows,proto3" json:"entity_rows,omitempty"` - // Optional field to specify project name override. If specified, uses the - // given project for retrieval. Overrides the projects specified in - // Feature References if both are specified. - Project string `protobuf:"bytes,5,opt,name=project,proto3" json:"project,omitempty"` -} - -func (x *GetOnlineFeaturesRequestV2) Reset() { - *x = GetOnlineFeaturesRequestV2{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOnlineFeaturesRequestV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOnlineFeaturesRequestV2) ProtoMessage() {} - -func (x *GetOnlineFeaturesRequestV2) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOnlineFeaturesRequestV2.ProtoReflect.Descriptor instead. -func (*GetOnlineFeaturesRequestV2) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{3} -} - -func (x *GetOnlineFeaturesRequestV2) GetFeatures() []*FeatureReferenceV2 { - if x != nil { - return x.Features - } - return nil -} - -func (x *GetOnlineFeaturesRequestV2) GetEntityRows() []*GetOnlineFeaturesRequestV2_EntityRow { - if x != nil { - return x.EntityRows - } - return nil -} - -func (x *GetOnlineFeaturesRequestV2) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -// In JSON "val" field can be omitted -type FeatureList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []string `protobuf:"bytes,1,rep,name=val,proto3" json:"val,omitempty"` -} - -func (x *FeatureList) Reset() { - *x = FeatureList{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureList) ProtoMessage() {} - -func (x *FeatureList) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureList.ProtoReflect.Descriptor instead. -func (*FeatureList) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{4} -} - -func (x *FeatureList) GetVal() []string { - if x != nil { - return x.Val - } - return nil -} - -type GetOnlineFeaturesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Kind: - // *GetOnlineFeaturesRequest_FeatureService - // *GetOnlineFeaturesRequest_Features - Kind isGetOnlineFeaturesRequest_Kind `protobuf_oneof:"kind"` - // The entity data is specified in a columnar format - // A map of entity name -> list of values - Entities map[string]*types.RepeatedValue `protobuf:"bytes,3,rep,name=entities,proto3" json:"entities,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - FullFeatureNames bool `protobuf:"varint,4,opt,name=full_feature_names,json=fullFeatureNames,proto3" json:"full_feature_names,omitempty"` - // Context for OnDemand Feature Transformation - // (was moved to dedicated parameter to avoid unnecessary separation logic on serving side) - // A map of variable name -> list of values - RequestContext map[string]*types.RepeatedValue `protobuf:"bytes,5,rep,name=request_context,json=requestContext,proto3" json:"request_context,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *GetOnlineFeaturesRequest) Reset() { - *x = GetOnlineFeaturesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOnlineFeaturesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOnlineFeaturesRequest) ProtoMessage() {} - -func (x *GetOnlineFeaturesRequest) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOnlineFeaturesRequest.ProtoReflect.Descriptor instead. -func (*GetOnlineFeaturesRequest) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{5} -} - -func (m *GetOnlineFeaturesRequest) GetKind() isGetOnlineFeaturesRequest_Kind { - if m != nil { - return m.Kind - } - return nil -} - -func (x *GetOnlineFeaturesRequest) GetFeatureService() string { - if x, ok := x.GetKind().(*GetOnlineFeaturesRequest_FeatureService); ok { - return x.FeatureService - } - return "" -} - -func (x *GetOnlineFeaturesRequest) GetFeatures() *FeatureList { - if x, ok := x.GetKind().(*GetOnlineFeaturesRequest_Features); ok { - return x.Features - } - return nil -} - -func (x *GetOnlineFeaturesRequest) GetEntities() map[string]*types.RepeatedValue { - if x != nil { - return x.Entities - } - return nil -} - -func (x *GetOnlineFeaturesRequest) GetFullFeatureNames() bool { - if x != nil { - return x.FullFeatureNames - } - return false -} - -func (x *GetOnlineFeaturesRequest) GetRequestContext() map[string]*types.RepeatedValue { - if x != nil { - return x.RequestContext - } - return nil -} - -type isGetOnlineFeaturesRequest_Kind interface { - isGetOnlineFeaturesRequest_Kind() -} - -type GetOnlineFeaturesRequest_FeatureService struct { - FeatureService string `protobuf:"bytes,1,opt,name=feature_service,json=featureService,proto3,oneof"` -} - -type GetOnlineFeaturesRequest_Features struct { - Features *FeatureList `protobuf:"bytes,2,opt,name=features,proto3,oneof"` -} - -func (*GetOnlineFeaturesRequest_FeatureService) isGetOnlineFeaturesRequest_Kind() {} - -func (*GetOnlineFeaturesRequest_Features) isGetOnlineFeaturesRequest_Kind() {} - -type GetOnlineFeaturesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Metadata *GetOnlineFeaturesResponseMetadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` - // Length of "results" array should match length of requested features. - // We also preserve the same order of features here as in metadata.feature_names - Results []*GetOnlineFeaturesResponse_FeatureVector `protobuf:"bytes,2,rep,name=results,proto3" json:"results,omitempty"` -} - -func (x *GetOnlineFeaturesResponse) Reset() { - *x = GetOnlineFeaturesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOnlineFeaturesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOnlineFeaturesResponse) ProtoMessage() {} - -func (x *GetOnlineFeaturesResponse) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOnlineFeaturesResponse.ProtoReflect.Descriptor instead. -func (*GetOnlineFeaturesResponse) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{6} -} - -func (x *GetOnlineFeaturesResponse) GetMetadata() *GetOnlineFeaturesResponseMetadata { - if x != nil { - return x.Metadata - } - return nil -} - -func (x *GetOnlineFeaturesResponse) GetResults() []*GetOnlineFeaturesResponse_FeatureVector { - if x != nil { - return x.Results - } - return nil -} - -type GetOnlineFeaturesResponseMetadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - FeatureNames *FeatureList `protobuf:"bytes,1,opt,name=feature_names,json=featureNames,proto3" json:"feature_names,omitempty"` -} - -func (x *GetOnlineFeaturesResponseMetadata) Reset() { - *x = GetOnlineFeaturesResponseMetadata{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOnlineFeaturesResponseMetadata) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOnlineFeaturesResponseMetadata) ProtoMessage() {} - -func (x *GetOnlineFeaturesResponseMetadata) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOnlineFeaturesResponseMetadata.ProtoReflect.Descriptor instead. -func (*GetOnlineFeaturesResponseMetadata) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{7} -} - -func (x *GetOnlineFeaturesResponseMetadata) GetFeatureNames() *FeatureList { - if x != nil { - return x.FeatureNames - } - return nil -} - -type GetOnlineFeaturesRequestV2_EntityRow struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request timestamp of this row. This value will be used, - // together with maxAge, to determine feature staleness. - Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - // Map containing mapping of entity name to entity value. - Fields map[string]*types.Value `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *GetOnlineFeaturesRequestV2_EntityRow) Reset() { - *x = GetOnlineFeaturesRequestV2_EntityRow{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOnlineFeaturesRequestV2_EntityRow) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOnlineFeaturesRequestV2_EntityRow) ProtoMessage() {} - -func (x *GetOnlineFeaturesRequestV2_EntityRow) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOnlineFeaturesRequestV2_EntityRow.ProtoReflect.Descriptor instead. -func (*GetOnlineFeaturesRequestV2_EntityRow) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{3, 0} -} - -func (x *GetOnlineFeaturesRequestV2_EntityRow) GetTimestamp() *timestamppb.Timestamp { - if x != nil { - return x.Timestamp - } - return nil -} - -func (x *GetOnlineFeaturesRequestV2_EntityRow) GetFields() map[string]*types.Value { - if x != nil { - return x.Fields - } - return nil -} - -type GetOnlineFeaturesResponse_FeatureVector struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Values []*types.Value `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` - Statuses []FieldStatus `protobuf:"varint,2,rep,packed,name=statuses,proto3,enum=feast.serving.FieldStatus" json:"statuses,omitempty"` - EventTimestamps []*timestamppb.Timestamp `protobuf:"bytes,3,rep,name=event_timestamps,json=eventTimestamps,proto3" json:"event_timestamps,omitempty"` -} - -func (x *GetOnlineFeaturesResponse_FeatureVector) Reset() { - *x = GetOnlineFeaturesResponse_FeatureVector{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_serving_ServingService_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOnlineFeaturesResponse_FeatureVector) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOnlineFeaturesResponse_FeatureVector) ProtoMessage() {} - -func (x *GetOnlineFeaturesResponse_FeatureVector) ProtoReflect() protoreflect.Message { - mi := &file_feast_serving_ServingService_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOnlineFeaturesResponse_FeatureVector.ProtoReflect.Descriptor instead. -func (*GetOnlineFeaturesResponse_FeatureVector) Descriptor() ([]byte, []int) { - return file_feast_serving_ServingService_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *GetOnlineFeaturesResponse_FeatureVector) GetValues() []*types.Value { - if x != nil { - return x.Values - } - return nil -} - -func (x *GetOnlineFeaturesResponse_FeatureVector) GetStatuses() []FieldStatus { - if x != nil { - return x.Statuses - } - return nil -} - -func (x *GetOnlineFeaturesResponse_FeatureVector) GetEventTimestamps() []*timestamppb.Timestamp { - if x != nil { - return x.EventTimestamps - } - return nil -} - -var File_feast_serving_ServingService_proto protoreflect.FileDescriptor - -var file_feast_serving_ServingService_proto_rawDesc = []byte{ - 0x0a, 0x22, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2f, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x6e, 0x67, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1c, 0x0a, - 0x1a, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x37, 0x0a, 0x1b, 0x47, - 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x63, 0x0a, 0x12, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x56, 0x69, - 0x65, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xbb, 0x03, 0x0a, 0x1a, 0x47, 0x65, - 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x12, 0x3d, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x52, 0x08, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x54, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, - 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, - 0x77, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x1a, 0xed, 0x01, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x6f, 0x77, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x57, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3f, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, - 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x32, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x52, 0x6f, 0x77, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x4d, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1f, 0x0a, 0x0b, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0xa6, 0x04, 0x0a, 0x18, 0x47, 0x65, 0x74, - 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x38, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x6e, 0x67, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, - 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, - 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, - 0x12, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x66, 0x75, 0x6c, 0x6c, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x1a, 0x57, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5d, 0x0a, 0x13, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x22, 0xf8, 0x02, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, - 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, - 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, - 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, - 0xba, 0x01, 0x0a, 0x0d, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x56, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x12, 0x2a, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x36, 0x0a, - 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, - 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x10, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x22, 0x64, 0x0a, 0x21, - 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x3f, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x2a, 0x5b, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0b, - 0x0a, 0x07, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, - 0x55, 0x4c, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4e, - 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, - 0x54, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x4d, 0x41, 0x58, 0x5f, 0x41, 0x47, 0x45, 0x10, 0x04, 0x32, - 0xe6, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x29, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, - 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x66, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x47, - 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x5e, 0x0a, 0x13, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x42, - 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x41, 0x50, 0x49, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, - 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_serving_ServingService_proto_rawDescOnce sync.Once - file_feast_serving_ServingService_proto_rawDescData = file_feast_serving_ServingService_proto_rawDesc -) - -func file_feast_serving_ServingService_proto_rawDescGZIP() []byte { - file_feast_serving_ServingService_proto_rawDescOnce.Do(func() { - file_feast_serving_ServingService_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_serving_ServingService_proto_rawDescData) - }) - return file_feast_serving_ServingService_proto_rawDescData -} - -var file_feast_serving_ServingService_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_feast_serving_ServingService_proto_msgTypes = make([]protoimpl.MessageInfo, 13) -var file_feast_serving_ServingService_proto_goTypes = []interface{}{ - (FieldStatus)(0), // 0: feast.serving.FieldStatus - (*GetFeastServingInfoRequest)(nil), // 1: feast.serving.GetFeastServingInfoRequest - (*GetFeastServingInfoResponse)(nil), // 2: feast.serving.GetFeastServingInfoResponse - (*FeatureReferenceV2)(nil), // 3: feast.serving.FeatureReferenceV2 - (*GetOnlineFeaturesRequestV2)(nil), // 4: feast.serving.GetOnlineFeaturesRequestV2 - (*FeatureList)(nil), // 5: feast.serving.FeatureList - (*GetOnlineFeaturesRequest)(nil), // 6: feast.serving.GetOnlineFeaturesRequest - (*GetOnlineFeaturesResponse)(nil), // 7: feast.serving.GetOnlineFeaturesResponse - (*GetOnlineFeaturesResponseMetadata)(nil), // 8: feast.serving.GetOnlineFeaturesResponseMetadata - (*GetOnlineFeaturesRequestV2_EntityRow)(nil), // 9: feast.serving.GetOnlineFeaturesRequestV2.EntityRow - nil, // 10: feast.serving.GetOnlineFeaturesRequestV2.EntityRow.FieldsEntry - nil, // 11: feast.serving.GetOnlineFeaturesRequest.EntitiesEntry - nil, // 12: feast.serving.GetOnlineFeaturesRequest.RequestContextEntry - (*GetOnlineFeaturesResponse_FeatureVector)(nil), // 13: feast.serving.GetOnlineFeaturesResponse.FeatureVector - (*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp - (*types.Value)(nil), // 15: feast.types.Value - (*types.RepeatedValue)(nil), // 16: feast.types.RepeatedValue -} -var file_feast_serving_ServingService_proto_depIdxs = []int32{ - 3, // 0: feast.serving.GetOnlineFeaturesRequestV2.features:type_name -> feast.serving.FeatureReferenceV2 - 9, // 1: feast.serving.GetOnlineFeaturesRequestV2.entity_rows:type_name -> feast.serving.GetOnlineFeaturesRequestV2.EntityRow - 5, // 2: feast.serving.GetOnlineFeaturesRequest.features:type_name -> feast.serving.FeatureList - 11, // 3: feast.serving.GetOnlineFeaturesRequest.entities:type_name -> feast.serving.GetOnlineFeaturesRequest.EntitiesEntry - 12, // 4: feast.serving.GetOnlineFeaturesRequest.request_context:type_name -> feast.serving.GetOnlineFeaturesRequest.RequestContextEntry - 8, // 5: feast.serving.GetOnlineFeaturesResponse.metadata:type_name -> feast.serving.GetOnlineFeaturesResponseMetadata - 13, // 6: feast.serving.GetOnlineFeaturesResponse.results:type_name -> feast.serving.GetOnlineFeaturesResponse.FeatureVector - 5, // 7: feast.serving.GetOnlineFeaturesResponseMetadata.feature_names:type_name -> feast.serving.FeatureList - 14, // 8: feast.serving.GetOnlineFeaturesRequestV2.EntityRow.timestamp:type_name -> google.protobuf.Timestamp - 10, // 9: feast.serving.GetOnlineFeaturesRequestV2.EntityRow.fields:type_name -> feast.serving.GetOnlineFeaturesRequestV2.EntityRow.FieldsEntry - 15, // 10: feast.serving.GetOnlineFeaturesRequestV2.EntityRow.FieldsEntry.value:type_name -> feast.types.Value - 16, // 11: feast.serving.GetOnlineFeaturesRequest.EntitiesEntry.value:type_name -> feast.types.RepeatedValue - 16, // 12: feast.serving.GetOnlineFeaturesRequest.RequestContextEntry.value:type_name -> feast.types.RepeatedValue - 15, // 13: feast.serving.GetOnlineFeaturesResponse.FeatureVector.values:type_name -> feast.types.Value - 0, // 14: feast.serving.GetOnlineFeaturesResponse.FeatureVector.statuses:type_name -> feast.serving.FieldStatus - 14, // 15: feast.serving.GetOnlineFeaturesResponse.FeatureVector.event_timestamps:type_name -> google.protobuf.Timestamp - 1, // 16: feast.serving.ServingService.GetFeastServingInfo:input_type -> feast.serving.GetFeastServingInfoRequest - 6, // 17: feast.serving.ServingService.GetOnlineFeatures:input_type -> feast.serving.GetOnlineFeaturesRequest - 2, // 18: feast.serving.ServingService.GetFeastServingInfo:output_type -> feast.serving.GetFeastServingInfoResponse - 7, // 19: feast.serving.ServingService.GetOnlineFeatures:output_type -> feast.serving.GetOnlineFeaturesResponse - 18, // [18:20] is the sub-list for method output_type - 16, // [16:18] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name -} - -func init() { file_feast_serving_ServingService_proto_init() } -func file_feast_serving_ServingService_proto_init() { - if File_feast_serving_ServingService_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_serving_ServingService_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeastServingInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetFeastServingInfoResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureReferenceV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOnlineFeaturesRequestV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOnlineFeaturesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOnlineFeaturesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOnlineFeaturesResponseMetadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOnlineFeaturesRequestV2_EntityRow); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_serving_ServingService_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOnlineFeaturesResponse_FeatureVector); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_serving_ServingService_proto_msgTypes[5].OneofWrappers = []interface{}{ - (*GetOnlineFeaturesRequest_FeatureService)(nil), - (*GetOnlineFeaturesRequest_Features)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_serving_ServingService_proto_rawDesc, - NumEnums: 1, - NumMessages: 13, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_feast_serving_ServingService_proto_goTypes, - DependencyIndexes: file_feast_serving_ServingService_proto_depIdxs, - EnumInfos: file_feast_serving_ServingService_proto_enumTypes, - MessageInfos: file_feast_serving_ServingService_proto_msgTypes, - }.Build() - File_feast_serving_ServingService_proto = out.File - file_feast_serving_ServingService_proto_rawDesc = nil - file_feast_serving_ServingService_proto_goTypes = nil - file_feast_serving_ServingService_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 - -// ServingServiceClient is the client API for ServingService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type ServingServiceClient interface { - // Get information about this Feast serving. - GetFeastServingInfo(ctx context.Context, in *GetFeastServingInfoRequest, opts ...grpc.CallOption) (*GetFeastServingInfoResponse, error) - // Get online features synchronously. - GetOnlineFeatures(ctx context.Context, in *GetOnlineFeaturesRequest, opts ...grpc.CallOption) (*GetOnlineFeaturesResponse, error) -} - -type servingServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewServingServiceClient(cc grpc.ClientConnInterface) ServingServiceClient { - return &servingServiceClient{cc} -} - -func (c *servingServiceClient) GetFeastServingInfo(ctx context.Context, in *GetFeastServingInfoRequest, opts ...grpc.CallOption) (*GetFeastServingInfoResponse, error) { - out := new(GetFeastServingInfoResponse) - err := c.cc.Invoke(ctx, "/feast.serving.ServingService/GetFeastServingInfo", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *servingServiceClient) GetOnlineFeatures(ctx context.Context, in *GetOnlineFeaturesRequest, opts ...grpc.CallOption) (*GetOnlineFeaturesResponse, error) { - out := new(GetOnlineFeaturesResponse) - err := c.cc.Invoke(ctx, "/feast.serving.ServingService/GetOnlineFeatures", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ServingServiceServer is the server API for ServingService service. -type ServingServiceServer interface { - // Get information about this Feast serving. - GetFeastServingInfo(context.Context, *GetFeastServingInfoRequest) (*GetFeastServingInfoResponse, error) - // Get online features synchronously. - GetOnlineFeatures(context.Context, *GetOnlineFeaturesRequest) (*GetOnlineFeaturesResponse, error) -} - -// UnimplementedServingServiceServer can be embedded to have forward compatible implementations. -type UnimplementedServingServiceServer struct { -} - -func (*UnimplementedServingServiceServer) GetFeastServingInfo(context.Context, *GetFeastServingInfoRequest) (*GetFeastServingInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetFeastServingInfo not implemented") -} -func (*UnimplementedServingServiceServer) GetOnlineFeatures(context.Context, *GetOnlineFeaturesRequest) (*GetOnlineFeaturesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetOnlineFeatures not implemented") -} - -func RegisterServingServiceServer(s *grpc.Server, srv ServingServiceServer) { - s.RegisterService(&_ServingService_serviceDesc, srv) -} - -func _ServingService_GetFeastServingInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetFeastServingInfoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ServingServiceServer).GetFeastServingInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.serving.ServingService/GetFeastServingInfo", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServingServiceServer).GetFeastServingInfo(ctx, req.(*GetFeastServingInfoRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ServingService_GetOnlineFeatures_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetOnlineFeaturesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ServingServiceServer).GetOnlineFeatures(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/feast.serving.ServingService/GetOnlineFeatures", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServingServiceServer).GetOnlineFeatures(ctx, req.(*GetOnlineFeaturesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _ServingService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "feast.serving.ServingService", - HandlerType: (*ServingServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetFeastServingInfo", - Handler: _ServingService_GetFeastServingInfo_Handler, - }, - { - MethodName: "GetOnlineFeatures", - Handler: _ServingService_GetOnlineFeatures_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "feast/serving/ServingService.proto", -} diff --git a/sdk/go/protos/feast/storage/Redis.pb.go b/sdk/go/protos/feast/storage/Redis.pb.go deleted file mode 100644 index 35f38ba2a7e..00000000000 --- a/sdk/go/protos/feast/storage/Redis.pb.go +++ /dev/null @@ -1,191 +0,0 @@ -// -// Copyright 2019 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/storage/Redis.proto - -package storage - -import ( - types "github.com/feast-dev/feast/sdk/go/protos/feast/types" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type RedisKeyV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - EntityNames []string `protobuf:"bytes,2,rep,name=entity_names,json=entityNames,proto3" json:"entity_names,omitempty"` - EntityValues []*types.Value `protobuf:"bytes,3,rep,name=entity_values,json=entityValues,proto3" json:"entity_values,omitempty"` -} - -func (x *RedisKeyV2) Reset() { - *x = RedisKeyV2{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_storage_Redis_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RedisKeyV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RedisKeyV2) ProtoMessage() {} - -func (x *RedisKeyV2) ProtoReflect() protoreflect.Message { - mi := &file_feast_storage_Redis_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RedisKeyV2.ProtoReflect.Descriptor instead. -func (*RedisKeyV2) Descriptor() ([]byte, []int) { - return file_feast_storage_Redis_proto_rawDescGZIP(), []int{0} -} - -func (x *RedisKeyV2) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *RedisKeyV2) GetEntityNames() []string { - if x != nil { - return x.EntityNames - } - return nil -} - -func (x *RedisKeyV2) GetEntityValues() []*types.Value { - if x != nil { - return x.EntityValues - } - return nil -} - -var File_feast_storage_Redis_proto protoreflect.FileDescriptor - -var file_feast_storage_Redis_proto_rawDesc = []byte{ - 0x0a, 0x19, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, - 0x52, 0x65, 0x64, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, - 0x0a, 0x52, 0x65, 0x64, 0x69, 0x73, 0x4b, 0x65, 0x79, 0x56, 0x32, 0x12, 0x18, 0x0a, 0x07, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x0d, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x42, 0x59, 0x0a, 0x13, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x0a, 0x52, 0x65, 0x64, 0x69, 0x73, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_storage_Redis_proto_rawDescOnce sync.Once - file_feast_storage_Redis_proto_rawDescData = file_feast_storage_Redis_proto_rawDesc -) - -func file_feast_storage_Redis_proto_rawDescGZIP() []byte { - file_feast_storage_Redis_proto_rawDescOnce.Do(func() { - file_feast_storage_Redis_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_storage_Redis_proto_rawDescData) - }) - return file_feast_storage_Redis_proto_rawDescData -} - -var file_feast_storage_Redis_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_feast_storage_Redis_proto_goTypes = []interface{}{ - (*RedisKeyV2)(nil), // 0: feast.storage.RedisKeyV2 - (*types.Value)(nil), // 1: feast.types.Value -} -var file_feast_storage_Redis_proto_depIdxs = []int32{ - 1, // 0: feast.storage.RedisKeyV2.entity_values:type_name -> feast.types.Value - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_feast_storage_Redis_proto_init() } -func file_feast_storage_Redis_proto_init() { - if File_feast_storage_Redis_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_storage_Redis_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RedisKeyV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_storage_Redis_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_storage_Redis_proto_goTypes, - DependencyIndexes: file_feast_storage_Redis_proto_depIdxs, - MessageInfos: file_feast_storage_Redis_proto_msgTypes, - }.Build() - File_feast_storage_Redis_proto = out.File - file_feast_storage_Redis_proto_rawDesc = nil - file_feast_storage_Redis_proto_goTypes = nil - file_feast_storage_Redis_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/types/FeatureRow.pb.go b/sdk/go/protos/feast/types/FeatureRow.pb.go deleted file mode 100644 index f6fe6bfa424..00000000000 --- a/sdk/go/protos/feast/types/FeatureRow.pb.go +++ /dev/null @@ -1,219 +0,0 @@ -// -// Copyright 2018 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.10.0 -// source: feast/types/FeatureRow.proto - -package types - -import ( - proto "github.com/golang/protobuf/proto" - timestamp "github.com/golang/protobuf/ptypes/timestamp" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 FeatureRow struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Fields in the feature row. - Fields []*Field `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty"` - // Timestamp of the feature row. While the actual definition of this timestamp may vary - // depending on the upstream feature creation pipelines, this is the timestamp that Feast - // will use to perform joins, determine latest values, and coalesce rows. - EventTimestamp *timestamp.Timestamp `protobuf:"bytes,3,opt,name=event_timestamp,json=eventTimestamp,proto3" json:"event_timestamp,omitempty"` - // Complete reference to the featureSet this featureRow belongs to, in the form of - // /. This value will be used by the feast ingestion job to filter - // rows, and write the values to the correct tables. - FeatureSet string `protobuf:"bytes,6,opt,name=feature_set,json=featureSet,proto3" json:"feature_set,omitempty"` - // Identifier tying this feature row to a specific ingestion job. - IngestionId string `protobuf:"bytes,7,opt,name=ingestion_id,json=ingestionId,proto3" json:"ingestion_id,omitempty"` -} - -func (x *FeatureRow) Reset() { - *x = FeatureRow{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_FeatureRow_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureRow) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureRow) ProtoMessage() {} - -func (x *FeatureRow) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_FeatureRow_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureRow.ProtoReflect.Descriptor instead. -func (*FeatureRow) Descriptor() ([]byte, []int) { - return file_feast_types_FeatureRow_proto_rawDescGZIP(), []int{0} -} - -func (x *FeatureRow) GetFields() []*Field { - if x != nil { - return x.Fields - } - return nil -} - -func (x *FeatureRow) GetEventTimestamp() *timestamp.Timestamp { - if x != nil { - return x.EventTimestamp - } - return nil -} - -func (x *FeatureRow) GetFeatureSet() string { - if x != nil { - return x.FeatureSet - } - return "" -} - -func (x *FeatureRow) GetIngestionId() string { - if x != nil { - return x.IngestionId - } - return "" -} - -var File_feast_types_FeatureRow_proto protoreflect.FileDescriptor - -var file_feast_types_FeatureRow_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc1, 0x01, 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x6f, 0x77, 0x12, 0x2a, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, - 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x5f, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, - 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x5a, 0x0a, 0x11, 0x66, 0x65, 0x61, - 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0f, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, - 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, - 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_types_FeatureRow_proto_rawDescOnce sync.Once - file_feast_types_FeatureRow_proto_rawDescData = file_feast_types_FeatureRow_proto_rawDesc -) - -func file_feast_types_FeatureRow_proto_rawDescGZIP() []byte { - file_feast_types_FeatureRow_proto_rawDescOnce.Do(func() { - file_feast_types_FeatureRow_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_types_FeatureRow_proto_rawDescData) - }) - return file_feast_types_FeatureRow_proto_rawDescData -} - -var file_feast_types_FeatureRow_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_feast_types_FeatureRow_proto_goTypes = []interface{}{ - (*FeatureRow)(nil), // 0: feast.types.FeatureRow - (*Field)(nil), // 1: feast.types.Field - (*timestamp.Timestamp)(nil), // 2: google.protobuf.Timestamp -} -var file_feast_types_FeatureRow_proto_depIdxs = []int32{ - 1, // 0: feast.types.FeatureRow.fields:type_name -> feast.types.Field - 2, // 1: feast.types.FeatureRow.event_timestamp:type_name -> google.protobuf.Timestamp - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_feast_types_FeatureRow_proto_init() } -func file_feast_types_FeatureRow_proto_init() { - if File_feast_types_FeatureRow_proto != nil { - return - } - file_feast_types_Field_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_types_FeatureRow_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureRow); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_types_FeatureRow_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_types_FeatureRow_proto_goTypes, - DependencyIndexes: file_feast_types_FeatureRow_proto_depIdxs, - MessageInfos: file_feast_types_FeatureRow_proto_msgTypes, - }.Build() - File_feast_types_FeatureRow_proto = out.File - file_feast_types_FeatureRow_proto_rawDesc = nil - file_feast_types_FeatureRow_proto_goTypes = nil - file_feast_types_FeatureRow_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/types/FeatureRowExtended.pb.go b/sdk/go/protos/feast/types/FeatureRowExtended.pb.go deleted file mode 100644 index a01f0b0417a..00000000000 --- a/sdk/go/protos/feast/types/FeatureRowExtended.pb.go +++ /dev/null @@ -1,370 +0,0 @@ -// -// Copyright 2018 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.10.0 -// source: feast/types/FeatureRowExtended.proto - -package types - -import ( - proto "github.com/golang/protobuf/proto" - timestamp "github.com/golang/protobuf/ptypes/timestamp" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = 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 Error struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Cause string `protobuf:"bytes,1,opt,name=cause,proto3" json:"cause,omitempty"` // exception class name - Transform string `protobuf:"bytes,2,opt,name=transform,proto3" json:"transform,omitempty"` // name of transform where the error occurred - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - StackTrace string `protobuf:"bytes,4,opt,name=stack_trace,json=stackTrace,proto3" json:"stack_trace,omitempty"` -} - -func (x *Error) Reset() { - *x = Error{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_FeatureRowExtended_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Error) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Error) ProtoMessage() {} - -func (x *Error) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_FeatureRowExtended_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Error.ProtoReflect.Descriptor instead. -func (*Error) Descriptor() ([]byte, []int) { - return file_feast_types_FeatureRowExtended_proto_rawDescGZIP(), []int{0} -} - -func (x *Error) GetCause() string { - if x != nil { - return x.Cause - } - return "" -} - -func (x *Error) GetTransform() string { - if x != nil { - return x.Transform - } - return "" -} - -func (x *Error) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *Error) GetStackTrace() string { - if x != nil { - return x.StackTrace - } - return "" -} - -type Attempt struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Attempts int32 `protobuf:"varint,1,opt,name=attempts,proto3" json:"attempts,omitempty"` - Error *Error `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` -} - -func (x *Attempt) Reset() { - *x = Attempt{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_FeatureRowExtended_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Attempt) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Attempt) ProtoMessage() {} - -func (x *Attempt) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_FeatureRowExtended_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Attempt.ProtoReflect.Descriptor instead. -func (*Attempt) Descriptor() ([]byte, []int) { - return file_feast_types_FeatureRowExtended_proto_rawDescGZIP(), []int{1} -} - -func (x *Attempt) GetAttempts() int32 { - if x != nil { - return x.Attempts - } - return 0 -} - -func (x *Attempt) GetError() *Error { - if x != nil { - return x.Error - } - return nil -} - -type FeatureRowExtended struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Row *FeatureRow `protobuf:"bytes,1,opt,name=row,proto3" json:"row,omitempty"` - LastAttempt *Attempt `protobuf:"bytes,2,opt,name=last_attempt,json=lastAttempt,proto3" json:"last_attempt,omitempty"` - FirstSeen *timestamp.Timestamp `protobuf:"bytes,3,opt,name=first_seen,json=firstSeen,proto3" json:"first_seen,omitempty"` -} - -func (x *FeatureRowExtended) Reset() { - *x = FeatureRowExtended{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_FeatureRowExtended_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureRowExtended) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureRowExtended) ProtoMessage() {} - -func (x *FeatureRowExtended) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_FeatureRowExtended_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureRowExtended.ProtoReflect.Descriptor instead. -func (*FeatureRowExtended) Descriptor() ([]byte, []int) { - return file_feast_types_FeatureRowExtended_proto_rawDescGZIP(), []int{2} -} - -func (x *FeatureRowExtended) GetRow() *FeatureRow { - if x != nil { - return x.Row - } - return nil -} - -func (x *FeatureRowExtended) GetLastAttempt() *Attempt { - if x != nil { - return x.LastAttempt - } - return nil -} - -func (x *FeatureRowExtended) GetFirstSeen() *timestamp.Timestamp { - if x != nil { - return x.FirstSeen - } - return nil -} - -var File_feast_types_FeatureRowExtended_proto protoreflect.FileDescriptor - -var file_feast_types_FeatureRowExtended_proto_rawDesc = []byte{ - 0x0a, 0x24, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x76, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x63, - 0x61, 0x75, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, 0x75, 0x73, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, - 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x73, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x22, 0x4f, 0x0a, 0x07, 0x41, 0x74, - 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, - 0x73, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xb3, 0x01, 0x0a, 0x12, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, - 0x65, 0x64, 0x12, 0x29, 0x0a, 0x03, 0x72, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x6f, 0x77, 0x52, 0x03, 0x72, 0x6f, 0x77, 0x12, 0x37, 0x0a, - 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x41, - 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, - 0x73, 0x65, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x53, 0x65, 0x65, - 0x6e, 0x42, 0x62, 0x0a, 0x11, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x17, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, - 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, - 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_types_FeatureRowExtended_proto_rawDescOnce sync.Once - file_feast_types_FeatureRowExtended_proto_rawDescData = file_feast_types_FeatureRowExtended_proto_rawDesc -) - -func file_feast_types_FeatureRowExtended_proto_rawDescGZIP() []byte { - file_feast_types_FeatureRowExtended_proto_rawDescOnce.Do(func() { - file_feast_types_FeatureRowExtended_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_types_FeatureRowExtended_proto_rawDescData) - }) - return file_feast_types_FeatureRowExtended_proto_rawDescData -} - -var file_feast_types_FeatureRowExtended_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_feast_types_FeatureRowExtended_proto_goTypes = []interface{}{ - (*Error)(nil), // 0: feast.types.Error - (*Attempt)(nil), // 1: feast.types.Attempt - (*FeatureRowExtended)(nil), // 2: feast.types.FeatureRowExtended - (*FeatureRow)(nil), // 3: feast.types.FeatureRow - (*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp -} -var file_feast_types_FeatureRowExtended_proto_depIdxs = []int32{ - 0, // 0: feast.types.Attempt.error:type_name -> feast.types.Error - 3, // 1: feast.types.FeatureRowExtended.row:type_name -> feast.types.FeatureRow - 1, // 2: feast.types.FeatureRowExtended.last_attempt:type_name -> feast.types.Attempt - 4, // 3: feast.types.FeatureRowExtended.first_seen:type_name -> google.protobuf.Timestamp - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_feast_types_FeatureRowExtended_proto_init() } -func file_feast_types_FeatureRowExtended_proto_init() { - if File_feast_types_FeatureRowExtended_proto != nil { - return - } - file_feast_types_FeatureRow_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_types_FeatureRowExtended_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Error); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_FeatureRowExtended_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Attempt); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_FeatureRowExtended_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureRowExtended); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_types_FeatureRowExtended_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_types_FeatureRowExtended_proto_goTypes, - DependencyIndexes: file_feast_types_FeatureRowExtended_proto_depIdxs, - MessageInfos: file_feast_types_FeatureRowExtended_proto_msgTypes, - }.Build() - File_feast_types_FeatureRowExtended_proto = out.File - file_feast_types_FeatureRowExtended_proto_rawDesc = nil - file_feast_types_FeatureRowExtended_proto_goTypes = nil - file_feast_types_FeatureRowExtended_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/types/Field.pb.go b/sdk/go/protos/feast/types/Field.pb.go deleted file mode 100644 index af964f2c6ea..00000000000 --- a/sdk/go/protos/feast/types/Field.pb.go +++ /dev/null @@ -1,177 +0,0 @@ -// -// Copyright 2018 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/types/Field.proto - -package types - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Field struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Value *Value `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *Field) Reset() { - *x = Field{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Field_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Field) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Field) ProtoMessage() {} - -func (x *Field) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Field_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Field.ProtoReflect.Descriptor instead. -func (*Field) Descriptor() ([]byte, []int) { - return file_feast_types_Field_proto_rawDescGZIP(), []int{0} -} - -func (x *Field) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Field) GetValue() *Value { - if x != nil { - return x.Value - } - return nil -} - -var File_feast_types_Field_proto protoreflect.FileDescriptor - -var file_feast_types_Field_proto_rawDesc = []byte{ - 0x0a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x1a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x45, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x55, 0x0a, 0x11, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0a, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x73, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_feast_types_Field_proto_rawDescOnce sync.Once - file_feast_types_Field_proto_rawDescData = file_feast_types_Field_proto_rawDesc -) - -func file_feast_types_Field_proto_rawDescGZIP() []byte { - file_feast_types_Field_proto_rawDescOnce.Do(func() { - file_feast_types_Field_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_types_Field_proto_rawDescData) - }) - return file_feast_types_Field_proto_rawDescData -} - -var file_feast_types_Field_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_feast_types_Field_proto_goTypes = []interface{}{ - (*Field)(nil), // 0: feast.types.Field - (*Value)(nil), // 1: feast.types.Value -} -var file_feast_types_Field_proto_depIdxs = []int32{ - 1, // 0: feast.types.Field.value:type_name -> feast.types.Value - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_feast_types_Field_proto_init() } -func file_feast_types_Field_proto_init() { - if File_feast_types_Field_proto != nil { - return - } - file_feast_types_Value_proto_init() - if !protoimpl.UnsafeEnabled { - file_feast_types_Field_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Field); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_types_Field_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_types_Field_proto_goTypes, - DependencyIndexes: file_feast_types_Field_proto_depIdxs, - MessageInfos: file_feast_types_Field_proto_msgTypes, - }.Build() - File_feast_types_Field_proto = out.File - file_feast_types_Field_proto_rawDesc = nil - file_feast_types_Field_proto_goTypes = nil - file_feast_types_Field_proto_depIdxs = nil -} diff --git a/sdk/go/protos/feast/types/Value.pb.go b/sdk/go/protos/feast/types/Value.pb.go deleted file mode 100644 index 79eaa160096..00000000000 --- a/sdk/go/protos/feast/types/Value.pb.go +++ /dev/null @@ -1,1200 +0,0 @@ -// -// Copyright 2018 The Feast Authors -// -// 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 -// -// https://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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feast/types/Value.proto - -package types - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Null int32 - -const ( - Null_NULL Null = 0 -) - -// Enum value maps for Null. -var ( - Null_name = map[int32]string{ - 0: "NULL", - } - Null_value = map[string]int32{ - "NULL": 0, - } -) - -func (x Null) Enum() *Null { - p := new(Null) - *p = x - return p -} - -func (x Null) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Null) Descriptor() protoreflect.EnumDescriptor { - return file_feast_types_Value_proto_enumTypes[0].Descriptor() -} - -func (Null) Type() protoreflect.EnumType { - return &file_feast_types_Value_proto_enumTypes[0] -} - -func (x Null) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Null.Descriptor instead. -func (Null) EnumDescriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{0} -} - -type ValueType_Enum int32 - -const ( - ValueType_INVALID ValueType_Enum = 0 - ValueType_BYTES ValueType_Enum = 1 - ValueType_STRING ValueType_Enum = 2 - ValueType_INT32 ValueType_Enum = 3 - ValueType_INT64 ValueType_Enum = 4 - ValueType_DOUBLE ValueType_Enum = 5 - ValueType_FLOAT ValueType_Enum = 6 - ValueType_BOOL ValueType_Enum = 7 - ValueType_UNIX_TIMESTAMP ValueType_Enum = 8 - ValueType_BYTES_LIST ValueType_Enum = 11 - ValueType_STRING_LIST ValueType_Enum = 12 - ValueType_INT32_LIST ValueType_Enum = 13 - ValueType_INT64_LIST ValueType_Enum = 14 - ValueType_DOUBLE_LIST ValueType_Enum = 15 - ValueType_FLOAT_LIST ValueType_Enum = 16 - ValueType_BOOL_LIST ValueType_Enum = 17 - ValueType_UNIX_TIMESTAMP_LIST ValueType_Enum = 18 - ValueType_NULL ValueType_Enum = 19 -) - -// Enum value maps for ValueType_Enum. -var ( - ValueType_Enum_name = map[int32]string{ - 0: "INVALID", - 1: "BYTES", - 2: "STRING", - 3: "INT32", - 4: "INT64", - 5: "DOUBLE", - 6: "FLOAT", - 7: "BOOL", - 8: "UNIX_TIMESTAMP", - 11: "BYTES_LIST", - 12: "STRING_LIST", - 13: "INT32_LIST", - 14: "INT64_LIST", - 15: "DOUBLE_LIST", - 16: "FLOAT_LIST", - 17: "BOOL_LIST", - 18: "UNIX_TIMESTAMP_LIST", - 19: "NULL", - } - ValueType_Enum_value = map[string]int32{ - "INVALID": 0, - "BYTES": 1, - "STRING": 2, - "INT32": 3, - "INT64": 4, - "DOUBLE": 5, - "FLOAT": 6, - "BOOL": 7, - "UNIX_TIMESTAMP": 8, - "BYTES_LIST": 11, - "STRING_LIST": 12, - "INT32_LIST": 13, - "INT64_LIST": 14, - "DOUBLE_LIST": 15, - "FLOAT_LIST": 16, - "BOOL_LIST": 17, - "UNIX_TIMESTAMP_LIST": 18, - "NULL": 19, - } -) - -func (x ValueType_Enum) Enum() *ValueType_Enum { - p := new(ValueType_Enum) - *p = x - return p -} - -func (x ValueType_Enum) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ValueType_Enum) Descriptor() protoreflect.EnumDescriptor { - return file_feast_types_Value_proto_enumTypes[1].Descriptor() -} - -func (ValueType_Enum) Type() protoreflect.EnumType { - return &file_feast_types_Value_proto_enumTypes[1] -} - -func (x ValueType_Enum) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ValueType_Enum.Descriptor instead. -func (ValueType_Enum) EnumDescriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{0, 0} -} - -type ValueType struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ValueType) Reset() { - *x = ValueType{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ValueType) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ValueType) ProtoMessage() {} - -func (x *ValueType) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ValueType.ProtoReflect.Descriptor instead. -func (*ValueType) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{0} -} - -type Value struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ValueType is referenced by the metadata types, FeatureInfo and EntityInfo. - // The enum values do not have to match the oneof val field ids, but they should. - // In JSON "*_val" field can be omitted - // - // Types that are assignable to Val: - // *Value_BytesVal - // *Value_StringVal - // *Value_Int32Val - // *Value_Int64Val - // *Value_DoubleVal - // *Value_FloatVal - // *Value_BoolVal - // *Value_UnixTimestampVal - // *Value_BytesListVal - // *Value_StringListVal - // *Value_Int32ListVal - // *Value_Int64ListVal - // *Value_DoubleListVal - // *Value_FloatListVal - // *Value_BoolListVal - // *Value_UnixTimestampListVal - // *Value_NullVal - Val isValue_Val `protobuf_oneof:"val"` -} - -func (x *Value) Reset() { - *x = Value{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Value) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Value) ProtoMessage() {} - -func (x *Value) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Value.ProtoReflect.Descriptor instead. -func (*Value) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{1} -} - -func (m *Value) GetVal() isValue_Val { - if m != nil { - return m.Val - } - return nil -} - -func (x *Value) GetBytesVal() []byte { - if x, ok := x.GetVal().(*Value_BytesVal); ok { - return x.BytesVal - } - return nil -} - -func (x *Value) GetStringVal() string { - if x, ok := x.GetVal().(*Value_StringVal); ok { - return x.StringVal - } - return "" -} - -func (x *Value) GetInt32Val() int32 { - if x, ok := x.GetVal().(*Value_Int32Val); ok { - return x.Int32Val - } - return 0 -} - -func (x *Value) GetInt64Val() int64 { - if x, ok := x.GetVal().(*Value_Int64Val); ok { - return x.Int64Val - } - return 0 -} - -func (x *Value) GetDoubleVal() float64 { - if x, ok := x.GetVal().(*Value_DoubleVal); ok { - return x.DoubleVal - } - return 0 -} - -func (x *Value) GetFloatVal() float32 { - if x, ok := x.GetVal().(*Value_FloatVal); ok { - return x.FloatVal - } - return 0 -} - -func (x *Value) GetBoolVal() bool { - if x, ok := x.GetVal().(*Value_BoolVal); ok { - return x.BoolVal - } - return false -} - -func (x *Value) GetUnixTimestampVal() int64 { - if x, ok := x.GetVal().(*Value_UnixTimestampVal); ok { - return x.UnixTimestampVal - } - return 0 -} - -func (x *Value) GetBytesListVal() *BytesList { - if x, ok := x.GetVal().(*Value_BytesListVal); ok { - return x.BytesListVal - } - return nil -} - -func (x *Value) GetStringListVal() *StringList { - if x, ok := x.GetVal().(*Value_StringListVal); ok { - return x.StringListVal - } - return nil -} - -func (x *Value) GetInt32ListVal() *Int32List { - if x, ok := x.GetVal().(*Value_Int32ListVal); ok { - return x.Int32ListVal - } - return nil -} - -func (x *Value) GetInt64ListVal() *Int64List { - if x, ok := x.GetVal().(*Value_Int64ListVal); ok { - return x.Int64ListVal - } - return nil -} - -func (x *Value) GetDoubleListVal() *DoubleList { - if x, ok := x.GetVal().(*Value_DoubleListVal); ok { - return x.DoubleListVal - } - return nil -} - -func (x *Value) GetFloatListVal() *FloatList { - if x, ok := x.GetVal().(*Value_FloatListVal); ok { - return x.FloatListVal - } - return nil -} - -func (x *Value) GetBoolListVal() *BoolList { - if x, ok := x.GetVal().(*Value_BoolListVal); ok { - return x.BoolListVal - } - return nil -} - -func (x *Value) GetUnixTimestampListVal() *Int64List { - if x, ok := x.GetVal().(*Value_UnixTimestampListVal); ok { - return x.UnixTimestampListVal - } - return nil -} - -func (x *Value) GetNullVal() Null { - if x, ok := x.GetVal().(*Value_NullVal); ok { - return x.NullVal - } - return Null_NULL -} - -type isValue_Val interface { - isValue_Val() -} - -type Value_BytesVal struct { - BytesVal []byte `protobuf:"bytes,1,opt,name=bytes_val,json=bytesVal,proto3,oneof"` -} - -type Value_StringVal struct { - StringVal string `protobuf:"bytes,2,opt,name=string_val,json=stringVal,proto3,oneof"` -} - -type Value_Int32Val struct { - Int32Val int32 `protobuf:"varint,3,opt,name=int32_val,json=int32Val,proto3,oneof"` -} - -type Value_Int64Val struct { - Int64Val int64 `protobuf:"varint,4,opt,name=int64_val,json=int64Val,proto3,oneof"` -} - -type Value_DoubleVal struct { - DoubleVal float64 `protobuf:"fixed64,5,opt,name=double_val,json=doubleVal,proto3,oneof"` -} - -type Value_FloatVal struct { - FloatVal float32 `protobuf:"fixed32,6,opt,name=float_val,json=floatVal,proto3,oneof"` -} - -type Value_BoolVal struct { - BoolVal bool `protobuf:"varint,7,opt,name=bool_val,json=boolVal,proto3,oneof"` -} - -type Value_UnixTimestampVal struct { - UnixTimestampVal int64 `protobuf:"varint,8,opt,name=unix_timestamp_val,json=unixTimestampVal,proto3,oneof"` -} - -type Value_BytesListVal struct { - BytesListVal *BytesList `protobuf:"bytes,11,opt,name=bytes_list_val,json=bytesListVal,proto3,oneof"` -} - -type Value_StringListVal struct { - StringListVal *StringList `protobuf:"bytes,12,opt,name=string_list_val,json=stringListVal,proto3,oneof"` -} - -type Value_Int32ListVal struct { - Int32ListVal *Int32List `protobuf:"bytes,13,opt,name=int32_list_val,json=int32ListVal,proto3,oneof"` -} - -type Value_Int64ListVal struct { - Int64ListVal *Int64List `protobuf:"bytes,14,opt,name=int64_list_val,json=int64ListVal,proto3,oneof"` -} - -type Value_DoubleListVal struct { - DoubleListVal *DoubleList `protobuf:"bytes,15,opt,name=double_list_val,json=doubleListVal,proto3,oneof"` -} - -type Value_FloatListVal struct { - FloatListVal *FloatList `protobuf:"bytes,16,opt,name=float_list_val,json=floatListVal,proto3,oneof"` -} - -type Value_BoolListVal struct { - BoolListVal *BoolList `protobuf:"bytes,17,opt,name=bool_list_val,json=boolListVal,proto3,oneof"` -} - -type Value_UnixTimestampListVal struct { - UnixTimestampListVal *Int64List `protobuf:"bytes,18,opt,name=unix_timestamp_list_val,json=unixTimestampListVal,proto3,oneof"` -} - -type Value_NullVal struct { - NullVal Null `protobuf:"varint,19,opt,name=null_val,json=nullVal,proto3,enum=feast.types.Null,oneof"` -} - -func (*Value_BytesVal) isValue_Val() {} - -func (*Value_StringVal) isValue_Val() {} - -func (*Value_Int32Val) isValue_Val() {} - -func (*Value_Int64Val) isValue_Val() {} - -func (*Value_DoubleVal) isValue_Val() {} - -func (*Value_FloatVal) isValue_Val() {} - -func (*Value_BoolVal) isValue_Val() {} - -func (*Value_UnixTimestampVal) isValue_Val() {} - -func (*Value_BytesListVal) isValue_Val() {} - -func (*Value_StringListVal) isValue_Val() {} - -func (*Value_Int32ListVal) isValue_Val() {} - -func (*Value_Int64ListVal) isValue_Val() {} - -func (*Value_DoubleListVal) isValue_Val() {} - -func (*Value_FloatListVal) isValue_Val() {} - -func (*Value_BoolListVal) isValue_Val() {} - -func (*Value_UnixTimestampListVal) isValue_Val() {} - -func (*Value_NullVal) isValue_Val() {} - -type BytesList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val [][]byte `protobuf:"bytes,1,rep,name=val,proto3" json:"val,omitempty"` -} - -func (x *BytesList) Reset() { - *x = BytesList{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BytesList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BytesList) ProtoMessage() {} - -func (x *BytesList) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BytesList.ProtoReflect.Descriptor instead. -func (*BytesList) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{2} -} - -func (x *BytesList) GetVal() [][]byte { - if x != nil { - return x.Val - } - return nil -} - -type StringList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []string `protobuf:"bytes,1,rep,name=val,proto3" json:"val,omitempty"` -} - -func (x *StringList) Reset() { - *x = StringList{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StringList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StringList) ProtoMessage() {} - -func (x *StringList) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StringList.ProtoReflect.Descriptor instead. -func (*StringList) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{3} -} - -func (x *StringList) GetVal() []string { - if x != nil { - return x.Val - } - return nil -} - -type Int32List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []int32 `protobuf:"varint,1,rep,packed,name=val,proto3" json:"val,omitempty"` -} - -func (x *Int32List) Reset() { - *x = Int32List{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Int32List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Int32List) ProtoMessage() {} - -func (x *Int32List) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Int32List.ProtoReflect.Descriptor instead. -func (*Int32List) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{4} -} - -func (x *Int32List) GetVal() []int32 { - if x != nil { - return x.Val - } - return nil -} - -type Int64List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []int64 `protobuf:"varint,1,rep,packed,name=val,proto3" json:"val,omitempty"` -} - -func (x *Int64List) Reset() { - *x = Int64List{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Int64List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Int64List) ProtoMessage() {} - -func (x *Int64List) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Int64List.ProtoReflect.Descriptor instead. -func (*Int64List) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{5} -} - -func (x *Int64List) GetVal() []int64 { - if x != nil { - return x.Val - } - return nil -} - -type DoubleList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []float64 `protobuf:"fixed64,1,rep,packed,name=val,proto3" json:"val,omitempty"` -} - -func (x *DoubleList) Reset() { - *x = DoubleList{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DoubleList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DoubleList) ProtoMessage() {} - -func (x *DoubleList) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DoubleList.ProtoReflect.Descriptor instead. -func (*DoubleList) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{6} -} - -func (x *DoubleList) GetVal() []float64 { - if x != nil { - return x.Val - } - return nil -} - -type FloatList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []float32 `protobuf:"fixed32,1,rep,packed,name=val,proto3" json:"val,omitempty"` -} - -func (x *FloatList) Reset() { - *x = FloatList{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FloatList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FloatList) ProtoMessage() {} - -func (x *FloatList) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FloatList.ProtoReflect.Descriptor instead. -func (*FloatList) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{7} -} - -func (x *FloatList) GetVal() []float32 { - if x != nil { - return x.Val - } - return nil -} - -type BoolList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []bool `protobuf:"varint,1,rep,packed,name=val,proto3" json:"val,omitempty"` -} - -func (x *BoolList) Reset() { - *x = BoolList{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BoolList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BoolList) ProtoMessage() {} - -func (x *BoolList) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BoolList.ProtoReflect.Descriptor instead. -func (*BoolList) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{8} -} - -func (x *BoolList) GetVal() []bool { - if x != nil { - return x.Val - } - return nil -} - -// This is to avoid an issue of being unable to specify `repeated value` in oneofs or maps -// In JSON "val" field can be omitted -type RepeatedValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []*Value `protobuf:"bytes,1,rep,name=val,proto3" json:"val,omitempty"` -} - -func (x *RepeatedValue) Reset() { - *x = RepeatedValue{} - if protoimpl.UnsafeEnabled { - mi := &file_feast_types_Value_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RepeatedValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RepeatedValue) ProtoMessage() {} - -func (x *RepeatedValue) ProtoReflect() protoreflect.Message { - mi := &file_feast_types_Value_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RepeatedValue.ProtoReflect.Descriptor instead. -func (*RepeatedValue) Descriptor() ([]byte, []int) { - return file_feast_types_Value_proto_rawDescGZIP(), []int{9} -} - -func (x *RepeatedValue) GetVal() []*Value { - if x != nil { - return x.Val - } - return nil -} - -var File_feast_types_Value_proto protoreflect.FileDescriptor - -var file_feast_types_Value_proto_rawDesc = []byte{ - 0x0a, 0x17, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x22, 0x97, 0x02, 0x0a, 0x09, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x22, 0x89, 0x02, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0b, 0x0a, - 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x59, - 0x54, 0x45, 0x53, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, - 0x02, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, - 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x4f, 0x55, 0x42, 0x4c, - 0x45, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x06, 0x12, 0x08, - 0x0a, 0x04, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x49, 0x58, - 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, - 0x42, 0x59, 0x54, 0x45, 0x53, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, - 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x0c, 0x12, 0x0e, 0x0a, - 0x0a, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x0d, 0x12, 0x0e, 0x0a, - 0x0a, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x0e, 0x12, 0x0f, 0x0a, - 0x0b, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x0f, 0x12, 0x0e, - 0x0a, 0x0a, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x10, 0x12, 0x0d, - 0x0a, 0x09, 0x42, 0x4f, 0x4f, 0x4c, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x11, 0x12, 0x17, 0x0a, - 0x13, 0x55, 0x4e, 0x49, 0x58, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x5f, - 0x4c, 0x49, 0x53, 0x54, 0x10, 0x12, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x55, 0x4c, 0x4c, 0x10, 0x13, - 0x22, 0xdd, 0x06, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, - 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0a, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, - 0x09, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, - 0x08, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0a, 0x64, 0x6f, 0x75, 0x62, - 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x09, - 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x09, 0x66, 0x6c, 0x6f, - 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x48, 0x00, 0x52, 0x08, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x08, 0x62, 0x6f, 0x6f, 0x6c, - 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x62, 0x6f, - 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x12, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x03, 0x48, 0x00, 0x52, 0x10, 0x75, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x56, 0x61, 0x6c, 0x12, 0x3e, 0x0a, 0x0e, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6c, - 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x42, 0x79, 0x74, 0x65, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, - 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x41, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x3e, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x33, - 0x32, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x33, - 0x32, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x3e, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x41, 0x0a, 0x0f, 0x64, 0x6f, 0x75, 0x62, - 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x64, 0x6f, - 0x75, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x3e, 0x0a, 0x0e, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x10, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0d, 0x62, - 0x6f, 0x6f, 0x6c, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x6f, 0x6f, - 0x6c, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x4f, 0x0a, 0x17, 0x75, 0x6e, 0x69, 0x78, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, - 0x76, 0x61, 0x6c, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x4c, 0x69, 0x73, - 0x74, 0x48, 0x00, 0x52, 0x14, 0x75, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x2e, 0x0a, 0x08, 0x6e, 0x75, 0x6c, - 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x66, 0x65, - 0x61, 0x73, 0x74, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x48, 0x00, - 0x52, 0x07, 0x6e, 0x75, 0x6c, 0x6c, 0x56, 0x61, 0x6c, 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, - 0x22, 0x1d, 0x0a, 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, - 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, - 0x1e, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, - 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, - 0x1d, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x1d, - 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x76, - 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x1e, 0x0a, - 0x0a, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x76, - 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x01, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x1d, 0x0a, - 0x09, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, - 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x02, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x1c, 0x0a, 0x08, - 0x42, 0x6f, 0x6f, 0x6c, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x08, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x35, 0x0a, 0x0d, 0x52, 0x65, - 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x76, - 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x76, 0x61, - 0x6c, 0x2a, 0x10, 0x0a, 0x04, 0x4e, 0x75, 0x6c, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x55, 0x4c, - 0x4c, 0x10, 0x00, 0x42, 0x55, 0x0a, 0x11, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x42, 0x0a, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, - 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x66, - 0x65, 0x61, 0x73, 0x74, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_feast_types_Value_proto_rawDescOnce sync.Once - file_feast_types_Value_proto_rawDescData = file_feast_types_Value_proto_rawDesc -) - -func file_feast_types_Value_proto_rawDescGZIP() []byte { - file_feast_types_Value_proto_rawDescOnce.Do(func() { - file_feast_types_Value_proto_rawDescData = protoimpl.X.CompressGZIP(file_feast_types_Value_proto_rawDescData) - }) - return file_feast_types_Value_proto_rawDescData -} - -var file_feast_types_Value_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_feast_types_Value_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -var file_feast_types_Value_proto_goTypes = []interface{}{ - (Null)(0), // 0: feast.types.Null - (ValueType_Enum)(0), // 1: feast.types.ValueType.Enum - (*ValueType)(nil), // 2: feast.types.ValueType - (*Value)(nil), // 3: feast.types.Value - (*BytesList)(nil), // 4: feast.types.BytesList - (*StringList)(nil), // 5: feast.types.StringList - (*Int32List)(nil), // 6: feast.types.Int32List - (*Int64List)(nil), // 7: feast.types.Int64List - (*DoubleList)(nil), // 8: feast.types.DoubleList - (*FloatList)(nil), // 9: feast.types.FloatList - (*BoolList)(nil), // 10: feast.types.BoolList - (*RepeatedValue)(nil), // 11: feast.types.RepeatedValue -} -var file_feast_types_Value_proto_depIdxs = []int32{ - 4, // 0: feast.types.Value.bytes_list_val:type_name -> feast.types.BytesList - 5, // 1: feast.types.Value.string_list_val:type_name -> feast.types.StringList - 6, // 2: feast.types.Value.int32_list_val:type_name -> feast.types.Int32List - 7, // 3: feast.types.Value.int64_list_val:type_name -> feast.types.Int64List - 8, // 4: feast.types.Value.double_list_val:type_name -> feast.types.DoubleList - 9, // 5: feast.types.Value.float_list_val:type_name -> feast.types.FloatList - 10, // 6: feast.types.Value.bool_list_val:type_name -> feast.types.BoolList - 7, // 7: feast.types.Value.unix_timestamp_list_val:type_name -> feast.types.Int64List - 0, // 8: feast.types.Value.null_val:type_name -> feast.types.Null - 3, // 9: feast.types.RepeatedValue.val:type_name -> feast.types.Value - 10, // [10:10] is the sub-list for method output_type - 10, // [10:10] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name -} - -func init() { file_feast_types_Value_proto_init() } -func file_feast_types_Value_proto_init() { - if File_feast_types_Value_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feast_types_Value_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValueType); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Value); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BytesList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StringList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Int32List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Int64List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoubleList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FloatList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BoolList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feast_types_Value_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RepeatedValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_feast_types_Value_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Value_BytesVal)(nil), - (*Value_StringVal)(nil), - (*Value_Int32Val)(nil), - (*Value_Int64Val)(nil), - (*Value_DoubleVal)(nil), - (*Value_FloatVal)(nil), - (*Value_BoolVal)(nil), - (*Value_UnixTimestampVal)(nil), - (*Value_BytesListVal)(nil), - (*Value_StringListVal)(nil), - (*Value_Int32ListVal)(nil), - (*Value_Int64ListVal)(nil), - (*Value_DoubleListVal)(nil), - (*Value_FloatListVal)(nil), - (*Value_BoolListVal)(nil), - (*Value_UnixTimestampListVal)(nil), - (*Value_NullVal)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feast_types_Value_proto_rawDesc, - NumEnums: 2, - NumMessages: 10, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feast_types_Value_proto_goTypes, - DependencyIndexes: file_feast_types_Value_proto_depIdxs, - EnumInfos: file_feast_types_Value_proto_enumTypes, - MessageInfos: file_feast_types_Value_proto_msgTypes, - }.Build() - File_feast_types_Value_proto = out.File - file_feast_types_Value_proto_rawDesc = nil - file_feast_types_Value_proto_goTypes = nil - file_feast_types_Value_proto_depIdxs = nil -} diff --git a/sdk/go/protos/tensorflow_metadata/proto/v0/path.pb.go b/sdk/go/protos/tensorflow_metadata/proto/v0/path.pb.go deleted file mode 100644 index 5abc145a622..00000000000 --- a/sdk/go/protos/tensorflow_metadata/proto/v0/path.pb.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2018 The TensorFlow Authors. All Rights Reserved. -// -// 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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.11.2 -// source: tensorflow_metadata/proto/v0/path.proto - -package v0 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// A path is a more general substitute for the name of a field or feature that -// can be used for flat examples as well as structured data. For example, if -// we had data in a protocol buffer: -// message Person { -// int age = 1; -// optional string gender = 2; -// repeated Person parent = 3; -// } -// Thus, here the path {step:["parent", "age"]} in statistics would refer to the -// age of a parent, and {step:["parent", "parent", "age"]} would refer to the -// age of a grandparent. This allows us to distinguish between the statistics -// of parents' ages and grandparents' ages. In general, repeated messages are -// to be preferred to linked lists of arbitrary length. -// For SequenceExample, if we have a feature list "foo", this is represented -// by {step:["##SEQUENCE##", "foo"]}. -type Path struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Any string is a valid step. - // However, whenever possible have a step be [A-Za-z0-9_]+. - Step []string `protobuf:"bytes,1,rep,name=step" json:"step,omitempty"` -} - -func (x *Path) Reset() { - *x = Path{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_path_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Path) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Path) ProtoMessage() {} - -func (x *Path) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_path_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Path.ProtoReflect.Descriptor instead. -func (*Path) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_path_proto_rawDescGZIP(), []int{0} -} - -func (x *Path) GetStep() []string { - if x != nil { - return x.Step - } - return nil -} - -var File_tensorflow_metadata_proto_v0_path_proto protoreflect.FileDescriptor - -var file_tensorflow_metadata_proto_v0_path_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0x2f, 0x70, - 0x61, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x22, 0x1a, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x65, - 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x65, 0x70, 0x42, 0x68, 0x0a, - 0x1a, 0x6f, 0x72, 0x67, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x50, 0x01, 0x5a, 0x45, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, - 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x76, 0x30, 0xf8, 0x01, 0x01, -} - -var ( - file_tensorflow_metadata_proto_v0_path_proto_rawDescOnce sync.Once - file_tensorflow_metadata_proto_v0_path_proto_rawDescData = file_tensorflow_metadata_proto_v0_path_proto_rawDesc -) - -func file_tensorflow_metadata_proto_v0_path_proto_rawDescGZIP() []byte { - file_tensorflow_metadata_proto_v0_path_proto_rawDescOnce.Do(func() { - file_tensorflow_metadata_proto_v0_path_proto_rawDescData = protoimpl.X.CompressGZIP(file_tensorflow_metadata_proto_v0_path_proto_rawDescData) - }) - return file_tensorflow_metadata_proto_v0_path_proto_rawDescData -} - -var file_tensorflow_metadata_proto_v0_path_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_tensorflow_metadata_proto_v0_path_proto_goTypes = []interface{}{ - (*Path)(nil), // 0: tensorflow.metadata.v0.Path -} -var file_tensorflow_metadata_proto_v0_path_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_tensorflow_metadata_proto_v0_path_proto_init() } -func file_tensorflow_metadata_proto_v0_path_proto_init() { - if File_tensorflow_metadata_proto_v0_path_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_tensorflow_metadata_proto_v0_path_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Path); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_tensorflow_metadata_proto_v0_path_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_tensorflow_metadata_proto_v0_path_proto_goTypes, - DependencyIndexes: file_tensorflow_metadata_proto_v0_path_proto_depIdxs, - MessageInfos: file_tensorflow_metadata_proto_v0_path_proto_msgTypes, - }.Build() - File_tensorflow_metadata_proto_v0_path_proto = out.File - file_tensorflow_metadata_proto_v0_path_proto_rawDesc = nil - file_tensorflow_metadata_proto_v0_path_proto_goTypes = nil - file_tensorflow_metadata_proto_v0_path_proto_depIdxs = nil -} diff --git a/sdk/go/protos/tensorflow_metadata/proto/v0/schema.pb.go b/sdk/go/protos/tensorflow_metadata/proto/v0/schema.pb.go deleted file mode 100644 index 0200d3afb61..00000000000 --- a/sdk/go/protos/tensorflow_metadata/proto/v0/schema.pb.go +++ /dev/null @@ -1,4078 +0,0 @@ -// Copyright 2017 The TensorFlow Authors. All Rights Reserved. -// -// 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. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.11.2 -// source: tensorflow_metadata/proto/v0/schema.proto - -package v0 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// LifecycleStage. Only UNKNOWN_STAGE, BETA, and PRODUCTION features are -// actually validated. -// PLANNED, ALPHA, and DEBUG are treated as DEPRECATED. -type LifecycleStage int32 - -const ( - LifecycleStage_UNKNOWN_STAGE LifecycleStage = 0 // Unknown stage. - LifecycleStage_PLANNED LifecycleStage = 1 // Planned feature, may not be created yet. - LifecycleStage_ALPHA LifecycleStage = 2 // Prototype feature, not used in experiments yet. - LifecycleStage_BETA LifecycleStage = 3 // Used in user-facing experiments. - LifecycleStage_PRODUCTION LifecycleStage = 4 // Used in a significant fraction of user traffic. - LifecycleStage_DEPRECATED LifecycleStage = 5 // No longer supported: do not use in new models. - LifecycleStage_DEBUG_ONLY LifecycleStage = 6 // Only exists for debugging purposes. -) - -// Enum value maps for LifecycleStage. -var ( - LifecycleStage_name = map[int32]string{ - 0: "UNKNOWN_STAGE", - 1: "PLANNED", - 2: "ALPHA", - 3: "BETA", - 4: "PRODUCTION", - 5: "DEPRECATED", - 6: "DEBUG_ONLY", - } - LifecycleStage_value = map[string]int32{ - "UNKNOWN_STAGE": 0, - "PLANNED": 1, - "ALPHA": 2, - "BETA": 3, - "PRODUCTION": 4, - "DEPRECATED": 5, - "DEBUG_ONLY": 6, - } -) - -func (x LifecycleStage) Enum() *LifecycleStage { - p := new(LifecycleStage) - *p = x - return p -} - -func (x LifecycleStage) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LifecycleStage) Descriptor() protoreflect.EnumDescriptor { - return file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[0].Descriptor() -} - -func (LifecycleStage) Type() protoreflect.EnumType { - return &file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[0] -} - -func (x LifecycleStage) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *LifecycleStage) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = LifecycleStage(num) - return nil -} - -// Deprecated: Use LifecycleStage.Descriptor instead. -func (LifecycleStage) EnumDescriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{0} -} - -// Describes the physical representation of a feature. -// It may be different than the logical representation, which -// is represented as a Domain. -type FeatureType int32 - -const ( - FeatureType_TYPE_UNKNOWN FeatureType = 0 - FeatureType_BYTES FeatureType = 1 - FeatureType_INT FeatureType = 2 - FeatureType_FLOAT FeatureType = 3 - FeatureType_STRUCT FeatureType = 4 -) - -// Enum value maps for FeatureType. -var ( - FeatureType_name = map[int32]string{ - 0: "TYPE_UNKNOWN", - 1: "BYTES", - 2: "INT", - 3: "FLOAT", - 4: "STRUCT", - } - FeatureType_value = map[string]int32{ - "TYPE_UNKNOWN": 0, - "BYTES": 1, - "INT": 2, - "FLOAT": 3, - "STRUCT": 4, - } -) - -func (x FeatureType) Enum() *FeatureType { - p := new(FeatureType) - *p = x - return p -} - -func (x FeatureType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (FeatureType) Descriptor() protoreflect.EnumDescriptor { - return file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[1].Descriptor() -} - -func (FeatureType) Type() protoreflect.EnumType { - return &file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[1] -} - -func (x FeatureType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *FeatureType) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = FeatureType(num) - return nil -} - -// Deprecated: Use FeatureType.Descriptor instead. -func (FeatureType) EnumDescriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{1} -} - -type TimeDomain_IntegerTimeFormat int32 - -const ( - TimeDomain_FORMAT_UNKNOWN TimeDomain_IntegerTimeFormat = 0 - TimeDomain_UNIX_DAYS TimeDomain_IntegerTimeFormat = 5 // Number of days since 1970-01-01. - TimeDomain_UNIX_SECONDS TimeDomain_IntegerTimeFormat = 1 - TimeDomain_UNIX_MILLISECONDS TimeDomain_IntegerTimeFormat = 2 - TimeDomain_UNIX_MICROSECONDS TimeDomain_IntegerTimeFormat = 3 - TimeDomain_UNIX_NANOSECONDS TimeDomain_IntegerTimeFormat = 4 -) - -// Enum value maps for TimeDomain_IntegerTimeFormat. -var ( - TimeDomain_IntegerTimeFormat_name = map[int32]string{ - 0: "FORMAT_UNKNOWN", - 5: "UNIX_DAYS", - 1: "UNIX_SECONDS", - 2: "UNIX_MILLISECONDS", - 3: "UNIX_MICROSECONDS", - 4: "UNIX_NANOSECONDS", - } - TimeDomain_IntegerTimeFormat_value = map[string]int32{ - "FORMAT_UNKNOWN": 0, - "UNIX_DAYS": 5, - "UNIX_SECONDS": 1, - "UNIX_MILLISECONDS": 2, - "UNIX_MICROSECONDS": 3, - "UNIX_NANOSECONDS": 4, - } -) - -func (x TimeDomain_IntegerTimeFormat) Enum() *TimeDomain_IntegerTimeFormat { - p := new(TimeDomain_IntegerTimeFormat) - *p = x - return p -} - -func (x TimeDomain_IntegerTimeFormat) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TimeDomain_IntegerTimeFormat) Descriptor() protoreflect.EnumDescriptor { - return file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[2].Descriptor() -} - -func (TimeDomain_IntegerTimeFormat) Type() protoreflect.EnumType { - return &file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[2] -} - -func (x TimeDomain_IntegerTimeFormat) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *TimeDomain_IntegerTimeFormat) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = TimeDomain_IntegerTimeFormat(num) - return nil -} - -// Deprecated: Use TimeDomain_IntegerTimeFormat.Descriptor instead. -func (TimeDomain_IntegerTimeFormat) EnumDescriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{19, 0} -} - -type TimeOfDayDomain_IntegerTimeOfDayFormat int32 - -const ( - TimeOfDayDomain_FORMAT_UNKNOWN TimeOfDayDomain_IntegerTimeOfDayFormat = 0 - // Time values, containing hour/minute/second/nanos, encoded into 8-byte - // bit fields following the ZetaSQL convention: - // 6 5 4 3 2 1 - // MSB 3210987654321098765432109876543210987654321098765432109876543210 LSB - // | H || M || S ||---------- nanos -----------| - TimeOfDayDomain_PACKED_64_NANOS TimeOfDayDomain_IntegerTimeOfDayFormat = 1 -) - -// Enum value maps for TimeOfDayDomain_IntegerTimeOfDayFormat. -var ( - TimeOfDayDomain_IntegerTimeOfDayFormat_name = map[int32]string{ - 0: "FORMAT_UNKNOWN", - 1: "PACKED_64_NANOS", - } - TimeOfDayDomain_IntegerTimeOfDayFormat_value = map[string]int32{ - "FORMAT_UNKNOWN": 0, - "PACKED_64_NANOS": 1, - } -) - -func (x TimeOfDayDomain_IntegerTimeOfDayFormat) Enum() *TimeOfDayDomain_IntegerTimeOfDayFormat { - p := new(TimeOfDayDomain_IntegerTimeOfDayFormat) - *p = x - return p -} - -func (x TimeOfDayDomain_IntegerTimeOfDayFormat) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TimeOfDayDomain_IntegerTimeOfDayFormat) Descriptor() protoreflect.EnumDescriptor { - return file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[3].Descriptor() -} - -func (TimeOfDayDomain_IntegerTimeOfDayFormat) Type() protoreflect.EnumType { - return &file_tensorflow_metadata_proto_v0_schema_proto_enumTypes[3] -} - -func (x TimeOfDayDomain_IntegerTimeOfDayFormat) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *TimeOfDayDomain_IntegerTimeOfDayFormat) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = TimeOfDayDomain_IntegerTimeOfDayFormat(num) - return nil -} - -// Deprecated: Use TimeOfDayDomain_IntegerTimeOfDayFormat.Descriptor instead. -func (TimeOfDayDomain_IntegerTimeOfDayFormat) EnumDescriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{20, 0} -} - -// -// Message to represent schema information. -// NextID: 14 -type Schema struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Features described in this schema. - Feature []*Feature `protobuf:"bytes,1,rep,name=feature" json:"feature,omitempty"` - // Sparse features described in this schema. - SparseFeature []*SparseFeature `protobuf:"bytes,6,rep,name=sparse_feature,json=sparseFeature" json:"sparse_feature,omitempty"` - // Weighted features described in this schema. - WeightedFeature []*WeightedFeature `protobuf:"bytes,12,rep,name=weighted_feature,json=weightedFeature" json:"weighted_feature,omitempty"` - // declared as top-level features in . - // String domains referenced in the features. - StringDomain []*StringDomain `protobuf:"bytes,4,rep,name=string_domain,json=stringDomain" json:"string_domain,omitempty"` - // top level float domains that can be reused by features - FloatDomain []*FloatDomain `protobuf:"bytes,9,rep,name=float_domain,json=floatDomain" json:"float_domain,omitempty"` - // top level int domains that can be reused by features - IntDomain []*IntDomain `protobuf:"bytes,10,rep,name=int_domain,json=intDomain" json:"int_domain,omitempty"` - // Default environments for each feature. - // An environment represents both a type of location (e.g. a server or phone) - // and a time (e.g. right before model X is run). In the standard scenario, - // 99% of the features should be in the default environments TRAINING, - // SERVING, and the LABEL (or labels) AND WEIGHT is only available at TRAINING - // (not at serving). - // Other possible variations: - // 1. There may be TRAINING_MOBILE, SERVING_MOBILE, TRAINING_SERVICE, - // and SERVING_SERVICE. - // 2. If one is ensembling three models, where the predictions of the first - // three models are available for the ensemble model, there may be - // TRAINING, SERVING_INITIAL, SERVING_ENSEMBLE. - // See FeatureProto::not_in_environment and FeatureProto::in_environment. - DefaultEnvironment []string `protobuf:"bytes,5,rep,name=default_environment,json=defaultEnvironment" json:"default_environment,omitempty"` - // Additional information about the schema as a whole. Features may also - // be annotated individually. - Annotation *Annotation `protobuf:"bytes,8,opt,name=annotation" json:"annotation,omitempty"` - // Dataset-level constraints. This is currently used for specifying - // information about changes in num_examples. - DatasetConstraints *DatasetConstraints `protobuf:"bytes,11,opt,name=dataset_constraints,json=datasetConstraints" json:"dataset_constraints,omitempty"` - // TensorRepresentation groups. The keys are the names of the groups. - // Key "" (empty string) denotes the "default" group, which is what should - // be used when a group name is not provided. - // See the documentation at TensorRepresentationGroup for more info. - // Under development. DO NOT USE. - TensorRepresentationGroup map[string]*TensorRepresentationGroup `protobuf:"bytes,13,rep,name=tensor_representation_group,json=tensorRepresentationGroup" json:"tensor_representation_group,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` -} - -func (x *Schema) Reset() { - *x = Schema{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Schema) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Schema) ProtoMessage() {} - -func (x *Schema) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Schema.ProtoReflect.Descriptor instead. -func (*Schema) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{0} -} - -func (x *Schema) GetFeature() []*Feature { - if x != nil { - return x.Feature - } - return nil -} - -func (x *Schema) GetSparseFeature() []*SparseFeature { - if x != nil { - return x.SparseFeature - } - return nil -} - -func (x *Schema) GetWeightedFeature() []*WeightedFeature { - if x != nil { - return x.WeightedFeature - } - return nil -} - -func (x *Schema) GetStringDomain() []*StringDomain { - if x != nil { - return x.StringDomain - } - return nil -} - -func (x *Schema) GetFloatDomain() []*FloatDomain { - if x != nil { - return x.FloatDomain - } - return nil -} - -func (x *Schema) GetIntDomain() []*IntDomain { - if x != nil { - return x.IntDomain - } - return nil -} - -func (x *Schema) GetDefaultEnvironment() []string { - if x != nil { - return x.DefaultEnvironment - } - return nil -} - -func (x *Schema) GetAnnotation() *Annotation { - if x != nil { - return x.Annotation - } - return nil -} - -func (x *Schema) GetDatasetConstraints() *DatasetConstraints { - if x != nil { - return x.DatasetConstraints - } - return nil -} - -func (x *Schema) GetTensorRepresentationGroup() map[string]*TensorRepresentationGroup { - if x != nil { - return x.TensorRepresentationGroup - } - return nil -} - -// Describes schema-level information about a specific feature. -// NextID: 31 -type Feature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The name of the feature. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // required - // This field is no longer supported. Instead, use: - // lifecycle_stage: DEPRECATED - // TODO(b/111450258): remove this. - // - // Deprecated: Do not use. - Deprecated *bool `protobuf:"varint,2,opt,name=deprecated" json:"deprecated,omitempty"` - // Types that are assignable to PresenceConstraints: - // *Feature_Presence - // *Feature_GroupPresence - PresenceConstraints isFeature_PresenceConstraints `protobuf_oneof:"presence_constraints"` - // The shape of the feature which governs the number of values that appear in - // each example. - // - // Types that are assignable to ShapeType: - // *Feature_Shape - // *Feature_ValueCount - ShapeType isFeature_ShapeType `protobuf_oneof:"shape_type"` - // Physical type of the feature's values. - // Note that you can have: - // type: BYTES - // int_domain: { - // min: 0 - // max: 3 - // } - // This would be a field that is syntactically BYTES (i.e. strings), but - // semantically an int, i.e. it would be "0", "1", "2", or "3". - Type *FeatureType `protobuf:"varint,6,opt,name=type,enum=tensorflow.metadata.v0.FeatureType" json:"type,omitempty"` - // Domain for the values of the feature. - // - // Types that are assignable to DomainInfo: - // *Feature_Domain - // *Feature_IntDomain - // *Feature_FloatDomain - // *Feature_StringDomain - // *Feature_BoolDomain - // *Feature_StructDomain - // *Feature_NaturalLanguageDomain - // *Feature_ImageDomain - // *Feature_MidDomain - // *Feature_UrlDomain - // *Feature_TimeDomain - // *Feature_TimeOfDayDomain - DomainInfo isFeature_DomainInfo `protobuf_oneof:"domain_info"` - // Constraints on the distribution of the feature values. - // Currently only supported for StringDomains. - // TODO(b/69473628): Extend functionality to other domain types. - DistributionConstraints *DistributionConstraints `protobuf:"bytes,15,opt,name=distribution_constraints,json=distributionConstraints" json:"distribution_constraints,omitempty"` - // Additional information about the feature for documentation purpose. - Annotation *Annotation `protobuf:"bytes,16,opt,name=annotation" json:"annotation,omitempty"` - // Tests comparing the distribution to the associated serving data. - SkewComparator *FeatureComparator `protobuf:"bytes,18,opt,name=skew_comparator,json=skewComparator" json:"skew_comparator,omitempty"` - // Tests comparing the distribution between two consecutive spans (e.g. days). - DriftComparator *FeatureComparator `protobuf:"bytes,21,opt,name=drift_comparator,json=driftComparator" json:"drift_comparator,omitempty"` - // List of environments this feature is present in. - // Should be disjoint from not_in_environment. - // This feature is in environment "foo" if: - // ("foo" is in in_environment or default_environments) AND - // "foo" is not in not_in_environment. - // See Schema::default_environments. - InEnvironment []string `protobuf:"bytes,20,rep,name=in_environment,json=inEnvironment" json:"in_environment,omitempty"` - // List of environments this feature is not present in. - // Should be disjoint from of in_environment. - // See Schema::default_environments and in_environment. - NotInEnvironment []string `protobuf:"bytes,19,rep,name=not_in_environment,json=notInEnvironment" json:"not_in_environment,omitempty"` - // The lifecycle stage of a feature. It can also apply to its descendants. - // i.e., if a struct is DEPRECATED, its children are implicitly deprecated. - LifecycleStage *LifecycleStage `protobuf:"varint,22,opt,name=lifecycle_stage,json=lifecycleStage,enum=tensorflow.metadata.v0.LifecycleStage" json:"lifecycle_stage,omitempty"` -} - -func (x *Feature) Reset() { - *x = Feature{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Feature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Feature) ProtoMessage() {} - -func (x *Feature) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Feature.ProtoReflect.Descriptor instead. -func (*Feature) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{1} -} - -func (x *Feature) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -// Deprecated: Do not use. -func (x *Feature) GetDeprecated() bool { - if x != nil && x.Deprecated != nil { - return *x.Deprecated - } - return false -} - -func (m *Feature) GetPresenceConstraints() isFeature_PresenceConstraints { - if m != nil { - return m.PresenceConstraints - } - return nil -} - -func (x *Feature) GetPresence() *FeaturePresence { - if x, ok := x.GetPresenceConstraints().(*Feature_Presence); ok { - return x.Presence - } - return nil -} - -func (x *Feature) GetGroupPresence() *FeaturePresenceWithinGroup { - if x, ok := x.GetPresenceConstraints().(*Feature_GroupPresence); ok { - return x.GroupPresence - } - return nil -} - -func (m *Feature) GetShapeType() isFeature_ShapeType { - if m != nil { - return m.ShapeType - } - return nil -} - -func (x *Feature) GetShape() *FixedShape { - if x, ok := x.GetShapeType().(*Feature_Shape); ok { - return x.Shape - } - return nil -} - -func (x *Feature) GetValueCount() *ValueCount { - if x, ok := x.GetShapeType().(*Feature_ValueCount); ok { - return x.ValueCount - } - return nil -} - -func (x *Feature) GetType() FeatureType { - if x != nil && x.Type != nil { - return *x.Type - } - return FeatureType_TYPE_UNKNOWN -} - -func (m *Feature) GetDomainInfo() isFeature_DomainInfo { - if m != nil { - return m.DomainInfo - } - return nil -} - -func (x *Feature) GetDomain() string { - if x, ok := x.GetDomainInfo().(*Feature_Domain); ok { - return x.Domain - } - return "" -} - -func (x *Feature) GetIntDomain() *IntDomain { - if x, ok := x.GetDomainInfo().(*Feature_IntDomain); ok { - return x.IntDomain - } - return nil -} - -func (x *Feature) GetFloatDomain() *FloatDomain { - if x, ok := x.GetDomainInfo().(*Feature_FloatDomain); ok { - return x.FloatDomain - } - return nil -} - -func (x *Feature) GetStringDomain() *StringDomain { - if x, ok := x.GetDomainInfo().(*Feature_StringDomain); ok { - return x.StringDomain - } - return nil -} - -func (x *Feature) GetBoolDomain() *BoolDomain { - if x, ok := x.GetDomainInfo().(*Feature_BoolDomain); ok { - return x.BoolDomain - } - return nil -} - -func (x *Feature) GetStructDomain() *StructDomain { - if x, ok := x.GetDomainInfo().(*Feature_StructDomain); ok { - return x.StructDomain - } - return nil -} - -func (x *Feature) GetNaturalLanguageDomain() *NaturalLanguageDomain { - if x, ok := x.GetDomainInfo().(*Feature_NaturalLanguageDomain); ok { - return x.NaturalLanguageDomain - } - return nil -} - -func (x *Feature) GetImageDomain() *ImageDomain { - if x, ok := x.GetDomainInfo().(*Feature_ImageDomain); ok { - return x.ImageDomain - } - return nil -} - -func (x *Feature) GetMidDomain() *MIDDomain { - if x, ok := x.GetDomainInfo().(*Feature_MidDomain); ok { - return x.MidDomain - } - return nil -} - -func (x *Feature) GetUrlDomain() *URLDomain { - if x, ok := x.GetDomainInfo().(*Feature_UrlDomain); ok { - return x.UrlDomain - } - return nil -} - -func (x *Feature) GetTimeDomain() *TimeDomain { - if x, ok := x.GetDomainInfo().(*Feature_TimeDomain); ok { - return x.TimeDomain - } - return nil -} - -func (x *Feature) GetTimeOfDayDomain() *TimeOfDayDomain { - if x, ok := x.GetDomainInfo().(*Feature_TimeOfDayDomain); ok { - return x.TimeOfDayDomain - } - return nil -} - -func (x *Feature) GetDistributionConstraints() *DistributionConstraints { - if x != nil { - return x.DistributionConstraints - } - return nil -} - -func (x *Feature) GetAnnotation() *Annotation { - if x != nil { - return x.Annotation - } - return nil -} - -func (x *Feature) GetSkewComparator() *FeatureComparator { - if x != nil { - return x.SkewComparator - } - return nil -} - -func (x *Feature) GetDriftComparator() *FeatureComparator { - if x != nil { - return x.DriftComparator - } - return nil -} - -func (x *Feature) GetInEnvironment() []string { - if x != nil { - return x.InEnvironment - } - return nil -} - -func (x *Feature) GetNotInEnvironment() []string { - if x != nil { - return x.NotInEnvironment - } - return nil -} - -func (x *Feature) GetLifecycleStage() LifecycleStage { - if x != nil && x.LifecycleStage != nil { - return *x.LifecycleStage - } - return LifecycleStage_UNKNOWN_STAGE -} - -type isFeature_PresenceConstraints interface { - isFeature_PresenceConstraints() -} - -type Feature_Presence struct { - // Constraints on the presence of this feature in the examples. - Presence *FeaturePresence `protobuf:"bytes,14,opt,name=presence,oneof"` -} - -type Feature_GroupPresence struct { - // Only used in the context of a "group" context, e.g., inside a sequence. - GroupPresence *FeaturePresenceWithinGroup `protobuf:"bytes,17,opt,name=group_presence,json=groupPresence,oneof"` -} - -func (*Feature_Presence) isFeature_PresenceConstraints() {} - -func (*Feature_GroupPresence) isFeature_PresenceConstraints() {} - -type isFeature_ShapeType interface { - isFeature_ShapeType() -} - -type Feature_Shape struct { - // The feature has a fixed shape corresponding to a multi-dimensional - // tensor. - Shape *FixedShape `protobuf:"bytes,23,opt,name=shape,oneof"` -} - -type Feature_ValueCount struct { - // The feature doesn't have a well defined shape. All we know are limits on - // the minimum and maximum number of values. - ValueCount *ValueCount `protobuf:"bytes,5,opt,name=value_count,json=valueCount,oneof"` -} - -func (*Feature_Shape) isFeature_ShapeType() {} - -func (*Feature_ValueCount) isFeature_ShapeType() {} - -type isFeature_DomainInfo interface { - isFeature_DomainInfo() -} - -type Feature_Domain struct { - // Reference to a domain defined at the schema level. - Domain string `protobuf:"bytes,7,opt,name=domain,oneof"` -} - -type Feature_IntDomain struct { - // Inline definitions of domains. - IntDomain *IntDomain `protobuf:"bytes,9,opt,name=int_domain,json=intDomain,oneof"` -} - -type Feature_FloatDomain struct { - FloatDomain *FloatDomain `protobuf:"bytes,10,opt,name=float_domain,json=floatDomain,oneof"` -} - -type Feature_StringDomain struct { - StringDomain *StringDomain `protobuf:"bytes,11,opt,name=string_domain,json=stringDomain,oneof"` -} - -type Feature_BoolDomain struct { - BoolDomain *BoolDomain `protobuf:"bytes,13,opt,name=bool_domain,json=boolDomain,oneof"` -} - -type Feature_StructDomain struct { - StructDomain *StructDomain `protobuf:"bytes,29,opt,name=struct_domain,json=structDomain,oneof"` -} - -type Feature_NaturalLanguageDomain struct { - // Supported semantic domains. - NaturalLanguageDomain *NaturalLanguageDomain `protobuf:"bytes,24,opt,name=natural_language_domain,json=naturalLanguageDomain,oneof"` -} - -type Feature_ImageDomain struct { - ImageDomain *ImageDomain `protobuf:"bytes,25,opt,name=image_domain,json=imageDomain,oneof"` -} - -type Feature_MidDomain struct { - MidDomain *MIDDomain `protobuf:"bytes,26,opt,name=mid_domain,json=midDomain,oneof"` -} - -type Feature_UrlDomain struct { - UrlDomain *URLDomain `protobuf:"bytes,27,opt,name=url_domain,json=urlDomain,oneof"` -} - -type Feature_TimeDomain struct { - TimeDomain *TimeDomain `protobuf:"bytes,28,opt,name=time_domain,json=timeDomain,oneof"` -} - -type Feature_TimeOfDayDomain struct { - TimeOfDayDomain *TimeOfDayDomain `protobuf:"bytes,30,opt,name=time_of_day_domain,json=timeOfDayDomain,oneof"` -} - -func (*Feature_Domain) isFeature_DomainInfo() {} - -func (*Feature_IntDomain) isFeature_DomainInfo() {} - -func (*Feature_FloatDomain) isFeature_DomainInfo() {} - -func (*Feature_StringDomain) isFeature_DomainInfo() {} - -func (*Feature_BoolDomain) isFeature_DomainInfo() {} - -func (*Feature_StructDomain) isFeature_DomainInfo() {} - -func (*Feature_NaturalLanguageDomain) isFeature_DomainInfo() {} - -func (*Feature_ImageDomain) isFeature_DomainInfo() {} - -func (*Feature_MidDomain) isFeature_DomainInfo() {} - -func (*Feature_UrlDomain) isFeature_DomainInfo() {} - -func (*Feature_TimeDomain) isFeature_DomainInfo() {} - -func (*Feature_TimeOfDayDomain) isFeature_DomainInfo() {} - -// Additional information about the schema or about a feature. -type Annotation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Tags can be used to mark features. For example, tag on user_age feature can - // be `user_feature`, tag on user_country feature can be `location_feature`, - // `user_feature`. - Tag []string `protobuf:"bytes,1,rep,name=tag" json:"tag,omitempty"` - // Free-text comments. This can be used as a description of the feature, - // developer notes etc. - Comment []string `protobuf:"bytes,2,rep,name=comment" json:"comment,omitempty"` - // Application-specific metadata may be attached here. - ExtraMetadata []*anypb.Any `protobuf:"bytes,3,rep,name=extra_metadata,json=extraMetadata" json:"extra_metadata,omitempty"` -} - -func (x *Annotation) Reset() { - *x = Annotation{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Annotation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Annotation) ProtoMessage() {} - -func (x *Annotation) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Annotation.ProtoReflect.Descriptor instead. -func (*Annotation) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{2} -} - -func (x *Annotation) GetTag() []string { - if x != nil { - return x.Tag - } - return nil -} - -func (x *Annotation) GetComment() []string { - if x != nil { - return x.Comment - } - return nil -} - -func (x *Annotation) GetExtraMetadata() []*anypb.Any { - if x != nil { - return x.ExtraMetadata - } - return nil -} - -// Checks that the ratio of the current value to the previous value is not below -// the min_fraction_threshold or above the max_fraction_threshold. That is, -// previous value * min_fraction_threshold <= current value <= -// previous value * max_fraction_threshold. -// To specify that the value cannot change, set both min_fraction_threshold and -// max_fraction_threshold to 1.0. -type NumericValueComparator struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MinFractionThreshold *float64 `protobuf:"fixed64,1,opt,name=min_fraction_threshold,json=minFractionThreshold" json:"min_fraction_threshold,omitempty"` - MaxFractionThreshold *float64 `protobuf:"fixed64,2,opt,name=max_fraction_threshold,json=maxFractionThreshold" json:"max_fraction_threshold,omitempty"` -} - -func (x *NumericValueComparator) Reset() { - *x = NumericValueComparator{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NumericValueComparator) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NumericValueComparator) ProtoMessage() {} - -func (x *NumericValueComparator) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NumericValueComparator.ProtoReflect.Descriptor instead. -func (*NumericValueComparator) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{3} -} - -func (x *NumericValueComparator) GetMinFractionThreshold() float64 { - if x != nil && x.MinFractionThreshold != nil { - return *x.MinFractionThreshold - } - return 0 -} - -func (x *NumericValueComparator) GetMaxFractionThreshold() float64 { - if x != nil && x.MaxFractionThreshold != nil { - return *x.MaxFractionThreshold - } - return 0 -} - -// Constraints on the entire dataset. -type DatasetConstraints struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Tests differences in number of examples between the current data and the - // previous span. - NumExamplesDriftComparator *NumericValueComparator `protobuf:"bytes,1,opt,name=num_examples_drift_comparator,json=numExamplesDriftComparator" json:"num_examples_drift_comparator,omitempty"` - // Tests comparisions in number of examples between the current data and the - // previous version of that data. - NumExamplesVersionComparator *NumericValueComparator `protobuf:"bytes,2,opt,name=num_examples_version_comparator,json=numExamplesVersionComparator" json:"num_examples_version_comparator,omitempty"` - // Minimum number of examples in the dataset. - MinExamplesCount *int64 `protobuf:"varint,3,opt,name=min_examples_count,json=minExamplesCount" json:"min_examples_count,omitempty"` -} - -func (x *DatasetConstraints) Reset() { - *x = DatasetConstraints{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DatasetConstraints) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DatasetConstraints) ProtoMessage() {} - -func (x *DatasetConstraints) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DatasetConstraints.ProtoReflect.Descriptor instead. -func (*DatasetConstraints) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{4} -} - -func (x *DatasetConstraints) GetNumExamplesDriftComparator() *NumericValueComparator { - if x != nil { - return x.NumExamplesDriftComparator - } - return nil -} - -func (x *DatasetConstraints) GetNumExamplesVersionComparator() *NumericValueComparator { - if x != nil { - return x.NumExamplesVersionComparator - } - return nil -} - -func (x *DatasetConstraints) GetMinExamplesCount() int64 { - if x != nil && x.MinExamplesCount != nil { - return *x.MinExamplesCount - } - return 0 -} - -// Specifies a fixed shape for the feature's values. The immediate implication -// is that each feature has a fixed number of values. Moreover, these values -// can be parsed in a multi-dimensional tensor using the specified axis sizes. -// The FixedShape defines a lexicographical ordering of the data. For instance, -// if there is a FixedShape { -// dim {size:3} dim {size:2} -// } -// then tensor[0][0]=field[0] -// then tensor[0][1]=field[1] -// then tensor[1][0]=field[2] -// then tensor[1][1]=field[3] -// then tensor[2][0]=field[4] -// then tensor[2][1]=field[5] -// -// The FixedShape message is identical with the TensorFlow TensorShape proto -// message. -type FixedShape struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The dimensions that define the shape. The total number of values in each - // example is the product of sizes of each dimension. - Dim []*FixedShape_Dim `protobuf:"bytes,2,rep,name=dim" json:"dim,omitempty"` -} - -func (x *FixedShape) Reset() { - *x = FixedShape{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FixedShape) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FixedShape) ProtoMessage() {} - -func (x *FixedShape) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FixedShape.ProtoReflect.Descriptor instead. -func (*FixedShape) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{5} -} - -func (x *FixedShape) GetDim() []*FixedShape_Dim { - if x != nil { - return x.Dim - } - return nil -} - -// Limits on maximum and minimum number of values in a -// single example (when the feature is present). Use this when the minimum -// value count can be different than the maximum value count. Otherwise prefer -// FixedShape. -type ValueCount struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Min *int64 `protobuf:"varint,1,opt,name=min" json:"min,omitempty"` - Max *int64 `protobuf:"varint,2,opt,name=max" json:"max,omitempty"` -} - -func (x *ValueCount) Reset() { - *x = ValueCount{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ValueCount) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ValueCount) ProtoMessage() {} - -func (x *ValueCount) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ValueCount.ProtoReflect.Descriptor instead. -func (*ValueCount) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{6} -} - -func (x *ValueCount) GetMin() int64 { - if x != nil && x.Min != nil { - return *x.Min - } - return 0 -} - -func (x *ValueCount) GetMax() int64 { - if x != nil && x.Max != nil { - return *x.Max - } - return 0 -} - -// Represents a weighted feature that is encoded as a combination of raw base -// features. The `weight_feature` should be a float feature with identical -// shape as the `feature`. This is useful for representing weights associated -// with categorical tokens (e.g. a TFIDF weight associated with each token). -// TODO(b/142122960): Handle WeightedCategorical end to end in TFX (validation, -// TFX Unit Testing, etc) -type WeightedFeature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name for the weighted feature. This should not clash with other features in - // the same schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // required - // Path of a base feature to be weighted. Required. - Feature *Path `protobuf:"bytes,2,opt,name=feature" json:"feature,omitempty"` - // Path of weight feature to associate with the base feature. Must be same - // shape as feature. Required. - WeightFeature *Path `protobuf:"bytes,3,opt,name=weight_feature,json=weightFeature" json:"weight_feature,omitempty"` - // The lifecycle_stage determines where a feature is expected to be used, - // and therefore how important issues with it are. - LifecycleStage *LifecycleStage `protobuf:"varint,4,opt,name=lifecycle_stage,json=lifecycleStage,enum=tensorflow.metadata.v0.LifecycleStage" json:"lifecycle_stage,omitempty"` -} - -func (x *WeightedFeature) Reset() { - *x = WeightedFeature{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WeightedFeature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WeightedFeature) ProtoMessage() {} - -func (x *WeightedFeature) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WeightedFeature.ProtoReflect.Descriptor instead. -func (*WeightedFeature) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{7} -} - -func (x *WeightedFeature) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -func (x *WeightedFeature) GetFeature() *Path { - if x != nil { - return x.Feature - } - return nil -} - -func (x *WeightedFeature) GetWeightFeature() *Path { - if x != nil { - return x.WeightFeature - } - return nil -} - -func (x *WeightedFeature) GetLifecycleStage() LifecycleStage { - if x != nil && x.LifecycleStage != nil { - return *x.LifecycleStage - } - return LifecycleStage_UNKNOWN_STAGE -} - -// A sparse feature represents a sparse tensor that is encoded with a -// combination of raw features, namely index features and a value feature. Each -// index feature defines a list of indices in a different dimension. -type SparseFeature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name for the sparse feature. This should not clash with other features in - // the same schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // required - // This field is no longer supported. Instead, use: - // lifecycle_stage: DEPRECATED - // TODO(b/111450258): remove this. - // - // Deprecated: Do not use. - Deprecated *bool `protobuf:"varint,2,opt,name=deprecated" json:"deprecated,omitempty"` - // The lifecycle_stage determines where a feature is expected to be used, - // and therefore how important issues with it are. - LifecycleStage *LifecycleStage `protobuf:"varint,7,opt,name=lifecycle_stage,json=lifecycleStage,enum=tensorflow.metadata.v0.LifecycleStage" json:"lifecycle_stage,omitempty"` - // Constraints on the presence of this feature in examples. - // Deprecated, this is inferred by the referred features. - // - // Deprecated: Do not use. - Presence *FeaturePresence `protobuf:"bytes,4,opt,name=presence" json:"presence,omitempty"` - // Shape of the sparse tensor that this SparseFeature represents. - // Currently not supported. - // TODO(b/109669962): Consider deriving this from the referred features. - DenseShape *FixedShape `protobuf:"bytes,5,opt,name=dense_shape,json=denseShape" json:"dense_shape,omitempty"` - // Features that represent indexes. Should be integers >= 0. - IndexFeature []*SparseFeature_IndexFeature `protobuf:"bytes,6,rep,name=index_feature,json=indexFeature" json:"index_feature,omitempty"` // at least one - // If true then the index values are already sorted lexicographically. - IsSorted *bool `protobuf:"varint,8,opt,name=is_sorted,json=isSorted" json:"is_sorted,omitempty"` - ValueFeature *SparseFeature_ValueFeature `protobuf:"bytes,9,opt,name=value_feature,json=valueFeature" json:"value_feature,omitempty"` // required - // Type of value feature. - // Deprecated, this is inferred by the referred features. - // - // Deprecated: Do not use. - Type *FeatureType `protobuf:"varint,10,opt,name=type,enum=tensorflow.metadata.v0.FeatureType" json:"type,omitempty"` -} - -func (x *SparseFeature) Reset() { - *x = SparseFeature{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SparseFeature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SparseFeature) ProtoMessage() {} - -func (x *SparseFeature) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SparseFeature.ProtoReflect.Descriptor instead. -func (*SparseFeature) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{8} -} - -func (x *SparseFeature) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -// Deprecated: Do not use. -func (x *SparseFeature) GetDeprecated() bool { - if x != nil && x.Deprecated != nil { - return *x.Deprecated - } - return false -} - -func (x *SparseFeature) GetLifecycleStage() LifecycleStage { - if x != nil && x.LifecycleStage != nil { - return *x.LifecycleStage - } - return LifecycleStage_UNKNOWN_STAGE -} - -// Deprecated: Do not use. -func (x *SparseFeature) GetPresence() *FeaturePresence { - if x != nil { - return x.Presence - } - return nil -} - -func (x *SparseFeature) GetDenseShape() *FixedShape { - if x != nil { - return x.DenseShape - } - return nil -} - -func (x *SparseFeature) GetIndexFeature() []*SparseFeature_IndexFeature { - if x != nil { - return x.IndexFeature - } - return nil -} - -func (x *SparseFeature) GetIsSorted() bool { - if x != nil && x.IsSorted != nil { - return *x.IsSorted - } - return false -} - -func (x *SparseFeature) GetValueFeature() *SparseFeature_ValueFeature { - if x != nil { - return x.ValueFeature - } - return nil -} - -// Deprecated: Do not use. -func (x *SparseFeature) GetType() FeatureType { - if x != nil && x.Type != nil { - return *x.Type - } - return FeatureType_TYPE_UNKNOWN -} - -// Models constraints on the distribution of a feature's values. -// TODO(martinz): replace min_domain_mass with max_off_domain (but slowly). -type DistributionConstraints struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The minimum fraction (in [0,1]) of values across all examples that - // should come from the feature's domain, e.g.: - // 1.0 => All values must come from the domain. - // .9 => At least 90% of the values must come from the domain. - MinDomainMass *float64 `protobuf:"fixed64,1,opt,name=min_domain_mass,json=minDomainMass,def=1" json:"min_domain_mass,omitempty"` -} - -// Default values for DistributionConstraints fields. -const ( - Default_DistributionConstraints_MinDomainMass = float64(1) -) - -func (x *DistributionConstraints) Reset() { - *x = DistributionConstraints{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DistributionConstraints) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DistributionConstraints) ProtoMessage() {} - -func (x *DistributionConstraints) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DistributionConstraints.ProtoReflect.Descriptor instead. -func (*DistributionConstraints) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{9} -} - -func (x *DistributionConstraints) GetMinDomainMass() float64 { - if x != nil && x.MinDomainMass != nil { - return *x.MinDomainMass - } - return Default_DistributionConstraints_MinDomainMass -} - -// Encodes information for domains of integer values. -// Note that FeatureType could be either INT or BYTES. -type IntDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Id of the domain. Required if the domain is defined at the schema level. If - // so, then the name must be unique within the schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // Min and max values for the domain. - Min *int64 `protobuf:"varint,3,opt,name=min" json:"min,omitempty"` - Max *int64 `protobuf:"varint,4,opt,name=max" json:"max,omitempty"` - // If true then the domain encodes categorical values (i.e., ids) rather than - // ordinal values. - IsCategorical *bool `protobuf:"varint,5,opt,name=is_categorical,json=isCategorical" json:"is_categorical,omitempty"` -} - -func (x *IntDomain) Reset() { - *x = IntDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntDomain) ProtoMessage() {} - -func (x *IntDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntDomain.ProtoReflect.Descriptor instead. -func (*IntDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{10} -} - -func (x *IntDomain) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -func (x *IntDomain) GetMin() int64 { - if x != nil && x.Min != nil { - return *x.Min - } - return 0 -} - -func (x *IntDomain) GetMax() int64 { - if x != nil && x.Max != nil { - return *x.Max - } - return 0 -} - -func (x *IntDomain) GetIsCategorical() bool { - if x != nil && x.IsCategorical != nil { - return *x.IsCategorical - } - return false -} - -// Encodes information for domains of float values. -// Note that FeatureType could be either INT or BYTES. -type FloatDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Id of the domain. Required if the domain is defined at the schema level. If - // so, then the name must be unique within the schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // Min and max values of the domain. - Min *float32 `protobuf:"fixed32,3,opt,name=min" json:"min,omitempty"` - Max *float32 `protobuf:"fixed32,4,opt,name=max" json:"max,omitempty"` -} - -func (x *FloatDomain) Reset() { - *x = FloatDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FloatDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FloatDomain) ProtoMessage() {} - -func (x *FloatDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FloatDomain.ProtoReflect.Descriptor instead. -func (*FloatDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{11} -} - -func (x *FloatDomain) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -func (x *FloatDomain) GetMin() float32 { - if x != nil && x.Min != nil { - return *x.Min - } - return 0 -} - -func (x *FloatDomain) GetMax() float32 { - if x != nil && x.Max != nil { - return *x.Max - } - return 0 -} - -// Domain for a recursive struct. -// NOTE: If a feature with a StructDomain is deprecated, then all the -// child features (features and sparse_features of the StructDomain) are also -// considered to be deprecated. Similarly child features can only be in -// environments of the parent feature. -type StructDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Feature []*Feature `protobuf:"bytes,1,rep,name=feature" json:"feature,omitempty"` - SparseFeature []*SparseFeature `protobuf:"bytes,2,rep,name=sparse_feature,json=sparseFeature" json:"sparse_feature,omitempty"` -} - -func (x *StructDomain) Reset() { - *x = StructDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StructDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StructDomain) ProtoMessage() {} - -func (x *StructDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StructDomain.ProtoReflect.Descriptor instead. -func (*StructDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{12} -} - -func (x *StructDomain) GetFeature() []*Feature { - if x != nil { - return x.Feature - } - return nil -} - -func (x *StructDomain) GetSparseFeature() []*SparseFeature { - if x != nil { - return x.SparseFeature - } - return nil -} - -// Encodes information for domains of string values. -type StringDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Id of the domain. Required if the domain is defined at the schema level. If - // so, then the name must be unique within the schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // The values appearing in the domain. - Value []string `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` -} - -func (x *StringDomain) Reset() { - *x = StringDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StringDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StringDomain) ProtoMessage() {} - -func (x *StringDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StringDomain.ProtoReflect.Descriptor instead. -func (*StringDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{13} -} - -func (x *StringDomain) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -func (x *StringDomain) GetValue() []string { - if x != nil { - return x.Value - } - return nil -} - -// Encodes information about the domain of a boolean attribute that encodes its -// TRUE/FALSE values as strings, or 0=false, 1=true. -// Note that FeatureType could be either INT or BYTES. -type BoolDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Id of the domain. Required if the domain is defined at the schema level. If - // so, then the name must be unique within the schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // Strings values for TRUE/FALSE. - TrueValue *string `protobuf:"bytes,2,opt,name=true_value,json=trueValue" json:"true_value,omitempty"` - FalseValue *string `protobuf:"bytes,3,opt,name=false_value,json=falseValue" json:"false_value,omitempty"` -} - -func (x *BoolDomain) Reset() { - *x = BoolDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BoolDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BoolDomain) ProtoMessage() {} - -func (x *BoolDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BoolDomain.ProtoReflect.Descriptor instead. -func (*BoolDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{14} -} - -func (x *BoolDomain) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -func (x *BoolDomain) GetTrueValue() string { - if x != nil && x.TrueValue != nil { - return *x.TrueValue - } - return "" -} - -func (x *BoolDomain) GetFalseValue() string { - if x != nil && x.FalseValue != nil { - return *x.FalseValue - } - return "" -} - -// Natural language text. -type NaturalLanguageDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *NaturalLanguageDomain) Reset() { - *x = NaturalLanguageDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NaturalLanguageDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NaturalLanguageDomain) ProtoMessage() {} - -func (x *NaturalLanguageDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NaturalLanguageDomain.ProtoReflect.Descriptor instead. -func (*NaturalLanguageDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{15} -} - -// Image data. -type ImageDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ImageDomain) Reset() { - *x = ImageDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ImageDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ImageDomain) ProtoMessage() {} - -func (x *ImageDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ImageDomain.ProtoReflect.Descriptor instead. -func (*ImageDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{16} -} - -// Knowledge graph ID, see: https://www.wikidata.org/wiki/Property:P646 -type MIDDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *MIDDomain) Reset() { - *x = MIDDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MIDDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MIDDomain) ProtoMessage() {} - -func (x *MIDDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MIDDomain.ProtoReflect.Descriptor instead. -func (*MIDDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{17} -} - -// A URL, see: https://en.wikipedia.org/wiki/URL -type URLDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *URLDomain) Reset() { - *x = URLDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *URLDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*URLDomain) ProtoMessage() {} - -func (x *URLDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use URLDomain.ProtoReflect.Descriptor instead. -func (*URLDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{18} -} - -// Time or date representation. -type TimeDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Format: - // *TimeDomain_StringFormat - // *TimeDomain_IntegerFormat - Format isTimeDomain_Format `protobuf_oneof:"format"` -} - -func (x *TimeDomain) Reset() { - *x = TimeDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TimeDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TimeDomain) ProtoMessage() {} - -func (x *TimeDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TimeDomain.ProtoReflect.Descriptor instead. -func (*TimeDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{19} -} - -func (m *TimeDomain) GetFormat() isTimeDomain_Format { - if m != nil { - return m.Format - } - return nil -} - -func (x *TimeDomain) GetStringFormat() string { - if x, ok := x.GetFormat().(*TimeDomain_StringFormat); ok { - return x.StringFormat - } - return "" -} - -func (x *TimeDomain) GetIntegerFormat() TimeDomain_IntegerTimeFormat { - if x, ok := x.GetFormat().(*TimeDomain_IntegerFormat); ok { - return x.IntegerFormat - } - return TimeDomain_FORMAT_UNKNOWN -} - -type isTimeDomain_Format interface { - isTimeDomain_Format() -} - -type TimeDomain_StringFormat struct { - // Expected format that contains a combination of regular characters and - // special format specifiers. Format specifiers are a subset of the - // strptime standard. - StringFormat string `protobuf:"bytes,1,opt,name=string_format,json=stringFormat,oneof"` -} - -type TimeDomain_IntegerFormat struct { - // Expected format of integer times. - IntegerFormat TimeDomain_IntegerTimeFormat `protobuf:"varint,2,opt,name=integer_format,json=integerFormat,enum=tensorflow.metadata.v0.TimeDomain_IntegerTimeFormat,oneof"` -} - -func (*TimeDomain_StringFormat) isTimeDomain_Format() {} - -func (*TimeDomain_IntegerFormat) isTimeDomain_Format() {} - -// Time of day, without a particular date. -type TimeOfDayDomain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Format: - // *TimeOfDayDomain_StringFormat - // *TimeOfDayDomain_IntegerFormat - Format isTimeOfDayDomain_Format `protobuf_oneof:"format"` -} - -func (x *TimeOfDayDomain) Reset() { - *x = TimeOfDayDomain{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TimeOfDayDomain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TimeOfDayDomain) ProtoMessage() {} - -func (x *TimeOfDayDomain) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TimeOfDayDomain.ProtoReflect.Descriptor instead. -func (*TimeOfDayDomain) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{20} -} - -func (m *TimeOfDayDomain) GetFormat() isTimeOfDayDomain_Format { - if m != nil { - return m.Format - } - return nil -} - -func (x *TimeOfDayDomain) GetStringFormat() string { - if x, ok := x.GetFormat().(*TimeOfDayDomain_StringFormat); ok { - return x.StringFormat - } - return "" -} - -func (x *TimeOfDayDomain) GetIntegerFormat() TimeOfDayDomain_IntegerTimeOfDayFormat { - if x, ok := x.GetFormat().(*TimeOfDayDomain_IntegerFormat); ok { - return x.IntegerFormat - } - return TimeOfDayDomain_FORMAT_UNKNOWN -} - -type isTimeOfDayDomain_Format interface { - isTimeOfDayDomain_Format() -} - -type TimeOfDayDomain_StringFormat struct { - // Expected format that contains a combination of regular characters and - // special format specifiers. Format specifiers are a subset of the - // strptime standard. - StringFormat string `protobuf:"bytes,1,opt,name=string_format,json=stringFormat,oneof"` -} - -type TimeOfDayDomain_IntegerFormat struct { - // Expected format of integer times. - IntegerFormat TimeOfDayDomain_IntegerTimeOfDayFormat `protobuf:"varint,2,opt,name=integer_format,json=integerFormat,enum=tensorflow.metadata.v0.TimeOfDayDomain_IntegerTimeOfDayFormat,oneof"` -} - -func (*TimeOfDayDomain_StringFormat) isTimeOfDayDomain_Format() {} - -func (*TimeOfDayDomain_IntegerFormat) isTimeOfDayDomain_Format() {} - -// Describes constraints on the presence of the feature in the data. -type FeaturePresence struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Minimum fraction of examples that have this feature. - MinFraction *float64 `protobuf:"fixed64,1,opt,name=min_fraction,json=minFraction" json:"min_fraction,omitempty"` - // Minimum number of examples that have this feature. - MinCount *int64 `protobuf:"varint,2,opt,name=min_count,json=minCount" json:"min_count,omitempty"` -} - -func (x *FeaturePresence) Reset() { - *x = FeaturePresence{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeaturePresence) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeaturePresence) ProtoMessage() {} - -func (x *FeaturePresence) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeaturePresence.ProtoReflect.Descriptor instead. -func (*FeaturePresence) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{21} -} - -func (x *FeaturePresence) GetMinFraction() float64 { - if x != nil && x.MinFraction != nil { - return *x.MinFraction - } - return 0 -} - -func (x *FeaturePresence) GetMinCount() int64 { - if x != nil && x.MinCount != nil { - return *x.MinCount - } - return 0 -} - -// Records constraints on the presence of a feature inside a "group" context -// (e.g., .presence inside a group of features that define a sequence). -type FeaturePresenceWithinGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Required *bool `protobuf:"varint,1,opt,name=required" json:"required,omitempty"` -} - -func (x *FeaturePresenceWithinGroup) Reset() { - *x = FeaturePresenceWithinGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeaturePresenceWithinGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeaturePresenceWithinGroup) ProtoMessage() {} - -func (x *FeaturePresenceWithinGroup) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeaturePresenceWithinGroup.ProtoReflect.Descriptor instead. -func (*FeaturePresenceWithinGroup) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{22} -} - -func (x *FeaturePresenceWithinGroup) GetRequired() bool { - if x != nil && x.Required != nil { - return *x.Required - } - return false -} - -// Checks that the L-infinity norm is below a certain threshold between the -// two discrete distributions. Since this is applied to a FeatureNameStatistics, -// it only considers the top k. -// L_infty(p,q) = max_i |p_i-q_i| -type InfinityNorm struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The InfinityNorm is in the interval [0.0, 1.0] so sensible bounds should - // be in the interval [0.0, 1.0). - Threshold *float64 `protobuf:"fixed64,1,opt,name=threshold" json:"threshold,omitempty"` -} - -func (x *InfinityNorm) Reset() { - *x = InfinityNorm{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InfinityNorm) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InfinityNorm) ProtoMessage() {} - -func (x *InfinityNorm) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InfinityNorm.ProtoReflect.Descriptor instead. -func (*InfinityNorm) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{23} -} - -func (x *InfinityNorm) GetThreshold() float64 { - if x != nil && x.Threshold != nil { - return *x.Threshold - } - return 0 -} - -type FeatureComparator struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - InfinityNorm *InfinityNorm `protobuf:"bytes,1,opt,name=infinity_norm,json=infinityNorm" json:"infinity_norm,omitempty"` -} - -func (x *FeatureComparator) Reset() { - *x = FeatureComparator{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureComparator) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureComparator) ProtoMessage() {} - -func (x *FeatureComparator) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureComparator.ProtoReflect.Descriptor instead. -func (*FeatureComparator) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{24} -} - -func (x *FeatureComparator) GetInfinityNorm() *InfinityNorm { - if x != nil { - return x.InfinityNorm - } - return nil -} - -// A TensorRepresentation captures the intent for converting columns in a -// dataset to TensorFlow Tensors (or more generally, tf.CompositeTensors). -// Note that one tf.CompositeTensor may consist of data from multiple columns, -// for example, a N-dimensional tf.SparseTensor may need N + 1 columns to -// provide the sparse indices and values. -// Note that the "column name" that a TensorRepresentation needs is a -// string, not a Path -- it means that the column name identifies a top-level -// Feature in the schema (i.e. you cannot specify a Feature nested in a STRUCT -// Feature). -type TensorRepresentation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Kind: - // *TensorRepresentation_DenseTensor_ - // *TensorRepresentation_VarlenSparseTensor - // *TensorRepresentation_SparseTensor_ - Kind isTensorRepresentation_Kind `protobuf_oneof:"kind"` -} - -func (x *TensorRepresentation) Reset() { - *x = TensorRepresentation{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TensorRepresentation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TensorRepresentation) ProtoMessage() {} - -func (x *TensorRepresentation) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TensorRepresentation.ProtoReflect.Descriptor instead. -func (*TensorRepresentation) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{25} -} - -func (m *TensorRepresentation) GetKind() isTensorRepresentation_Kind { - if m != nil { - return m.Kind - } - return nil -} - -func (x *TensorRepresentation) GetDenseTensor() *TensorRepresentation_DenseTensor { - if x, ok := x.GetKind().(*TensorRepresentation_DenseTensor_); ok { - return x.DenseTensor - } - return nil -} - -func (x *TensorRepresentation) GetVarlenSparseTensor() *TensorRepresentation_VarLenSparseTensor { - if x, ok := x.GetKind().(*TensorRepresentation_VarlenSparseTensor); ok { - return x.VarlenSparseTensor - } - return nil -} - -func (x *TensorRepresentation) GetSparseTensor() *TensorRepresentation_SparseTensor { - if x, ok := x.GetKind().(*TensorRepresentation_SparseTensor_); ok { - return x.SparseTensor - } - return nil -} - -type isTensorRepresentation_Kind interface { - isTensorRepresentation_Kind() -} - -type TensorRepresentation_DenseTensor_ struct { - DenseTensor *TensorRepresentation_DenseTensor `protobuf:"bytes,1,opt,name=dense_tensor,json=denseTensor,oneof"` -} - -type TensorRepresentation_VarlenSparseTensor struct { - VarlenSparseTensor *TensorRepresentation_VarLenSparseTensor `protobuf:"bytes,2,opt,name=varlen_sparse_tensor,json=varlenSparseTensor,oneof"` -} - -type TensorRepresentation_SparseTensor_ struct { - SparseTensor *TensorRepresentation_SparseTensor `protobuf:"bytes,3,opt,name=sparse_tensor,json=sparseTensor,oneof"` -} - -func (*TensorRepresentation_DenseTensor_) isTensorRepresentation_Kind() {} - -func (*TensorRepresentation_VarlenSparseTensor) isTensorRepresentation_Kind() {} - -func (*TensorRepresentation_SparseTensor_) isTensorRepresentation_Kind() {} - -// A TensorRepresentationGroup is a collection of TensorRepresentations with -// names. These names may serve as identifiers when converting the dataset -// to a collection of Tensors or tf.CompositeTensors. -// For example, given the following group: -// { -// key: "dense_tensor" -// tensor_representation { -// dense_tensor { -// column_name: "univalent_feature" -// shape { -// dim { -// size: 1 -// } -// } -// default_value { -// float_value: 0 -// } -// } -// } -// } -// { -// key: "varlen_sparse_tensor" -// tensor_representation { -// varlen_sparse_tensor { -// column_name: "multivalent_feature" -// } -// } -// } -// -// Then the schema is expected to have feature "univalent_feature" and -// "multivalent_feature", and when a batch of data is converted to Tensors using -// this TensorRepresentationGroup, the result may be the following dict: -// { -// "dense_tensor": tf.Tensor(...), -// "varlen_sparse_tensor": tf.SparseTensor(...), -// } -type TensorRepresentationGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TensorRepresentation map[string]*TensorRepresentation `protobuf:"bytes,1,rep,name=tensor_representation,json=tensorRepresentation" json:"tensor_representation,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` -} - -func (x *TensorRepresentationGroup) Reset() { - *x = TensorRepresentationGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TensorRepresentationGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TensorRepresentationGroup) ProtoMessage() {} - -func (x *TensorRepresentationGroup) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TensorRepresentationGroup.ProtoReflect.Descriptor instead. -func (*TensorRepresentationGroup) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{26} -} - -func (x *TensorRepresentationGroup) GetTensorRepresentation() map[string]*TensorRepresentation { - if x != nil { - return x.TensorRepresentation - } - return nil -} - -// An axis in a multi-dimensional feature representation. -type FixedShape_Dim struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Size *int64 `protobuf:"varint,1,opt,name=size" json:"size,omitempty"` - // Optional name of the tensor dimension. - Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` -} - -func (x *FixedShape_Dim) Reset() { - *x = FixedShape_Dim{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FixedShape_Dim) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FixedShape_Dim) ProtoMessage() {} - -func (x *FixedShape_Dim) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FixedShape_Dim.ProtoReflect.Descriptor instead. -func (*FixedShape_Dim) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{5, 0} -} - -func (x *FixedShape_Dim) GetSize() int64 { - if x != nil && x.Size != nil { - return *x.Size - } - return 0 -} - -func (x *FixedShape_Dim) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -type SparseFeature_IndexFeature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the index-feature. This should be a reference to an existing - // feature in the schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` -} - -func (x *SparseFeature_IndexFeature) Reset() { - *x = SparseFeature_IndexFeature{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SparseFeature_IndexFeature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SparseFeature_IndexFeature) ProtoMessage() {} - -func (x *SparseFeature_IndexFeature) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SparseFeature_IndexFeature.ProtoReflect.Descriptor instead. -func (*SparseFeature_IndexFeature) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{8, 0} -} - -func (x *SparseFeature_IndexFeature) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -type SparseFeature_ValueFeature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name of the value-feature. This should be a reference to an existing - // feature in the schema. - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` -} - -func (x *SparseFeature_ValueFeature) Reset() { - *x = SparseFeature_ValueFeature{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SparseFeature_ValueFeature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SparseFeature_ValueFeature) ProtoMessage() {} - -func (x *SparseFeature_ValueFeature) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SparseFeature_ValueFeature.ProtoReflect.Descriptor instead. -func (*SparseFeature_ValueFeature) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{8, 1} -} - -func (x *SparseFeature_ValueFeature) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -type TensorRepresentation_DefaultValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Kind: - // *TensorRepresentation_DefaultValue_FloatValue - // *TensorRepresentation_DefaultValue_IntValue - // *TensorRepresentation_DefaultValue_BytesValue - // *TensorRepresentation_DefaultValue_UintValue - Kind isTensorRepresentation_DefaultValue_Kind `protobuf_oneof:"kind"` -} - -func (x *TensorRepresentation_DefaultValue) Reset() { - *x = TensorRepresentation_DefaultValue{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TensorRepresentation_DefaultValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TensorRepresentation_DefaultValue) ProtoMessage() {} - -func (x *TensorRepresentation_DefaultValue) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TensorRepresentation_DefaultValue.ProtoReflect.Descriptor instead. -func (*TensorRepresentation_DefaultValue) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{25, 0} -} - -func (m *TensorRepresentation_DefaultValue) GetKind() isTensorRepresentation_DefaultValue_Kind { - if m != nil { - return m.Kind - } - return nil -} - -func (x *TensorRepresentation_DefaultValue) GetFloatValue() float64 { - if x, ok := x.GetKind().(*TensorRepresentation_DefaultValue_FloatValue); ok { - return x.FloatValue - } - return 0 -} - -func (x *TensorRepresentation_DefaultValue) GetIntValue() int64 { - if x, ok := x.GetKind().(*TensorRepresentation_DefaultValue_IntValue); ok { - return x.IntValue - } - return 0 -} - -func (x *TensorRepresentation_DefaultValue) GetBytesValue() []byte { - if x, ok := x.GetKind().(*TensorRepresentation_DefaultValue_BytesValue); ok { - return x.BytesValue - } - return nil -} - -func (x *TensorRepresentation_DefaultValue) GetUintValue() uint64 { - if x, ok := x.GetKind().(*TensorRepresentation_DefaultValue_UintValue); ok { - return x.UintValue - } - return 0 -} - -type isTensorRepresentation_DefaultValue_Kind interface { - isTensorRepresentation_DefaultValue_Kind() -} - -type TensorRepresentation_DefaultValue_FloatValue struct { - FloatValue float64 `protobuf:"fixed64,1,opt,name=float_value,json=floatValue,oneof"` -} - -type TensorRepresentation_DefaultValue_IntValue struct { - // Note that the data column might be of a shorter integral type. It's the - // user's responsitiblity to make sure the default value fits that type. - IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,oneof"` -} - -type TensorRepresentation_DefaultValue_BytesValue struct { - BytesValue []byte `protobuf:"bytes,3,opt,name=bytes_value,json=bytesValue,oneof"` -} - -type TensorRepresentation_DefaultValue_UintValue struct { - // uint_value should only be used if the default value can't fit in a - // int64 (`int_value`). - UintValue uint64 `protobuf:"varint,4,opt,name=uint_value,json=uintValue,oneof"` -} - -func (*TensorRepresentation_DefaultValue_FloatValue) isTensorRepresentation_DefaultValue_Kind() {} - -func (*TensorRepresentation_DefaultValue_IntValue) isTensorRepresentation_DefaultValue_Kind() {} - -func (*TensorRepresentation_DefaultValue_BytesValue) isTensorRepresentation_DefaultValue_Kind() {} - -func (*TensorRepresentation_DefaultValue_UintValue) isTensorRepresentation_DefaultValue_Kind() {} - -// A tf.Tensor -type TensorRepresentation_DenseTensor struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Identifies the column in the dataset that provides the values of this - // Tensor. - ColumnName *string `protobuf:"bytes,1,opt,name=column_name,json=columnName" json:"column_name,omitempty"` - // The shape of each row of the data (i.e. does not include the batch - // dimension) - Shape *FixedShape `protobuf:"bytes,2,opt,name=shape" json:"shape,omitempty"` - // If this column is missing values in a row, the default_value will be - // used to fill that row. - DefaultValue *TensorRepresentation_DefaultValue `protobuf:"bytes,3,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` -} - -func (x *TensorRepresentation_DenseTensor) Reset() { - *x = TensorRepresentation_DenseTensor{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TensorRepresentation_DenseTensor) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TensorRepresentation_DenseTensor) ProtoMessage() {} - -func (x *TensorRepresentation_DenseTensor) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[32] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TensorRepresentation_DenseTensor.ProtoReflect.Descriptor instead. -func (*TensorRepresentation_DenseTensor) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{25, 1} -} - -func (x *TensorRepresentation_DenseTensor) GetColumnName() string { - if x != nil && x.ColumnName != nil { - return *x.ColumnName - } - return "" -} - -func (x *TensorRepresentation_DenseTensor) GetShape() *FixedShape { - if x != nil { - return x.Shape - } - return nil -} - -func (x *TensorRepresentation_DenseTensor) GetDefaultValue() *TensorRepresentation_DefaultValue { - if x != nil { - return x.DefaultValue - } - return nil -} - -// A ragged tf.SparseTensor that models nested lists. -type TensorRepresentation_VarLenSparseTensor struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Identifies the column in the dataset that should be converted to the - // VarLenSparseTensor. - ColumnName *string `protobuf:"bytes,1,opt,name=column_name,json=columnName" json:"column_name,omitempty"` -} - -func (x *TensorRepresentation_VarLenSparseTensor) Reset() { - *x = TensorRepresentation_VarLenSparseTensor{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TensorRepresentation_VarLenSparseTensor) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TensorRepresentation_VarLenSparseTensor) ProtoMessage() {} - -func (x *TensorRepresentation_VarLenSparseTensor) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[33] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TensorRepresentation_VarLenSparseTensor.ProtoReflect.Descriptor instead. -func (*TensorRepresentation_VarLenSparseTensor) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{25, 2} -} - -func (x *TensorRepresentation_VarLenSparseTensor) GetColumnName() string { - if x != nil && x.ColumnName != nil { - return *x.ColumnName - } - return "" -} - -// A tf.SparseTensor whose indices and values come from separate data columns. -// This will replace Schema.sparse_feature eventually. -// The index columns must be of INT type, and all the columns must co-occur -// and have the same valency at the same row. -type TensorRepresentation_SparseTensor struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The dense shape of the resulting SparseTensor (does not include the batch - // dimension). - DenseShape *FixedShape `protobuf:"bytes,1,opt,name=dense_shape,json=denseShape" json:"dense_shape,omitempty"` - // The columns constitute the coordinates of the values. - // indices_column[i][j] contains the coordinate of the i-th dimension of the - // j-th value. - IndexColumnNames []string `protobuf:"bytes,2,rep,name=index_column_names,json=indexColumnNames" json:"index_column_names,omitempty"` - // The column that contains the values. - ValueColumnName *string `protobuf:"bytes,3,opt,name=value_column_name,json=valueColumnName" json:"value_column_name,omitempty"` -} - -func (x *TensorRepresentation_SparseTensor) Reset() { - *x = TensorRepresentation_SparseTensor{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TensorRepresentation_SparseTensor) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TensorRepresentation_SparseTensor) ProtoMessage() {} - -func (x *TensorRepresentation_SparseTensor) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[34] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TensorRepresentation_SparseTensor.ProtoReflect.Descriptor instead. -func (*TensorRepresentation_SparseTensor) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP(), []int{25, 3} -} - -func (x *TensorRepresentation_SparseTensor) GetDenseShape() *FixedShape { - if x != nil { - return x.DenseShape - } - return nil -} - -func (x *TensorRepresentation_SparseTensor) GetIndexColumnNames() []string { - if x != nil { - return x.IndexColumnNames - } - return nil -} - -func (x *TensorRepresentation_SparseTensor) GetValueColumnName() string { - if x != nil && x.ValueColumnName != nil { - return *x.ValueColumnName - } - return "" -} - -var File_tensorflow_metadata_proto_v0_schema_proto protoreflect.FileDescriptor - -var file_tensorflow_metadata_proto_v0_schema_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0x2f, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, - 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0x2f, 0x70, 0x61, 0x74, - 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8c, 0x07, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x12, 0x39, 0x0a, 0x07, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x07, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x4c, 0x0a, - 0x0e, 0x73, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0d, 0x73, 0x70, - 0x61, 0x72, 0x73, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x52, 0x0a, 0x10, 0x77, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x57, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0f, - 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, - 0x49, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x0c, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x46, 0x0a, 0x0c, 0x66, 0x6c, - 0x6f, 0x61, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x0b, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x12, 0x40, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x49, 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, - 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, - 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x64, 0x61, 0x74, - 0x61, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, - 0x74, 0x73, 0x52, 0x12, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x74, - 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x1b, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, - 0x5f, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x54, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x19, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x1a, 0x7f, 0x0a, 0x1e, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, - 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb9, 0x0e, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, - 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, - 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x45, 0x0a, 0x08, 0x70, 0x72, - 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x5b, 0x0a, 0x0e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, - 0x6e, 0x63, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x63, 0x65, 0x57, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, - 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3a, - 0x0a, 0x05, 0x73, 0x68, 0x61, 0x70, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, 0x70, - 0x65, 0x48, 0x01, 0x52, 0x05, 0x73, 0x68, 0x61, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x48, 0x01, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x06, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x49, 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x09, 0x69, - 0x6e, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x48, 0x0a, 0x0c, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0b, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, - 0x02, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, - 0x45, 0x0a, 0x0b, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x42, 0x6f, - 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, - 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x4b, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x12, 0x67, 0x0a, 0x17, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x5f, 0x6c, - 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x18, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4e, 0x61, - 0x74, 0x75, 0x72, 0x61, 0x6c, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x15, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x4c, 0x61, - 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x48, 0x0a, 0x0c, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x19, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6d, 0x61, 0x67, - 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, - 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x6d, 0x69, 0x64, 0x5f, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x4d, 0x49, 0x44, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, - 0x09, 0x6d, 0x69, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0a, 0x75, 0x72, - 0x6c, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x55, 0x52, 0x4c, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x48, 0x02, 0x52, 0x09, 0x75, 0x72, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x45, - 0x0a, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x1c, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x56, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6f, 0x66, - 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x1e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x4f, - 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x0f, 0x74, 0x69, - 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x6a, 0x0a, - 0x18, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, - 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2f, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, - 0x52, 0x17, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x42, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, - 0x0f, 0x73, 0x6b, 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x0e, 0x73, 0x6b, 0x65, 0x77, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x12, 0x54, 0x0a, 0x10, 0x64, 0x72, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6d, 0x70, - 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x0f, 0x64, 0x72, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6d, - 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x5f, 0x65, 0x6e, - 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0d, 0x69, 0x6e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2c, - 0x0a, 0x12, 0x6e, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x13, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x6f, 0x74, 0x49, - 0x6e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x4f, 0x0a, 0x0f, - 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, - 0x16, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4c, - 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x0e, 0x6c, - 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x42, 0x16, 0x0a, - 0x14, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, - 0x61, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, - 0x66, 0x6f, 0x22, 0x75, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x74, - 0x61, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x0e, - 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x0d, 0x65, 0x78, 0x74, 0x72, - 0x61, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x84, 0x01, 0x0a, 0x16, 0x4e, 0x75, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x01, 0x52, 0x14, 0x6d, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x6d, 0x61, - 0x78, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, - 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x46, - 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, - 0x22, 0xac, 0x02, 0x0a, 0x12, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x73, - 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x71, 0x0a, 0x1d, 0x6e, 0x75, 0x6d, 0x5f, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x5f, 0x64, 0x72, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, - 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x1a, - 0x6e, 0x75, 0x6d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x44, 0x72, 0x69, 0x66, 0x74, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x75, 0x0a, 0x1f, 0x6e, 0x75, - 0x6d, 0x5f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4e, 0x75, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x1c, 0x6e, 0x75, 0x6d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6d, - 0x69, 0x6e, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, - 0x75, 0x0a, 0x0a, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, 0x70, 0x65, 0x12, 0x38, 0x0a, - 0x03, 0x64, 0x69, 0x6d, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, 0x70, 0x65, 0x2e, 0x44, - 0x69, 0x6d, 0x52, 0x03, 0x64, 0x69, 0x6d, 0x1a, 0x2d, 0x0a, 0x03, 0x44, 0x69, 0x6d, 0x12, 0x12, - 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, - 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x30, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x22, 0xf3, 0x01, 0x0a, 0x0f, 0x57, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x36, 0x0a, 0x07, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x07, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x43, 0x0a, 0x0e, 0x77, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0d, - 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x4f, 0x0a, - 0x0f, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x0e, - 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x22, 0x80, - 0x05, 0x0a, 0x0d, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x64, 0x65, - 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x4f, 0x0a, 0x0f, 0x6c, 0x69, 0x66, 0x65, - 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x26, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x63, - 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x0e, 0x6c, 0x69, 0x66, 0x65, 0x63, - 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, - 0x65, 0x6e, 0x63, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x70, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, - 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, - 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x6e, - 0x73, 0x65, 0x53, 0x68, 0x61, 0x70, 0x65, 0x12, 0x57, 0x0a, 0x0d, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x0c, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x57, 0x0a, - 0x0d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x70, - 0x61, 0x72, 0x73, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0c, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x1a, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x22, 0x0a, 0x0c, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x0b, 0x10, - 0x0c, 0x22, 0x44, 0x0a, 0x17, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x0f, - 0x6d, 0x69, 0x6e, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x01, 0x3a, 0x01, 0x31, 0x52, 0x0d, 0x6d, 0x69, 0x6e, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x73, 0x73, 0x22, 0x6a, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, - 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x25, 0x0a, 0x0e, - 0x69, 0x73, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, - 0x63, 0x61, 0x6c, 0x22, 0x45, 0x0a, 0x0b, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x02, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x22, 0x97, 0x01, 0x0a, 0x0c, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x39, 0x0a, 0x07, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x07, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x4c, 0x0a, 0x0e, 0x73, 0x70, 0x61, 0x72, 0x73, 0x65, - 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0d, 0x73, 0x70, 0x61, 0x72, 0x73, 0x65, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x22, 0x38, 0x0a, 0x0c, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x60, - 0x0a, 0x0a, 0x42, 0x6f, 0x6f, 0x6c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x75, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72, 0x75, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x1f, 0x0a, 0x0b, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x17, 0x0a, 0x15, 0x4e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x4c, 0x61, 0x6e, 0x67, 0x75, - 0x61, 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x0d, 0x0a, 0x0b, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x0b, 0x0a, 0x09, 0x4d, 0x49, 0x44, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x0b, 0x0a, 0x09, 0x55, 0x52, 0x4c, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x22, 0xab, 0x02, 0x0a, 0x0a, 0x54, 0x69, 0x6d, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x5d, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x65, 0x72, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, - 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, - 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, - 0x67, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, - 0x0e, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x49, 0x58, 0x5f, 0x44, 0x41, 0x59, 0x53, 0x10, 0x05, - 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x49, 0x58, 0x5f, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x53, - 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x49, 0x58, 0x5f, 0x4d, 0x49, 0x4c, 0x4c, 0x49, - 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x53, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x49, - 0x58, 0x5f, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x53, 0x10, 0x03, - 0x12, 0x14, 0x0a, 0x10, 0x55, 0x4e, 0x49, 0x58, 0x5f, 0x4e, 0x41, 0x4e, 0x4f, 0x53, 0x45, 0x43, - 0x4f, 0x4e, 0x44, 0x53, 0x10, 0x04, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x22, 0xee, 0x01, 0x0a, 0x0f, 0x54, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x67, 0x0a, 0x0e, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x49, 0x6e, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x46, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x46, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x22, 0x41, 0x0a, 0x16, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x54, - 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x44, 0x61, 0x79, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, - 0x0a, 0x0e, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, - 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x44, 0x5f, 0x36, 0x34, 0x5f, - 0x4e, 0x41, 0x4e, 0x4f, 0x53, 0x10, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x22, 0x51, 0x0a, 0x0f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, - 0x65, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x46, - 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x1a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, - 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x57, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0x2c, - 0x0a, 0x0c, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x4e, 0x6f, 0x72, 0x6d, 0x12, 0x1c, - 0x0a, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x01, 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0x5e, 0x0a, 0x11, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x12, 0x49, 0x0a, 0x0d, 0x69, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x6e, 0x6f, - 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x4e, 0x6f, 0x72, 0x6d, 0x52, 0x0c, - 0x69, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x4e, 0x6f, 0x72, 0x6d, 0x22, 0xa5, 0x07, 0x0a, - 0x14, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5d, 0x0a, 0x0c, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6e, 0x73, 0x65, 0x54, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x54, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x12, 0x73, 0x0a, 0x14, 0x76, 0x61, 0x72, 0x6c, 0x65, 0x6e, 0x5f, 0x73, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x56, 0x61, 0x72, 0x4c, 0x65, 0x6e, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x54, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x12, 0x76, 0x61, 0x72, 0x6c, 0x65, 0x6e, 0x53, 0x70, 0x61, - 0x72, 0x73, 0x65, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x12, 0x60, 0x0a, 0x0d, 0x73, 0x70, 0x61, - 0x72, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x39, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, - 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0c, 0x73, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x1a, 0x9c, 0x01, 0x0a, 0x0c, - 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, - 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x01, 0x48, 0x00, 0x52, 0x0a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, - 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x1a, 0xc8, 0x01, 0x0a, 0x0b, 0x44, - 0x65, 0x6e, 0x73, 0x65, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, - 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x05, 0x73, - 0x68, 0x61, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x68, 0x61, 0x70, 0x65, 0x52, 0x05, - 0x73, 0x68, 0x61, 0x70, 0x65, 0x12, 0x5e, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, - 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x35, 0x0a, 0x12, 0x56, 0x61, 0x72, 0x4c, 0x65, 0x6e, 0x53, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x63, - 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0xad, 0x01, 0x0a, - 0x0c, 0x53, 0x70, 0x61, 0x72, 0x73, 0x65, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x12, 0x43, 0x0a, - 0x0b, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x69, 0x78, 0x65, - 0x64, 0x53, 0x68, 0x61, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x53, 0x68, 0x61, - 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x63, 0x6f, 0x6c, 0x75, - 0x6d, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x06, 0x0a, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x95, 0x02, 0x0a, 0x19, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, - 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x5f, 0x72, 0x65, - 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, - 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x14, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x75, 0x0a, 0x19, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, - 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x42, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x54, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x2a, 0x75, 0x0a, 0x0e, - 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x11, - 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x10, - 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x4c, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x01, 0x12, 0x09, - 0x0a, 0x05, 0x41, 0x4c, 0x50, 0x48, 0x41, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x45, 0x54, - 0x41, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, - 0x44, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5f, 0x4f, 0x4e, 0x4c, - 0x59, 0x10, 0x06, 0x2a, 0x4a, 0x0a, 0x0b, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x01, 0x12, - 0x07, 0x0a, 0x03, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, 0x41, - 0x54, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x10, 0x04, 0x42, - 0x68, 0x0a, 0x1a, 0x6f, 0x72, 0x67, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x50, 0x01, 0x5a, - 0x45, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, - 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, - 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, - 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0xf8, 0x01, 0x01, -} - -var ( - file_tensorflow_metadata_proto_v0_schema_proto_rawDescOnce sync.Once - file_tensorflow_metadata_proto_v0_schema_proto_rawDescData = file_tensorflow_metadata_proto_v0_schema_proto_rawDesc -) - -func file_tensorflow_metadata_proto_v0_schema_proto_rawDescGZIP() []byte { - file_tensorflow_metadata_proto_v0_schema_proto_rawDescOnce.Do(func() { - file_tensorflow_metadata_proto_v0_schema_proto_rawDescData = protoimpl.X.CompressGZIP(file_tensorflow_metadata_proto_v0_schema_proto_rawDescData) - }) - return file_tensorflow_metadata_proto_v0_schema_proto_rawDescData -} - -var file_tensorflow_metadata_proto_v0_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_tensorflow_metadata_proto_v0_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 36) -var file_tensorflow_metadata_proto_v0_schema_proto_goTypes = []interface{}{ - (LifecycleStage)(0), // 0: tensorflow.metadata.v0.LifecycleStage - (FeatureType)(0), // 1: tensorflow.metadata.v0.FeatureType - (TimeDomain_IntegerTimeFormat)(0), // 2: tensorflow.metadata.v0.TimeDomain.IntegerTimeFormat - (TimeOfDayDomain_IntegerTimeOfDayFormat)(0), // 3: tensorflow.metadata.v0.TimeOfDayDomain.IntegerTimeOfDayFormat - (*Schema)(nil), // 4: tensorflow.metadata.v0.Schema - (*Feature)(nil), // 5: tensorflow.metadata.v0.Feature - (*Annotation)(nil), // 6: tensorflow.metadata.v0.Annotation - (*NumericValueComparator)(nil), // 7: tensorflow.metadata.v0.NumericValueComparator - (*DatasetConstraints)(nil), // 8: tensorflow.metadata.v0.DatasetConstraints - (*FixedShape)(nil), // 9: tensorflow.metadata.v0.FixedShape - (*ValueCount)(nil), // 10: tensorflow.metadata.v0.ValueCount - (*WeightedFeature)(nil), // 11: tensorflow.metadata.v0.WeightedFeature - (*SparseFeature)(nil), // 12: tensorflow.metadata.v0.SparseFeature - (*DistributionConstraints)(nil), // 13: tensorflow.metadata.v0.DistributionConstraints - (*IntDomain)(nil), // 14: tensorflow.metadata.v0.IntDomain - (*FloatDomain)(nil), // 15: tensorflow.metadata.v0.FloatDomain - (*StructDomain)(nil), // 16: tensorflow.metadata.v0.StructDomain - (*StringDomain)(nil), // 17: tensorflow.metadata.v0.StringDomain - (*BoolDomain)(nil), // 18: tensorflow.metadata.v0.BoolDomain - (*NaturalLanguageDomain)(nil), // 19: tensorflow.metadata.v0.NaturalLanguageDomain - (*ImageDomain)(nil), // 20: tensorflow.metadata.v0.ImageDomain - (*MIDDomain)(nil), // 21: tensorflow.metadata.v0.MIDDomain - (*URLDomain)(nil), // 22: tensorflow.metadata.v0.URLDomain - (*TimeDomain)(nil), // 23: tensorflow.metadata.v0.TimeDomain - (*TimeOfDayDomain)(nil), // 24: tensorflow.metadata.v0.TimeOfDayDomain - (*FeaturePresence)(nil), // 25: tensorflow.metadata.v0.FeaturePresence - (*FeaturePresenceWithinGroup)(nil), // 26: tensorflow.metadata.v0.FeaturePresenceWithinGroup - (*InfinityNorm)(nil), // 27: tensorflow.metadata.v0.InfinityNorm - (*FeatureComparator)(nil), // 28: tensorflow.metadata.v0.FeatureComparator - (*TensorRepresentation)(nil), // 29: tensorflow.metadata.v0.TensorRepresentation - (*TensorRepresentationGroup)(nil), // 30: tensorflow.metadata.v0.TensorRepresentationGroup - nil, // 31: tensorflow.metadata.v0.Schema.TensorRepresentationGroupEntry - (*FixedShape_Dim)(nil), // 32: tensorflow.metadata.v0.FixedShape.Dim - (*SparseFeature_IndexFeature)(nil), // 33: tensorflow.metadata.v0.SparseFeature.IndexFeature - (*SparseFeature_ValueFeature)(nil), // 34: tensorflow.metadata.v0.SparseFeature.ValueFeature - (*TensorRepresentation_DefaultValue)(nil), // 35: tensorflow.metadata.v0.TensorRepresentation.DefaultValue - (*TensorRepresentation_DenseTensor)(nil), // 36: tensorflow.metadata.v0.TensorRepresentation.DenseTensor - (*TensorRepresentation_VarLenSparseTensor)(nil), // 37: tensorflow.metadata.v0.TensorRepresentation.VarLenSparseTensor - (*TensorRepresentation_SparseTensor)(nil), // 38: tensorflow.metadata.v0.TensorRepresentation.SparseTensor - nil, // 39: tensorflow.metadata.v0.TensorRepresentationGroup.TensorRepresentationEntry - (*anypb.Any)(nil), // 40: google.protobuf.Any - (*Path)(nil), // 41: tensorflow.metadata.v0.Path -} -var file_tensorflow_metadata_proto_v0_schema_proto_depIdxs = []int32{ - 5, // 0: tensorflow.metadata.v0.Schema.feature:type_name -> tensorflow.metadata.v0.Feature - 12, // 1: tensorflow.metadata.v0.Schema.sparse_feature:type_name -> tensorflow.metadata.v0.SparseFeature - 11, // 2: tensorflow.metadata.v0.Schema.weighted_feature:type_name -> tensorflow.metadata.v0.WeightedFeature - 17, // 3: tensorflow.metadata.v0.Schema.string_domain:type_name -> tensorflow.metadata.v0.StringDomain - 15, // 4: tensorflow.metadata.v0.Schema.float_domain:type_name -> tensorflow.metadata.v0.FloatDomain - 14, // 5: tensorflow.metadata.v0.Schema.int_domain:type_name -> tensorflow.metadata.v0.IntDomain - 6, // 6: tensorflow.metadata.v0.Schema.annotation:type_name -> tensorflow.metadata.v0.Annotation - 8, // 7: tensorflow.metadata.v0.Schema.dataset_constraints:type_name -> tensorflow.metadata.v0.DatasetConstraints - 31, // 8: tensorflow.metadata.v0.Schema.tensor_representation_group:type_name -> tensorflow.metadata.v0.Schema.TensorRepresentationGroupEntry - 25, // 9: tensorflow.metadata.v0.Feature.presence:type_name -> tensorflow.metadata.v0.FeaturePresence - 26, // 10: tensorflow.metadata.v0.Feature.group_presence:type_name -> tensorflow.metadata.v0.FeaturePresenceWithinGroup - 9, // 11: tensorflow.metadata.v0.Feature.shape:type_name -> tensorflow.metadata.v0.FixedShape - 10, // 12: tensorflow.metadata.v0.Feature.value_count:type_name -> tensorflow.metadata.v0.ValueCount - 1, // 13: tensorflow.metadata.v0.Feature.type:type_name -> tensorflow.metadata.v0.FeatureType - 14, // 14: tensorflow.metadata.v0.Feature.int_domain:type_name -> tensorflow.metadata.v0.IntDomain - 15, // 15: tensorflow.metadata.v0.Feature.float_domain:type_name -> tensorflow.metadata.v0.FloatDomain - 17, // 16: tensorflow.metadata.v0.Feature.string_domain:type_name -> tensorflow.metadata.v0.StringDomain - 18, // 17: tensorflow.metadata.v0.Feature.bool_domain:type_name -> tensorflow.metadata.v0.BoolDomain - 16, // 18: tensorflow.metadata.v0.Feature.struct_domain:type_name -> tensorflow.metadata.v0.StructDomain - 19, // 19: tensorflow.metadata.v0.Feature.natural_language_domain:type_name -> tensorflow.metadata.v0.NaturalLanguageDomain - 20, // 20: tensorflow.metadata.v0.Feature.image_domain:type_name -> tensorflow.metadata.v0.ImageDomain - 21, // 21: tensorflow.metadata.v0.Feature.mid_domain:type_name -> tensorflow.metadata.v0.MIDDomain - 22, // 22: tensorflow.metadata.v0.Feature.url_domain:type_name -> tensorflow.metadata.v0.URLDomain - 23, // 23: tensorflow.metadata.v0.Feature.time_domain:type_name -> tensorflow.metadata.v0.TimeDomain - 24, // 24: tensorflow.metadata.v0.Feature.time_of_day_domain:type_name -> tensorflow.metadata.v0.TimeOfDayDomain - 13, // 25: tensorflow.metadata.v0.Feature.distribution_constraints:type_name -> tensorflow.metadata.v0.DistributionConstraints - 6, // 26: tensorflow.metadata.v0.Feature.annotation:type_name -> tensorflow.metadata.v0.Annotation - 28, // 27: tensorflow.metadata.v0.Feature.skew_comparator:type_name -> tensorflow.metadata.v0.FeatureComparator - 28, // 28: tensorflow.metadata.v0.Feature.drift_comparator:type_name -> tensorflow.metadata.v0.FeatureComparator - 0, // 29: tensorflow.metadata.v0.Feature.lifecycle_stage:type_name -> tensorflow.metadata.v0.LifecycleStage - 40, // 30: tensorflow.metadata.v0.Annotation.extra_metadata:type_name -> google.protobuf.Any - 7, // 31: tensorflow.metadata.v0.DatasetConstraints.num_examples_drift_comparator:type_name -> tensorflow.metadata.v0.NumericValueComparator - 7, // 32: tensorflow.metadata.v0.DatasetConstraints.num_examples_version_comparator:type_name -> tensorflow.metadata.v0.NumericValueComparator - 32, // 33: tensorflow.metadata.v0.FixedShape.dim:type_name -> tensorflow.metadata.v0.FixedShape.Dim - 41, // 34: tensorflow.metadata.v0.WeightedFeature.feature:type_name -> tensorflow.metadata.v0.Path - 41, // 35: tensorflow.metadata.v0.WeightedFeature.weight_feature:type_name -> tensorflow.metadata.v0.Path - 0, // 36: tensorflow.metadata.v0.WeightedFeature.lifecycle_stage:type_name -> tensorflow.metadata.v0.LifecycleStage - 0, // 37: tensorflow.metadata.v0.SparseFeature.lifecycle_stage:type_name -> tensorflow.metadata.v0.LifecycleStage - 25, // 38: tensorflow.metadata.v0.SparseFeature.presence:type_name -> tensorflow.metadata.v0.FeaturePresence - 9, // 39: tensorflow.metadata.v0.SparseFeature.dense_shape:type_name -> tensorflow.metadata.v0.FixedShape - 33, // 40: tensorflow.metadata.v0.SparseFeature.index_feature:type_name -> tensorflow.metadata.v0.SparseFeature.IndexFeature - 34, // 41: tensorflow.metadata.v0.SparseFeature.value_feature:type_name -> tensorflow.metadata.v0.SparseFeature.ValueFeature - 1, // 42: tensorflow.metadata.v0.SparseFeature.type:type_name -> tensorflow.metadata.v0.FeatureType - 5, // 43: tensorflow.metadata.v0.StructDomain.feature:type_name -> tensorflow.metadata.v0.Feature - 12, // 44: tensorflow.metadata.v0.StructDomain.sparse_feature:type_name -> tensorflow.metadata.v0.SparseFeature - 2, // 45: tensorflow.metadata.v0.TimeDomain.integer_format:type_name -> tensorflow.metadata.v0.TimeDomain.IntegerTimeFormat - 3, // 46: tensorflow.metadata.v0.TimeOfDayDomain.integer_format:type_name -> tensorflow.metadata.v0.TimeOfDayDomain.IntegerTimeOfDayFormat - 27, // 47: tensorflow.metadata.v0.FeatureComparator.infinity_norm:type_name -> tensorflow.metadata.v0.InfinityNorm - 36, // 48: tensorflow.metadata.v0.TensorRepresentation.dense_tensor:type_name -> tensorflow.metadata.v0.TensorRepresentation.DenseTensor - 37, // 49: tensorflow.metadata.v0.TensorRepresentation.varlen_sparse_tensor:type_name -> tensorflow.metadata.v0.TensorRepresentation.VarLenSparseTensor - 38, // 50: tensorflow.metadata.v0.TensorRepresentation.sparse_tensor:type_name -> tensorflow.metadata.v0.TensorRepresentation.SparseTensor - 39, // 51: tensorflow.metadata.v0.TensorRepresentationGroup.tensor_representation:type_name -> tensorflow.metadata.v0.TensorRepresentationGroup.TensorRepresentationEntry - 30, // 52: tensorflow.metadata.v0.Schema.TensorRepresentationGroupEntry.value:type_name -> tensorflow.metadata.v0.TensorRepresentationGroup - 9, // 53: tensorflow.metadata.v0.TensorRepresentation.DenseTensor.shape:type_name -> tensorflow.metadata.v0.FixedShape - 35, // 54: tensorflow.metadata.v0.TensorRepresentation.DenseTensor.default_value:type_name -> tensorflow.metadata.v0.TensorRepresentation.DefaultValue - 9, // 55: tensorflow.metadata.v0.TensorRepresentation.SparseTensor.dense_shape:type_name -> tensorflow.metadata.v0.FixedShape - 29, // 56: tensorflow.metadata.v0.TensorRepresentationGroup.TensorRepresentationEntry.value:type_name -> tensorflow.metadata.v0.TensorRepresentation - 57, // [57:57] is the sub-list for method output_type - 57, // [57:57] is the sub-list for method input_type - 57, // [57:57] is the sub-list for extension type_name - 57, // [57:57] is the sub-list for extension extendee - 0, // [0:57] is the sub-list for field type_name -} - -func init() { file_tensorflow_metadata_proto_v0_schema_proto_init() } -func file_tensorflow_metadata_proto_v0_schema_proto_init() { - if File_tensorflow_metadata_proto_v0_schema_proto != nil { - return - } - file_tensorflow_metadata_proto_v0_path_proto_init() - if !protoimpl.UnsafeEnabled { - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Schema); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Feature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Annotation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NumericValueComparator); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DatasetConstraints); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FixedShape); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValueCount); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WeightedFeature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SparseFeature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DistributionConstraints); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FloatDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StructDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StringDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BoolDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NaturalLanguageDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ImageDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MIDDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*URLDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TimeDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TimeOfDayDomain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeaturePresence); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeaturePresenceWithinGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InfinityNorm); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureComparator); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TensorRepresentation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TensorRepresentationGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FixedShape_Dim); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SparseFeature_IndexFeature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SparseFeature_ValueFeature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TensorRepresentation_DefaultValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TensorRepresentation_DenseTensor); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TensorRepresentation_VarLenSparseTensor); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TensorRepresentation_SparseTensor); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Feature_Presence)(nil), - (*Feature_GroupPresence)(nil), - (*Feature_Shape)(nil), - (*Feature_ValueCount)(nil), - (*Feature_Domain)(nil), - (*Feature_IntDomain)(nil), - (*Feature_FloatDomain)(nil), - (*Feature_StringDomain)(nil), - (*Feature_BoolDomain)(nil), - (*Feature_StructDomain)(nil), - (*Feature_NaturalLanguageDomain)(nil), - (*Feature_ImageDomain)(nil), - (*Feature_MidDomain)(nil), - (*Feature_UrlDomain)(nil), - (*Feature_TimeDomain)(nil), - (*Feature_TimeOfDayDomain)(nil), - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[19].OneofWrappers = []interface{}{ - (*TimeDomain_StringFormat)(nil), - (*TimeDomain_IntegerFormat)(nil), - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[20].OneofWrappers = []interface{}{ - (*TimeOfDayDomain_StringFormat)(nil), - (*TimeOfDayDomain_IntegerFormat)(nil), - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[25].OneofWrappers = []interface{}{ - (*TensorRepresentation_DenseTensor_)(nil), - (*TensorRepresentation_VarlenSparseTensor)(nil), - (*TensorRepresentation_SparseTensor_)(nil), - } - file_tensorflow_metadata_proto_v0_schema_proto_msgTypes[31].OneofWrappers = []interface{}{ - (*TensorRepresentation_DefaultValue_FloatValue)(nil), - (*TensorRepresentation_DefaultValue_IntValue)(nil), - (*TensorRepresentation_DefaultValue_BytesValue)(nil), - (*TensorRepresentation_DefaultValue_UintValue)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_tensorflow_metadata_proto_v0_schema_proto_rawDesc, - NumEnums: 4, - NumMessages: 36, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_tensorflow_metadata_proto_v0_schema_proto_goTypes, - DependencyIndexes: file_tensorflow_metadata_proto_v0_schema_proto_depIdxs, - EnumInfos: file_tensorflow_metadata_proto_v0_schema_proto_enumTypes, - MessageInfos: file_tensorflow_metadata_proto_v0_schema_proto_msgTypes, - }.Build() - File_tensorflow_metadata_proto_v0_schema_proto = out.File - file_tensorflow_metadata_proto_v0_schema_proto_rawDesc = nil - file_tensorflow_metadata_proto_v0_schema_proto_goTypes = nil - file_tensorflow_metadata_proto_v0_schema_proto_depIdxs = nil -} diff --git a/sdk/go/protos/tensorflow_metadata/proto/v0/statistics.pb.go b/sdk/go/protos/tensorflow_metadata/proto/v0/statistics.pb.go deleted file mode 100644 index cd8bdf5d894..00000000000 --- a/sdk/go/protos/tensorflow_metadata/proto/v0/statistics.pb.go +++ /dev/null @@ -1,3115 +0,0 @@ -// Copyright 2017 The TensorFlow Authors. All Rights Reserved. -// -// 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. -// ============================================================================= - -// Definitions for aggregated feature statistics for datasets. -// TODO(b/80075690): make a Javascript build rule for this. -// TODO(b/80075691): migrate Facets to use this. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.11.2 -// source: tensorflow_metadata/proto/v0/statistics.proto - -package v0 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// The types supported by the feature statistics. When aggregating -// tf.Examples, if the bytelist contains a string, it is recommended to encode -// it here as STRING instead of BYTES in order to calculate string-specific -// statistical measures. -type FeatureNameStatistics_Type int32 - -const ( - FeatureNameStatistics_INT FeatureNameStatistics_Type = 0 - FeatureNameStatistics_FLOAT FeatureNameStatistics_Type = 1 - FeatureNameStatistics_STRING FeatureNameStatistics_Type = 2 - FeatureNameStatistics_BYTES FeatureNameStatistics_Type = 3 - FeatureNameStatistics_STRUCT FeatureNameStatistics_Type = 4 -) - -// Enum value maps for FeatureNameStatistics_Type. -var ( - FeatureNameStatistics_Type_name = map[int32]string{ - 0: "INT", - 1: "FLOAT", - 2: "STRING", - 3: "BYTES", - 4: "STRUCT", - } - FeatureNameStatistics_Type_value = map[string]int32{ - "INT": 0, - "FLOAT": 1, - "STRING": 2, - "BYTES": 3, - "STRUCT": 4, - } -) - -func (x FeatureNameStatistics_Type) Enum() *FeatureNameStatistics_Type { - p := new(FeatureNameStatistics_Type) - *p = x - return p -} - -func (x FeatureNameStatistics_Type) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (FeatureNameStatistics_Type) Descriptor() protoreflect.EnumDescriptor { - return file_tensorflow_metadata_proto_v0_statistics_proto_enumTypes[0].Descriptor() -} - -func (FeatureNameStatistics_Type) Type() protoreflect.EnumType { - return &file_tensorflow_metadata_proto_v0_statistics_proto_enumTypes[0] -} - -func (x FeatureNameStatistics_Type) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use FeatureNameStatistics_Type.Descriptor instead. -func (FeatureNameStatistics_Type) EnumDescriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{7, 0} -} - -// The type of the histogram. A standard histogram has equal-width buckets. -// The quantiles type is used for when the histogram message is used to store -// quantile information (by using equal-count buckets with variable widths). -type Histogram_HistogramType int32 - -const ( - Histogram_STANDARD Histogram_HistogramType = 0 - Histogram_QUANTILES Histogram_HistogramType = 1 -) - -// Enum value maps for Histogram_HistogramType. -var ( - Histogram_HistogramType_name = map[int32]string{ - 0: "STANDARD", - 1: "QUANTILES", - } - Histogram_HistogramType_value = map[string]int32{ - "STANDARD": 0, - "QUANTILES": 1, - } -) - -func (x Histogram_HistogramType) Enum() *Histogram_HistogramType { - p := new(Histogram_HistogramType) - *p = x - return p -} - -func (x Histogram_HistogramType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Histogram_HistogramType) Descriptor() protoreflect.EnumDescriptor { - return file_tensorflow_metadata_proto_v0_statistics_proto_enumTypes[1].Descriptor() -} - -func (Histogram_HistogramType) Type() protoreflect.EnumType { - return &file_tensorflow_metadata_proto_v0_statistics_proto_enumTypes[1] -} - -func (x Histogram_HistogramType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Histogram_HistogramType.Descriptor instead. -func (Histogram_HistogramType) EnumDescriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{17, 0} -} - -// A list of features statistics for different datasets. If you wish to compare -// different datasets using this list, then the DatasetFeatureStatistics -// entries should all contain the same list of features. -type DatasetFeatureStatisticsList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Datasets []*DatasetFeatureStatistics `protobuf:"bytes,1,rep,name=datasets,proto3" json:"datasets,omitempty"` -} - -func (x *DatasetFeatureStatisticsList) Reset() { - *x = DatasetFeatureStatisticsList{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DatasetFeatureStatisticsList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DatasetFeatureStatisticsList) ProtoMessage() {} - -func (x *DatasetFeatureStatisticsList) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DatasetFeatureStatisticsList.ProtoReflect.Descriptor instead. -func (*DatasetFeatureStatisticsList) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{0} -} - -func (x *DatasetFeatureStatisticsList) GetDatasets() []*DatasetFeatureStatistics { - if x != nil { - return x.Datasets - } - return nil -} - -// The feature statistics for a single dataset. -type DatasetFeatureStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The name of the dataset. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // The number of examples in the dataset. - NumExamples uint64 `protobuf:"varint,2,opt,name=num_examples,json=numExamples,proto3" json:"num_examples,omitempty"` - // Only valid if the weight feature was specified. - // Treats a missing weighted feature as zero. - WeightedNumExamples float64 `protobuf:"fixed64,4,opt,name=weighted_num_examples,json=weightedNumExamples,proto3" json:"weighted_num_examples,omitempty"` - // The feature statistics for the dataset. - Features []*FeatureNameStatistics `protobuf:"bytes,3,rep,name=features,proto3" json:"features,omitempty"` - // Cross feature statistics for the dataset. - CrossFeatures []*CrossFeatureStatistics `protobuf:"bytes,5,rep,name=cross_features,json=crossFeatures,proto3" json:"cross_features,omitempty"` -} - -func (x *DatasetFeatureStatistics) Reset() { - *x = DatasetFeatureStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DatasetFeatureStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DatasetFeatureStatistics) ProtoMessage() {} - -func (x *DatasetFeatureStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DatasetFeatureStatistics.ProtoReflect.Descriptor instead. -func (*DatasetFeatureStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{1} -} - -func (x *DatasetFeatureStatistics) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *DatasetFeatureStatistics) GetNumExamples() uint64 { - if x != nil { - return x.NumExamples - } - return 0 -} - -func (x *DatasetFeatureStatistics) GetWeightedNumExamples() float64 { - if x != nil { - return x.WeightedNumExamples - } - return 0 -} - -func (x *DatasetFeatureStatistics) GetFeatures() []*FeatureNameStatistics { - if x != nil { - return x.Features - } - return nil -} - -func (x *DatasetFeatureStatistics) GetCrossFeatures() []*CrossFeatureStatistics { - if x != nil { - return x.CrossFeatures - } - return nil -} - -type CrossFeatureStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The path of feature x. - PathX *Path `protobuf:"bytes,1,opt,name=path_x,json=pathX,proto3" json:"path_x,omitempty"` - // The path of feature y. - PathY *Path `protobuf:"bytes,2,opt,name=path_y,json=pathY,proto3" json:"path_y,omitempty"` - // Number of occurrences of this feature cross in the data. If any of - // the features in the cross is missing, the example is ignored. - Count uint64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` - // Types that are assignable to CrossStats: - // *CrossFeatureStatistics_NumCrossStats - // *CrossFeatureStatistics_CategoricalCrossStats - CrossStats isCrossFeatureStatistics_CrossStats `protobuf_oneof:"cross_stats"` -} - -func (x *CrossFeatureStatistics) Reset() { - *x = CrossFeatureStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CrossFeatureStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CrossFeatureStatistics) ProtoMessage() {} - -func (x *CrossFeatureStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CrossFeatureStatistics.ProtoReflect.Descriptor instead. -func (*CrossFeatureStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{2} -} - -func (x *CrossFeatureStatistics) GetPathX() *Path { - if x != nil { - return x.PathX - } - return nil -} - -func (x *CrossFeatureStatistics) GetPathY() *Path { - if x != nil { - return x.PathY - } - return nil -} - -func (x *CrossFeatureStatistics) GetCount() uint64 { - if x != nil { - return x.Count - } - return 0 -} - -func (m *CrossFeatureStatistics) GetCrossStats() isCrossFeatureStatistics_CrossStats { - if m != nil { - return m.CrossStats - } - return nil -} - -func (x *CrossFeatureStatistics) GetNumCrossStats() *NumericCrossStatistics { - if x, ok := x.GetCrossStats().(*CrossFeatureStatistics_NumCrossStats); ok { - return x.NumCrossStats - } - return nil -} - -func (x *CrossFeatureStatistics) GetCategoricalCrossStats() *CategoricalCrossStatistics { - if x, ok := x.GetCrossStats().(*CrossFeatureStatistics_CategoricalCrossStats); ok { - return x.CategoricalCrossStats - } - return nil -} - -type isCrossFeatureStatistics_CrossStats interface { - isCrossFeatureStatistics_CrossStats() -} - -type CrossFeatureStatistics_NumCrossStats struct { - NumCrossStats *NumericCrossStatistics `protobuf:"bytes,4,opt,name=num_cross_stats,json=numCrossStats,proto3,oneof"` -} - -type CrossFeatureStatistics_CategoricalCrossStats struct { - CategoricalCrossStats *CategoricalCrossStatistics `protobuf:"bytes,5,opt,name=categorical_cross_stats,json=categoricalCrossStats,proto3,oneof"` -} - -func (*CrossFeatureStatistics_NumCrossStats) isCrossFeatureStatistics_CrossStats() {} - -func (*CrossFeatureStatistics_CategoricalCrossStats) isCrossFeatureStatistics_CrossStats() {} - -type NumericCrossStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Pearson product-moment correlation coefficient. - Correlation float32 `protobuf:"fixed32,1,opt,name=correlation,proto3" json:"correlation,omitempty"` - // Standard covariance. E[(X-E[X])*(Y-E[Y])] - Covariance float32 `protobuf:"fixed32,2,opt,name=covariance,proto3" json:"covariance,omitempty"` -} - -func (x *NumericCrossStatistics) Reset() { - *x = NumericCrossStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NumericCrossStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NumericCrossStatistics) ProtoMessage() {} - -func (x *NumericCrossStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NumericCrossStatistics.ProtoReflect.Descriptor instead. -func (*NumericCrossStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{3} -} - -func (x *NumericCrossStatistics) GetCorrelation() float32 { - if x != nil { - return x.Correlation - } - return 0 -} - -func (x *NumericCrossStatistics) GetCovariance() float32 { - if x != nil { - return x.Covariance - } - return 0 -} - -type CategoricalCrossStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Lift *LiftStatistics `protobuf:"bytes,1,opt,name=lift,proto3" json:"lift,omitempty"` -} - -func (x *CategoricalCrossStatistics) Reset() { - *x = CategoricalCrossStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CategoricalCrossStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CategoricalCrossStatistics) ProtoMessage() {} - -func (x *CategoricalCrossStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CategoricalCrossStatistics.ProtoReflect.Descriptor instead. -func (*CategoricalCrossStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{4} -} - -func (x *CategoricalCrossStatistics) GetLift() *LiftStatistics { - if x != nil { - return x.Lift - } - return nil -} - -type LiftStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Lift information for each value of path_y. Lift is defined for each pair of - // values (x,y) as P(path_y=y|path_x=x)/P(path_y=y). - LiftSeries []*LiftSeries `protobuf:"bytes,1,rep,name=lift_series,json=liftSeries,proto3" json:"lift_series,omitempty"` - // Weighted lift information for each value of path_y. Weighted lift is - // defined for each pair of values (x,y) as P(path_y=y|path_x=x)/P(path_y=y) - // where probabilities are computed over weighted example space. - WeightedLiftSeries []*LiftSeries `protobuf:"bytes,2,rep,name=weighted_lift_series,json=weightedLiftSeries,proto3" json:"weighted_lift_series,omitempty"` -} - -func (x *LiftStatistics) Reset() { - *x = LiftStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LiftStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LiftStatistics) ProtoMessage() {} - -func (x *LiftStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LiftStatistics.ProtoReflect.Descriptor instead. -func (*LiftStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{5} -} - -func (x *LiftStatistics) GetLiftSeries() []*LiftSeries { - if x != nil { - return x.LiftSeries - } - return nil -} - -func (x *LiftStatistics) GetWeightedLiftSeries() []*LiftSeries { - if x != nil { - return x.WeightedLiftSeries - } - return nil -} - -// Container for lift information for a specific y-value. -type LiftSeries struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The particular value of path_y corresponding to this LiftSeries. Each - // element in lift_values corresponds to the lift a different x_value and - // this specific y_value. - // - // Types that are assignable to YValue: - // *LiftSeries_YInt - // *LiftSeries_YString - // *LiftSeries_YBucket - YValue isLiftSeries_YValue `protobuf_oneof:"y_value"` - // The number of examples in which y_value appears. - // - // Types that are assignable to YCountValue: - // *LiftSeries_YCount - // *LiftSeries_WeightedYCount - YCountValue isLiftSeries_YCountValue `protobuf_oneof:"y_count_value"` - // The lifts for a each path_x value and this y_value. - LiftValues []*LiftSeries_LiftValue `protobuf:"bytes,6,rep,name=lift_values,json=liftValues,proto3" json:"lift_values,omitempty"` -} - -func (x *LiftSeries) Reset() { - *x = LiftSeries{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LiftSeries) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LiftSeries) ProtoMessage() {} - -func (x *LiftSeries) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LiftSeries.ProtoReflect.Descriptor instead. -func (*LiftSeries) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{6} -} - -func (m *LiftSeries) GetYValue() isLiftSeries_YValue { - if m != nil { - return m.YValue - } - return nil -} - -func (x *LiftSeries) GetYInt() int32 { - if x, ok := x.GetYValue().(*LiftSeries_YInt); ok { - return x.YInt - } - return 0 -} - -func (x *LiftSeries) GetYString() string { - if x, ok := x.GetYValue().(*LiftSeries_YString); ok { - return x.YString - } - return "" -} - -func (x *LiftSeries) GetYBucket() *LiftSeries_Bucket { - if x, ok := x.GetYValue().(*LiftSeries_YBucket); ok { - return x.YBucket - } - return nil -} - -func (m *LiftSeries) GetYCountValue() isLiftSeries_YCountValue { - if m != nil { - return m.YCountValue - } - return nil -} - -func (x *LiftSeries) GetYCount() uint64 { - if x, ok := x.GetYCountValue().(*LiftSeries_YCount); ok { - return x.YCount - } - return 0 -} - -func (x *LiftSeries) GetWeightedYCount() float64 { - if x, ok := x.GetYCountValue().(*LiftSeries_WeightedYCount); ok { - return x.WeightedYCount - } - return 0 -} - -func (x *LiftSeries) GetLiftValues() []*LiftSeries_LiftValue { - if x != nil { - return x.LiftValues - } - return nil -} - -type isLiftSeries_YValue interface { - isLiftSeries_YValue() -} - -type LiftSeries_YInt struct { - YInt int32 `protobuf:"varint,1,opt,name=y_int,json=yInt,proto3,oneof"` -} - -type LiftSeries_YString struct { - YString string `protobuf:"bytes,2,opt,name=y_string,json=yString,proto3,oneof"` -} - -type LiftSeries_YBucket struct { - YBucket *LiftSeries_Bucket `protobuf:"bytes,3,opt,name=y_bucket,json=yBucket,proto3,oneof"` -} - -func (*LiftSeries_YInt) isLiftSeries_YValue() {} - -func (*LiftSeries_YString) isLiftSeries_YValue() {} - -func (*LiftSeries_YBucket) isLiftSeries_YValue() {} - -type isLiftSeries_YCountValue interface { - isLiftSeries_YCountValue() -} - -type LiftSeries_YCount struct { - YCount uint64 `protobuf:"varint,4,opt,name=y_count,json=yCount,proto3,oneof"` -} - -type LiftSeries_WeightedYCount struct { - WeightedYCount float64 `protobuf:"fixed64,5,opt,name=weighted_y_count,json=weightedYCount,proto3,oneof"` -} - -func (*LiftSeries_YCount) isLiftSeries_YCountValue() {} - -func (*LiftSeries_WeightedYCount) isLiftSeries_YCountValue() {} - -// The complete set of statistics for a given feature name for a dataset. -type FeatureNameStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // One can identify a field either by the name (for simple fields), or by - // a path (for structured fields). Note that: - // name: "foo" - // is equivalent to: - // path: {step:"foo"} - // Note: this oneof must be consistently either name or path across all - // FeatureNameStatistics in one DatasetFeatureStatistics. - // - // Types that are assignable to FieldId: - // *FeatureNameStatistics_Name - // *FeatureNameStatistics_Path - FieldId isFeatureNameStatistics_FieldId `protobuf_oneof:"field_id"` - // The data type of the feature - Type FeatureNameStatistics_Type `protobuf:"varint,2,opt,name=type,proto3,enum=tensorflow.metadata.v0.FeatureNameStatistics_Type" json:"type,omitempty"` - // The statistics of the values of the feature. - // - // Types that are assignable to Stats: - // *FeatureNameStatistics_NumStats - // *FeatureNameStatistics_StringStats - // *FeatureNameStatistics_BytesStats - // *FeatureNameStatistics_StructStats - Stats isFeatureNameStatistics_Stats `protobuf_oneof:"stats"` - // Any custom statistics can be stored in this list. - CustomStats []*CustomStatistic `protobuf:"bytes,6,rep,name=custom_stats,json=customStats,proto3" json:"custom_stats,omitempty"` -} - -func (x *FeatureNameStatistics) Reset() { - *x = FeatureNameStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureNameStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureNameStatistics) ProtoMessage() {} - -func (x *FeatureNameStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureNameStatistics.ProtoReflect.Descriptor instead. -func (*FeatureNameStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{7} -} - -func (m *FeatureNameStatistics) GetFieldId() isFeatureNameStatistics_FieldId { - if m != nil { - return m.FieldId - } - return nil -} - -func (x *FeatureNameStatistics) GetName() string { - if x, ok := x.GetFieldId().(*FeatureNameStatistics_Name); ok { - return x.Name - } - return "" -} - -func (x *FeatureNameStatistics) GetPath() *Path { - if x, ok := x.GetFieldId().(*FeatureNameStatistics_Path); ok { - return x.Path - } - return nil -} - -func (x *FeatureNameStatistics) GetType() FeatureNameStatistics_Type { - if x != nil { - return x.Type - } - return FeatureNameStatistics_INT -} - -func (m *FeatureNameStatistics) GetStats() isFeatureNameStatistics_Stats { - if m != nil { - return m.Stats - } - return nil -} - -func (x *FeatureNameStatistics) GetNumStats() *NumericStatistics { - if x, ok := x.GetStats().(*FeatureNameStatistics_NumStats); ok { - return x.NumStats - } - return nil -} - -func (x *FeatureNameStatistics) GetStringStats() *StringStatistics { - if x, ok := x.GetStats().(*FeatureNameStatistics_StringStats); ok { - return x.StringStats - } - return nil -} - -func (x *FeatureNameStatistics) GetBytesStats() *BytesStatistics { - if x, ok := x.GetStats().(*FeatureNameStatistics_BytesStats); ok { - return x.BytesStats - } - return nil -} - -func (x *FeatureNameStatistics) GetStructStats() *StructStatistics { - if x, ok := x.GetStats().(*FeatureNameStatistics_StructStats); ok { - return x.StructStats - } - return nil -} - -func (x *FeatureNameStatistics) GetCustomStats() []*CustomStatistic { - if x != nil { - return x.CustomStats - } - return nil -} - -type isFeatureNameStatistics_FieldId interface { - isFeatureNameStatistics_FieldId() -} - -type FeatureNameStatistics_Name struct { - // The feature name - Name string `protobuf:"bytes,1,opt,name=name,proto3,oneof"` -} - -type FeatureNameStatistics_Path struct { - // The path of the feature. - Path *Path `protobuf:"bytes,8,opt,name=path,proto3,oneof"` -} - -func (*FeatureNameStatistics_Name) isFeatureNameStatistics_FieldId() {} - -func (*FeatureNameStatistics_Path) isFeatureNameStatistics_FieldId() {} - -type isFeatureNameStatistics_Stats interface { - isFeatureNameStatistics_Stats() -} - -type FeatureNameStatistics_NumStats struct { - NumStats *NumericStatistics `protobuf:"bytes,3,opt,name=num_stats,json=numStats,proto3,oneof"` -} - -type FeatureNameStatistics_StringStats struct { - StringStats *StringStatistics `protobuf:"bytes,4,opt,name=string_stats,json=stringStats,proto3,oneof"` -} - -type FeatureNameStatistics_BytesStats struct { - BytesStats *BytesStatistics `protobuf:"bytes,5,opt,name=bytes_stats,json=bytesStats,proto3,oneof"` -} - -type FeatureNameStatistics_StructStats struct { - StructStats *StructStatistics `protobuf:"bytes,7,opt,name=struct_stats,json=structStats,proto3,oneof"` -} - -func (*FeatureNameStatistics_NumStats) isFeatureNameStatistics_Stats() {} - -func (*FeatureNameStatistics_StringStats) isFeatureNameStatistics_Stats() {} - -func (*FeatureNameStatistics_BytesStats) isFeatureNameStatistics_Stats() {} - -func (*FeatureNameStatistics_StructStats) isFeatureNameStatistics_Stats() {} - -// Common weighted statistics for all feature types. Statistics counting number -// of values (i.e., avg_num_values and tot_num_values) include NaNs. -// If the weighted column is missing, then this counts as a weight of 1 -// for that example. -type WeightedCommonStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Weighted number of examples not missing. - NumNonMissing float64 `protobuf:"fixed64,1,opt,name=num_non_missing,json=numNonMissing,proto3" json:"num_non_missing,omitempty"` - // Weighted number of examples missing. - // Note that if the weighted column is zero, this does not count - // as missing. - NumMissing float64 `protobuf:"fixed64,2,opt,name=num_missing,json=numMissing,proto3" json:"num_missing,omitempty"` - // average number of values, weighted by the number of examples. - AvgNumValues float64 `protobuf:"fixed64,3,opt,name=avg_num_values,json=avgNumValues,proto3" json:"avg_num_values,omitempty"` - // tot_num_values = avg_num_values * num_non_missing. - // This is calculated directly, so should have less numerical error. - TotNumValues float64 `protobuf:"fixed64,4,opt,name=tot_num_values,json=totNumValues,proto3" json:"tot_num_values,omitempty"` -} - -func (x *WeightedCommonStatistics) Reset() { - *x = WeightedCommonStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WeightedCommonStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WeightedCommonStatistics) ProtoMessage() {} - -func (x *WeightedCommonStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WeightedCommonStatistics.ProtoReflect.Descriptor instead. -func (*WeightedCommonStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{8} -} - -func (x *WeightedCommonStatistics) GetNumNonMissing() float64 { - if x != nil { - return x.NumNonMissing - } - return 0 -} - -func (x *WeightedCommonStatistics) GetNumMissing() float64 { - if x != nil { - return x.NumMissing - } - return 0 -} - -func (x *WeightedCommonStatistics) GetAvgNumValues() float64 { - if x != nil { - return x.AvgNumValues - } - return 0 -} - -func (x *WeightedCommonStatistics) GetTotNumValues() float64 { - if x != nil { - return x.TotNumValues - } - return 0 -} - -// Stores the name and value of any custom statistic. The value can be a string, -// double, or histogram. -type CustomStatistic struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to Val: - // *CustomStatistic_Num - // *CustomStatistic_Str - // *CustomStatistic_Histogram - // *CustomStatistic_RankHistogram - Val isCustomStatistic_Val `protobuf_oneof:"val"` -} - -func (x *CustomStatistic) Reset() { - *x = CustomStatistic{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CustomStatistic) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CustomStatistic) ProtoMessage() {} - -func (x *CustomStatistic) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CustomStatistic.ProtoReflect.Descriptor instead. -func (*CustomStatistic) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{9} -} - -func (x *CustomStatistic) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *CustomStatistic) GetVal() isCustomStatistic_Val { - if m != nil { - return m.Val - } - return nil -} - -func (x *CustomStatistic) GetNum() float64 { - if x, ok := x.GetVal().(*CustomStatistic_Num); ok { - return x.Num - } - return 0 -} - -func (x *CustomStatistic) GetStr() string { - if x, ok := x.GetVal().(*CustomStatistic_Str); ok { - return x.Str - } - return "" -} - -func (x *CustomStatistic) GetHistogram() *Histogram { - if x, ok := x.GetVal().(*CustomStatistic_Histogram); ok { - return x.Histogram - } - return nil -} - -func (x *CustomStatistic) GetRankHistogram() *RankHistogram { - if x, ok := x.GetVal().(*CustomStatistic_RankHistogram); ok { - return x.RankHistogram - } - return nil -} - -type isCustomStatistic_Val interface { - isCustomStatistic_Val() -} - -type CustomStatistic_Num struct { - Num float64 `protobuf:"fixed64,2,opt,name=num,proto3,oneof"` -} - -type CustomStatistic_Str struct { - Str string `protobuf:"bytes,3,opt,name=str,proto3,oneof"` -} - -type CustomStatistic_Histogram struct { - Histogram *Histogram `protobuf:"bytes,4,opt,name=histogram,proto3,oneof"` -} - -type CustomStatistic_RankHistogram struct { - RankHistogram *RankHistogram `protobuf:"bytes,5,opt,name=rank_histogram,json=rankHistogram,proto3,oneof"` -} - -func (*CustomStatistic_Num) isCustomStatistic_Val() {} - -func (*CustomStatistic_Str) isCustomStatistic_Val() {} - -func (*CustomStatistic_Histogram) isCustomStatistic_Val() {} - -func (*CustomStatistic_RankHistogram) isCustomStatistic_Val() {} - -// Statistics for a numeric feature in a dataset. -type NumericStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CommonStats *CommonStatistics `protobuf:"bytes,1,opt,name=common_stats,json=commonStats,proto3" json:"common_stats,omitempty"` - // The mean of the values - Mean float64 `protobuf:"fixed64,2,opt,name=mean,proto3" json:"mean,omitempty"` - // The standard deviation of the values - StdDev float64 `protobuf:"fixed64,3,opt,name=std_dev,json=stdDev,proto3" json:"std_dev,omitempty"` - // The number of values that equal 0 - NumZeros uint64 `protobuf:"varint,4,opt,name=num_zeros,json=numZeros,proto3" json:"num_zeros,omitempty"` - // The minimum value - Min float64 `protobuf:"fixed64,5,opt,name=min,proto3" json:"min,omitempty"` - // The median value - Median float64 `protobuf:"fixed64,6,opt,name=median,proto3" json:"median,omitempty"` - // The maximum value - Max float64 `protobuf:"fixed64,7,opt,name=max,proto3" json:"max,omitempty"` - // The histogram(s) of the feature values. - Histograms []*Histogram `protobuf:"bytes,8,rep,name=histograms,proto3" json:"histograms,omitempty"` - // Weighted statistics for the feature, if the values have weights. - WeightedNumericStats *WeightedNumericStatistics `protobuf:"bytes,9,opt,name=weighted_numeric_stats,json=weightedNumericStats,proto3" json:"weighted_numeric_stats,omitempty"` -} - -func (x *NumericStatistics) Reset() { - *x = NumericStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NumericStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NumericStatistics) ProtoMessage() {} - -func (x *NumericStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NumericStatistics.ProtoReflect.Descriptor instead. -func (*NumericStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{10} -} - -func (x *NumericStatistics) GetCommonStats() *CommonStatistics { - if x != nil { - return x.CommonStats - } - return nil -} - -func (x *NumericStatistics) GetMean() float64 { - if x != nil { - return x.Mean - } - return 0 -} - -func (x *NumericStatistics) GetStdDev() float64 { - if x != nil { - return x.StdDev - } - return 0 -} - -func (x *NumericStatistics) GetNumZeros() uint64 { - if x != nil { - return x.NumZeros - } - return 0 -} - -func (x *NumericStatistics) GetMin() float64 { - if x != nil { - return x.Min - } - return 0 -} - -func (x *NumericStatistics) GetMedian() float64 { - if x != nil { - return x.Median - } - return 0 -} - -func (x *NumericStatistics) GetMax() float64 { - if x != nil { - return x.Max - } - return 0 -} - -func (x *NumericStatistics) GetHistograms() []*Histogram { - if x != nil { - return x.Histograms - } - return nil -} - -func (x *NumericStatistics) GetWeightedNumericStats() *WeightedNumericStatistics { - if x != nil { - return x.WeightedNumericStats - } - return nil -} - -// Statistics for a string feature in a dataset. -type StringStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CommonStats *CommonStatistics `protobuf:"bytes,1,opt,name=common_stats,json=commonStats,proto3" json:"common_stats,omitempty"` - // The number of unique values - Unique uint64 `protobuf:"varint,2,opt,name=unique,proto3" json:"unique,omitempty"` - // A sorted list of the most-frequent values and their frequencies, with - // the most-frequent being first. - TopValues []*StringStatistics_FreqAndValue `protobuf:"bytes,3,rep,name=top_values,json=topValues,proto3" json:"top_values,omitempty"` - // The average length of the values - AvgLength float32 `protobuf:"fixed32,4,opt,name=avg_length,json=avgLength,proto3" json:"avg_length,omitempty"` - // The rank histogram for the values of the feature. - // The rank is used to measure of how commonly the value is found in the - // dataset. The most common value would have a rank of 1, with the second-most - // common value having a rank of 2, and so on. - RankHistogram *RankHistogram `protobuf:"bytes,5,opt,name=rank_histogram,json=rankHistogram,proto3" json:"rank_histogram,omitempty"` - // Weighted statistics for the feature, if the values have weights. - WeightedStringStats *WeightedStringStatistics `protobuf:"bytes,6,opt,name=weighted_string_stats,json=weightedStringStats,proto3" json:"weighted_string_stats,omitempty"` - // A vocabulary file, used for vocabularies too large to store in the proto - // itself. Note that the file may be relative to some context-dependent - // directory. E.g. in TFX the feature statistics will live in a PPP and - // vocabulary file names will be relative to this PPP. - VocabularyFile string `protobuf:"bytes,7,opt,name=vocabulary_file,json=vocabularyFile,proto3" json:"vocabulary_file,omitempty"` -} - -func (x *StringStatistics) Reset() { - *x = StringStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StringStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StringStatistics) ProtoMessage() {} - -func (x *StringStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StringStatistics.ProtoReflect.Descriptor instead. -func (*StringStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{11} -} - -func (x *StringStatistics) GetCommonStats() *CommonStatistics { - if x != nil { - return x.CommonStats - } - return nil -} - -func (x *StringStatistics) GetUnique() uint64 { - if x != nil { - return x.Unique - } - return 0 -} - -func (x *StringStatistics) GetTopValues() []*StringStatistics_FreqAndValue { - if x != nil { - return x.TopValues - } - return nil -} - -func (x *StringStatistics) GetAvgLength() float32 { - if x != nil { - return x.AvgLength - } - return 0 -} - -func (x *StringStatistics) GetRankHistogram() *RankHistogram { - if x != nil { - return x.RankHistogram - } - return nil -} - -func (x *StringStatistics) GetWeightedStringStats() *WeightedStringStatistics { - if x != nil { - return x.WeightedStringStats - } - return nil -} - -func (x *StringStatistics) GetVocabularyFile() string { - if x != nil { - return x.VocabularyFile - } - return "" -} - -// Statistics for a weighted numeric feature in a dataset. -type WeightedNumericStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The weighted mean of the values - Mean float64 `protobuf:"fixed64,1,opt,name=mean,proto3" json:"mean,omitempty"` - // The weighted standard deviation of the values - StdDev float64 `protobuf:"fixed64,2,opt,name=std_dev,json=stdDev,proto3" json:"std_dev,omitempty"` - // The weighted median of the values - Median float64 `protobuf:"fixed64,3,opt,name=median,proto3" json:"median,omitempty"` - // The histogram(s) of the weighted feature values. - Histograms []*Histogram `protobuf:"bytes,4,rep,name=histograms,proto3" json:"histograms,omitempty"` -} - -func (x *WeightedNumericStatistics) Reset() { - *x = WeightedNumericStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WeightedNumericStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WeightedNumericStatistics) ProtoMessage() {} - -func (x *WeightedNumericStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WeightedNumericStatistics.ProtoReflect.Descriptor instead. -func (*WeightedNumericStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{12} -} - -func (x *WeightedNumericStatistics) GetMean() float64 { - if x != nil { - return x.Mean - } - return 0 -} - -func (x *WeightedNumericStatistics) GetStdDev() float64 { - if x != nil { - return x.StdDev - } - return 0 -} - -func (x *WeightedNumericStatistics) GetMedian() float64 { - if x != nil { - return x.Median - } - return 0 -} - -func (x *WeightedNumericStatistics) GetHistograms() []*Histogram { - if x != nil { - return x.Histograms - } - return nil -} - -// Statistics for a weighted string feature in a dataset. -type WeightedStringStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // A sorted list of the most-frequent values and their weighted frequencies, - // with the most-frequent being first. - TopValues []*StringStatistics_FreqAndValue `protobuf:"bytes,1,rep,name=top_values,json=topValues,proto3" json:"top_values,omitempty"` - // The rank histogram for the weighted values of the feature. - RankHistogram *RankHistogram `protobuf:"bytes,2,opt,name=rank_histogram,json=rankHistogram,proto3" json:"rank_histogram,omitempty"` -} - -func (x *WeightedStringStatistics) Reset() { - *x = WeightedStringStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WeightedStringStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WeightedStringStatistics) ProtoMessage() {} - -func (x *WeightedStringStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WeightedStringStatistics.ProtoReflect.Descriptor instead. -func (*WeightedStringStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{13} -} - -func (x *WeightedStringStatistics) GetTopValues() []*StringStatistics_FreqAndValue { - if x != nil { - return x.TopValues - } - return nil -} - -func (x *WeightedStringStatistics) GetRankHistogram() *RankHistogram { - if x != nil { - return x.RankHistogram - } - return nil -} - -// Statistics for a bytes feature in a dataset. -type BytesStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CommonStats *CommonStatistics `protobuf:"bytes,1,opt,name=common_stats,json=commonStats,proto3" json:"common_stats,omitempty"` - // The number of unique values - Unique uint64 `protobuf:"varint,2,opt,name=unique,proto3" json:"unique,omitempty"` - // The average number of bytes in a value - AvgNumBytes float32 `protobuf:"fixed32,3,opt,name=avg_num_bytes,json=avgNumBytes,proto3" json:"avg_num_bytes,omitempty"` - // The minimum number of bytes in a value - MinNumBytes float32 `protobuf:"fixed32,4,opt,name=min_num_bytes,json=minNumBytes,proto3" json:"min_num_bytes,omitempty"` - // The maximum number of bytes in a value - MaxNumBytes float32 `protobuf:"fixed32,5,opt,name=max_num_bytes,json=maxNumBytes,proto3" json:"max_num_bytes,omitempty"` -} - -func (x *BytesStatistics) Reset() { - *x = BytesStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BytesStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BytesStatistics) ProtoMessage() {} - -func (x *BytesStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BytesStatistics.ProtoReflect.Descriptor instead. -func (*BytesStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{14} -} - -func (x *BytesStatistics) GetCommonStats() *CommonStatistics { - if x != nil { - return x.CommonStats - } - return nil -} - -func (x *BytesStatistics) GetUnique() uint64 { - if x != nil { - return x.Unique - } - return 0 -} - -func (x *BytesStatistics) GetAvgNumBytes() float32 { - if x != nil { - return x.AvgNumBytes - } - return 0 -} - -func (x *BytesStatistics) GetMinNumBytes() float32 { - if x != nil { - return x.MinNumBytes - } - return 0 -} - -func (x *BytesStatistics) GetMaxNumBytes() float32 { - if x != nil { - return x.MaxNumBytes - } - return 0 -} - -type StructStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CommonStats *CommonStatistics `protobuf:"bytes,1,opt,name=common_stats,json=commonStats,proto3" json:"common_stats,omitempty"` -} - -func (x *StructStatistics) Reset() { - *x = StructStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StructStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StructStatistics) ProtoMessage() {} - -func (x *StructStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StructStatistics.ProtoReflect.Descriptor instead. -func (*StructStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{15} -} - -func (x *StructStatistics) GetCommonStats() *CommonStatistics { - if x != nil { - return x.CommonStats - } - return nil -} - -// Common statistics for all feature types. Statistics counting number of values -// (i.e., min_num_values, max_num_values, avg_num_values, and tot_num_values) -// include NaNs. -type CommonStatistics struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The number of examples with at least one value for this feature. - NumNonMissing uint64 `protobuf:"varint,1,opt,name=num_non_missing,json=numNonMissing,proto3" json:"num_non_missing,omitempty"` - // The number of examples with no values for this feature. - NumMissing uint64 `protobuf:"varint,2,opt,name=num_missing,json=numMissing,proto3" json:"num_missing,omitempty"` - // The minimum number of values in a single example for this feature. - MinNumValues uint64 `protobuf:"varint,3,opt,name=min_num_values,json=minNumValues,proto3" json:"min_num_values,omitempty"` - // The maximum number of values in a single example for this feature. - MaxNumValues uint64 `protobuf:"varint,4,opt,name=max_num_values,json=maxNumValues,proto3" json:"max_num_values,omitempty"` - // The average number of values in a single example for this feature. - AvgNumValues float32 `protobuf:"fixed32,5,opt,name=avg_num_values,json=avgNumValues,proto3" json:"avg_num_values,omitempty"` - // tot_num_values = avg_num_values * num_non_missing. - // This is calculated directly, so should have less numerical error. - TotNumValues uint64 `protobuf:"varint,8,opt,name=tot_num_values,json=totNumValues,proto3" json:"tot_num_values,omitempty"` - // The quantiles histogram for the number of values in this feature. - NumValuesHistogram *Histogram `protobuf:"bytes,6,opt,name=num_values_histogram,json=numValuesHistogram,proto3" json:"num_values_histogram,omitempty"` - WeightedCommonStats *WeightedCommonStatistics `protobuf:"bytes,7,opt,name=weighted_common_stats,json=weightedCommonStats,proto3" json:"weighted_common_stats,omitempty"` - // The histogram for the number of features in the feature list (only set if - // this feature is a non-context feature from a tf.SequenceExample). - // This is different from num_values_histogram, as num_values_histogram tracks - // the count of all values for a feature in an example, whereas this tracks - // the length of the feature list for this feature in an example (where each - // feature list can contain multiple values). - FeatureListLengthHistogram *Histogram `protobuf:"bytes,9,opt,name=feature_list_length_histogram,json=featureListLengthHistogram,proto3" json:"feature_list_length_histogram,omitempty"` -} - -func (x *CommonStatistics) Reset() { - *x = CommonStatistics{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CommonStatistics) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CommonStatistics) ProtoMessage() {} - -func (x *CommonStatistics) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CommonStatistics.ProtoReflect.Descriptor instead. -func (*CommonStatistics) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{16} -} - -func (x *CommonStatistics) GetNumNonMissing() uint64 { - if x != nil { - return x.NumNonMissing - } - return 0 -} - -func (x *CommonStatistics) GetNumMissing() uint64 { - if x != nil { - return x.NumMissing - } - return 0 -} - -func (x *CommonStatistics) GetMinNumValues() uint64 { - if x != nil { - return x.MinNumValues - } - return 0 -} - -func (x *CommonStatistics) GetMaxNumValues() uint64 { - if x != nil { - return x.MaxNumValues - } - return 0 -} - -func (x *CommonStatistics) GetAvgNumValues() float32 { - if x != nil { - return x.AvgNumValues - } - return 0 -} - -func (x *CommonStatistics) GetTotNumValues() uint64 { - if x != nil { - return x.TotNumValues - } - return 0 -} - -func (x *CommonStatistics) GetNumValuesHistogram() *Histogram { - if x != nil { - return x.NumValuesHistogram - } - return nil -} - -func (x *CommonStatistics) GetWeightedCommonStats() *WeightedCommonStatistics { - if x != nil { - return x.WeightedCommonStats - } - return nil -} - -func (x *CommonStatistics) GetFeatureListLengthHistogram() *Histogram { - if x != nil { - return x.FeatureListLengthHistogram - } - return nil -} - -// The data used to create a histogram of a numeric feature for a dataset. -type Histogram struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The number of NaN values in the dataset. - NumNan uint64 `protobuf:"varint,1,opt,name=num_nan,json=numNan,proto3" json:"num_nan,omitempty"` - // The number of undefined values in the dataset. - NumUndefined uint64 `protobuf:"varint,2,opt,name=num_undefined,json=numUndefined,proto3" json:"num_undefined,omitempty"` - // A list of buckets in the histogram, sorted from lowest bucket to highest - // bucket. - Buckets []*Histogram_Bucket `protobuf:"bytes,3,rep,name=buckets,proto3" json:"buckets,omitempty"` - // The type of the histogram. - Type Histogram_HistogramType `protobuf:"varint,4,opt,name=type,proto3,enum=tensorflow.metadata.v0.Histogram_HistogramType" json:"type,omitempty"` - // An optional descriptive name of the histogram, to be used for labeling. - Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *Histogram) Reset() { - *x = Histogram{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Histogram) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Histogram) ProtoMessage() {} - -func (x *Histogram) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Histogram.ProtoReflect.Descriptor instead. -func (*Histogram) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{17} -} - -func (x *Histogram) GetNumNan() uint64 { - if x != nil { - return x.NumNan - } - return 0 -} - -func (x *Histogram) GetNumUndefined() uint64 { - if x != nil { - return x.NumUndefined - } - return 0 -} - -func (x *Histogram) GetBuckets() []*Histogram_Bucket { - if x != nil { - return x.Buckets - } - return nil -} - -func (x *Histogram) GetType() Histogram_HistogramType { - if x != nil { - return x.Type - } - return Histogram_STANDARD -} - -func (x *Histogram) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// The data used to create a rank histogram of a non-numeric feature of a -// dataset. The rank of a value in a feature can be used as a measure of how -// commonly the value is found in the entire dataset. With bucket sizes of one, -// this becomes a distribution function of all feature values. -type RankHistogram struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // A list of buckets in the histogram, sorted from lowest-ranked bucket to - // highest-ranked bucket. - Buckets []*RankHistogram_Bucket `protobuf:"bytes,1,rep,name=buckets,proto3" json:"buckets,omitempty"` - // An optional descriptive name of the histogram, to be used for labeling. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *RankHistogram) Reset() { - *x = RankHistogram{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RankHistogram) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RankHistogram) ProtoMessage() {} - -func (x *RankHistogram) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RankHistogram.ProtoReflect.Descriptor instead. -func (*RankHistogram) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{18} -} - -func (x *RankHistogram) GetBuckets() []*RankHistogram_Bucket { - if x != nil { - return x.Buckets - } - return nil -} - -func (x *RankHistogram) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// A bucket for referring to binned numeric features. -type LiftSeries_Bucket struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The low value of the bucket, inclusive. - LowValue float64 `protobuf:"fixed64,1,opt,name=low_value,json=lowValue,proto3" json:"low_value,omitempty"` - // The high value of the bucket, exclusive (unless the high_value is - // positive infinity). - HighValue float64 `protobuf:"fixed64,2,opt,name=high_value,json=highValue,proto3" json:"high_value,omitempty"` -} - -func (x *LiftSeries_Bucket) Reset() { - *x = LiftSeries_Bucket{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LiftSeries_Bucket) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LiftSeries_Bucket) ProtoMessage() {} - -func (x *LiftSeries_Bucket) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LiftSeries_Bucket.ProtoReflect.Descriptor instead. -func (*LiftSeries_Bucket) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *LiftSeries_Bucket) GetLowValue() float64 { - if x != nil { - return x.LowValue - } - return 0 -} - -func (x *LiftSeries_Bucket) GetHighValue() float64 { - if x != nil { - return x.HighValue - } - return 0 -} - -// A container for lift information about a specific value of path_x. -type LiftSeries_LiftValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to XValue: - // *LiftSeries_LiftValue_XInt - // *LiftSeries_LiftValue_XString - XValue isLiftSeries_LiftValue_XValue `protobuf_oneof:"x_value"` - // P(path_y=y|path_x=x) / P(path_y=y) for x_value and the enclosing y_value. - // In terms of concrete fields, this number represents: - // (x_and_y_count / x_count) / (y_count / num_examples) - Lift float64 `protobuf:"fixed64,3,opt,name=lift,proto3" json:"lift,omitempty"` - // The number of examples in which x_value appears. - // - // Types that are assignable to XCountValue: - // *LiftSeries_LiftValue_XCount - // *LiftSeries_LiftValue_WeightedXCount - XCountValue isLiftSeries_LiftValue_XCountValue `protobuf_oneof:"x_count_value"` - // The number of examples in which x_value appears and y_value appears. - // - // Types that are assignable to XAndYCountValue: - // *LiftSeries_LiftValue_XAndYCount - // *LiftSeries_LiftValue_WeightedXAndYCount - XAndYCountValue isLiftSeries_LiftValue_XAndYCountValue `protobuf_oneof:"x_and_y_count_value"` -} - -func (x *LiftSeries_LiftValue) Reset() { - *x = LiftSeries_LiftValue{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LiftSeries_LiftValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LiftSeries_LiftValue) ProtoMessage() {} - -func (x *LiftSeries_LiftValue) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LiftSeries_LiftValue.ProtoReflect.Descriptor instead. -func (*LiftSeries_LiftValue) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{6, 1} -} - -func (m *LiftSeries_LiftValue) GetXValue() isLiftSeries_LiftValue_XValue { - if m != nil { - return m.XValue - } - return nil -} - -func (x *LiftSeries_LiftValue) GetXInt() int32 { - if x, ok := x.GetXValue().(*LiftSeries_LiftValue_XInt); ok { - return x.XInt - } - return 0 -} - -func (x *LiftSeries_LiftValue) GetXString() string { - if x, ok := x.GetXValue().(*LiftSeries_LiftValue_XString); ok { - return x.XString - } - return "" -} - -func (x *LiftSeries_LiftValue) GetLift() float64 { - if x != nil { - return x.Lift - } - return 0 -} - -func (m *LiftSeries_LiftValue) GetXCountValue() isLiftSeries_LiftValue_XCountValue { - if m != nil { - return m.XCountValue - } - return nil -} - -func (x *LiftSeries_LiftValue) GetXCount() uint64 { - if x, ok := x.GetXCountValue().(*LiftSeries_LiftValue_XCount); ok { - return x.XCount - } - return 0 -} - -func (x *LiftSeries_LiftValue) GetWeightedXCount() float64 { - if x, ok := x.GetXCountValue().(*LiftSeries_LiftValue_WeightedXCount); ok { - return x.WeightedXCount - } - return 0 -} - -func (m *LiftSeries_LiftValue) GetXAndYCountValue() isLiftSeries_LiftValue_XAndYCountValue { - if m != nil { - return m.XAndYCountValue - } - return nil -} - -func (x *LiftSeries_LiftValue) GetXAndYCount() uint64 { - if x, ok := x.GetXAndYCountValue().(*LiftSeries_LiftValue_XAndYCount); ok { - return x.XAndYCount - } - return 0 -} - -func (x *LiftSeries_LiftValue) GetWeightedXAndYCount() float64 { - if x, ok := x.GetXAndYCountValue().(*LiftSeries_LiftValue_WeightedXAndYCount); ok { - return x.WeightedXAndYCount - } - return 0 -} - -type isLiftSeries_LiftValue_XValue interface { - isLiftSeries_LiftValue_XValue() -} - -type LiftSeries_LiftValue_XInt struct { - XInt int32 `protobuf:"varint,1,opt,name=x_int,json=xInt,proto3,oneof"` -} - -type LiftSeries_LiftValue_XString struct { - XString string `protobuf:"bytes,2,opt,name=x_string,json=xString,proto3,oneof"` -} - -func (*LiftSeries_LiftValue_XInt) isLiftSeries_LiftValue_XValue() {} - -func (*LiftSeries_LiftValue_XString) isLiftSeries_LiftValue_XValue() {} - -type isLiftSeries_LiftValue_XCountValue interface { - isLiftSeries_LiftValue_XCountValue() -} - -type LiftSeries_LiftValue_XCount struct { - XCount uint64 `protobuf:"varint,4,opt,name=x_count,json=xCount,proto3,oneof"` -} - -type LiftSeries_LiftValue_WeightedXCount struct { - WeightedXCount float64 `protobuf:"fixed64,5,opt,name=weighted_x_count,json=weightedXCount,proto3,oneof"` -} - -func (*LiftSeries_LiftValue_XCount) isLiftSeries_LiftValue_XCountValue() {} - -func (*LiftSeries_LiftValue_WeightedXCount) isLiftSeries_LiftValue_XCountValue() {} - -type isLiftSeries_LiftValue_XAndYCountValue interface { - isLiftSeries_LiftValue_XAndYCountValue() -} - -type LiftSeries_LiftValue_XAndYCount struct { - XAndYCount uint64 `protobuf:"varint,6,opt,name=x_and_y_count,json=xAndYCount,proto3,oneof"` -} - -type LiftSeries_LiftValue_WeightedXAndYCount struct { - WeightedXAndYCount float64 `protobuf:"fixed64,7,opt,name=weighted_x_and_y_count,json=weightedXAndYCount,proto3,oneof"` -} - -func (*LiftSeries_LiftValue_XAndYCount) isLiftSeries_LiftValue_XAndYCountValue() {} - -func (*LiftSeries_LiftValue_WeightedXAndYCount) isLiftSeries_LiftValue_XAndYCountValue() {} - -type StringStatistics_FreqAndValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - // The number of times the value occurs. Stored as a double to be able to - // handle weighted features. - Frequency float64 `protobuf:"fixed64,3,opt,name=frequency,proto3" json:"frequency,omitempty"` -} - -func (x *StringStatistics_FreqAndValue) Reset() { - *x = StringStatistics_FreqAndValue{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StringStatistics_FreqAndValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StringStatistics_FreqAndValue) ProtoMessage() {} - -func (x *StringStatistics_FreqAndValue) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StringStatistics_FreqAndValue.ProtoReflect.Descriptor instead. -func (*StringStatistics_FreqAndValue) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{11, 0} -} - -func (x *StringStatistics_FreqAndValue) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -func (x *StringStatistics_FreqAndValue) GetFrequency() float64 { - if x != nil { - return x.Frequency - } - return 0 -} - -// Each bucket defines its low and high values along with its count. The -// low and high values must be a real number or positive or negative -// infinity. They cannot be NaN or undefined. Counts of those special values -// can be found in the numNaN and numUndefined fields. -type Histogram_Bucket struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The low value of the bucket, inclusive. - LowValue float64 `protobuf:"fixed64,1,opt,name=low_value,json=lowValue,proto3" json:"low_value,omitempty"` - // The high value of the bucket, exclusive (unless the highValue is - // positive infinity). - HighValue float64 `protobuf:"fixed64,2,opt,name=high_value,json=highValue,proto3" json:"high_value,omitempty"` - // The number of items in the bucket. Stored as a double to be able to - // handle weighted histograms. - SampleCount float64 `protobuf:"fixed64,4,opt,name=sample_count,json=sampleCount,proto3" json:"sample_count,omitempty"` -} - -func (x *Histogram_Bucket) Reset() { - *x = Histogram_Bucket{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Histogram_Bucket) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Histogram_Bucket) ProtoMessage() {} - -func (x *Histogram_Bucket) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Histogram_Bucket.ProtoReflect.Descriptor instead. -func (*Histogram_Bucket) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{17, 0} -} - -func (x *Histogram_Bucket) GetLowValue() float64 { - if x != nil { - return x.LowValue - } - return 0 -} - -func (x *Histogram_Bucket) GetHighValue() float64 { - if x != nil { - return x.HighValue - } - return 0 -} - -func (x *Histogram_Bucket) GetSampleCount() float64 { - if x != nil { - return x.SampleCount - } - return 0 -} - -// Each bucket defines its start and end ranks along with its count. -type RankHistogram_Bucket struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The low rank of the bucket, inclusive. - LowRank uint64 `protobuf:"varint,1,opt,name=low_rank,json=lowRank,proto3" json:"low_rank,omitempty"` - // The high rank of the bucket, exclusive. - HighRank uint64 `protobuf:"varint,2,opt,name=high_rank,json=highRank,proto3" json:"high_rank,omitempty"` - // The label for the bucket. Can be used to list or summarize the values in - // this rank bucket. - Label string `protobuf:"bytes,4,opt,name=label,proto3" json:"label,omitempty"` - // The number of items in the bucket. Stored as a double to be able to - // handle weighted histograms. - SampleCount float64 `protobuf:"fixed64,5,opt,name=sample_count,json=sampleCount,proto3" json:"sample_count,omitempty"` -} - -func (x *RankHistogram_Bucket) Reset() { - *x = RankHistogram_Bucket{} - if protoimpl.UnsafeEnabled { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RankHistogram_Bucket) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RankHistogram_Bucket) ProtoMessage() {} - -func (x *RankHistogram_Bucket) ProtoReflect() protoreflect.Message { - mi := &file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RankHistogram_Bucket.ProtoReflect.Descriptor instead. -func (*RankHistogram_Bucket) Descriptor() ([]byte, []int) { - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP(), []int{18, 0} -} - -func (x *RankHistogram_Bucket) GetLowRank() uint64 { - if x != nil { - return x.LowRank - } - return 0 -} - -func (x *RankHistogram_Bucket) GetHighRank() uint64 { - if x != nil { - return x.HighRank - } - return 0 -} - -func (x *RankHistogram_Bucket) GetLabel() string { - if x != nil { - return x.Label - } - return "" -} - -func (x *RankHistogram_Bucket) GetSampleCount() float64 { - if x != nil { - return x.SampleCount - } - return 0 -} - -var File_tensorflow_metadata_proto_v0_statistics_proto protoreflect.FileDescriptor - -var file_tensorflow_metadata_proto_v0_statistics_proto_rawDesc = []byte{ - 0x0a, 0x2d, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x30, 0x2f, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x16, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x1a, 0x27, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x76, 0x30, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x6c, 0x0a, 0x1c, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x4c, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x44, 0x61, 0x74, 0x61, - 0x73, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, - 0x74, 0x69, 0x63, 0x73, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x73, 0x22, 0xa7, - 0x02, 0x0a, 0x18, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x6e, - 0x75, 0x6d, 0x5f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x01, 0x52, 0x13, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4e, 0x75, 0x6d, 0x45, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x12, 0x55, 0x0a, 0x0e, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x0d, 0x63, 0x72, 0x6f, 0x73, 0x73, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0xef, 0x02, 0x0a, 0x16, 0x43, 0x72, 0x6f, - 0x73, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, - 0x69, 0x63, 0x73, 0x12, 0x33, 0x0a, 0x06, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x78, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x50, 0x61, 0x74, - 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x58, 0x12, 0x33, 0x0a, 0x06, 0x70, 0x61, 0x74, 0x68, - 0x5f, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x59, 0x12, 0x14, 0x0a, - 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, - 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x43, 0x72, 0x6f, - 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x48, 0x00, 0x52, 0x0d, - 0x6e, 0x75, 0x6d, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x6c, 0x0a, - 0x17, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x6f, - 0x73, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, - 0x63, 0x61, 0x6c, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x48, 0x00, 0x52, 0x15, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, - 0x6c, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x63, - 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x5a, 0x0a, 0x16, 0x4e, 0x75, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, - 0x74, 0x69, 0x63, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0b, 0x63, 0x6f, 0x72, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x76, 0x61, 0x72, 0x69, - 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0a, 0x63, 0x6f, 0x76, 0x61, - 0x72, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x58, 0x0a, 0x1a, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x69, 0x63, 0x61, 0x6c, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, - 0x74, 0x69, 0x63, 0x73, 0x12, 0x3a, 0x0a, 0x04, 0x6c, 0x69, 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4c, 0x69, 0x66, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x04, 0x6c, 0x69, 0x66, 0x74, - 0x22, 0xab, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, - 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x0b, 0x6c, 0x69, 0x66, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x4c, 0x69, 0x66, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x0a, 0x6c, 0x69, - 0x66, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x54, 0x0a, 0x14, 0x77, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x66, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x4c, 0x69, 0x66, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x12, 0x77, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x65, 0x64, 0x4c, 0x69, 0x66, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0xab, - 0x05, 0x0a, 0x0a, 0x4c, 0x69, 0x66, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x15, 0x0a, - 0x05, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x04, - 0x79, 0x49, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x08, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x79, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x12, 0x46, 0x0a, 0x08, 0x79, 0x5f, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4c, 0x69, 0x66, - 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x48, 0x00, - 0x52, 0x07, 0x79, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x79, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x06, 0x79, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x5f, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x48, 0x01, - 0x52, 0x0e, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x59, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x4d, 0x0a, 0x0b, 0x6c, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4c, - 0x69, 0x66, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x66, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x6c, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, - 0x44, 0x0a, 0x06, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x77, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6c, 0x6f, - 0x77, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x68, 0x69, 0x67, 0x68, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xa8, 0x02, 0x0a, 0x09, 0x4c, 0x69, 0x66, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x15, 0x0a, 0x05, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x05, 0x48, 0x00, 0x52, 0x04, 0x78, 0x49, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x08, 0x78, 0x5f, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, - 0x78, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x66, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04, 0x6c, 0x69, 0x66, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x78, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x06, - 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x65, 0x64, 0x5f, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, - 0x48, 0x01, 0x52, 0x0e, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x58, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x78, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x79, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x48, 0x02, 0x52, 0x0a, 0x78, 0x41, 0x6e, - 0x64, 0x59, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x65, 0x64, 0x5f, 0x78, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x48, 0x02, 0x52, 0x12, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x65, 0x64, 0x58, 0x41, 0x6e, 0x64, 0x59, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x09, 0x0a, - 0x07, 0x78, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x78, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x15, 0x0a, 0x13, 0x78, 0x5f, 0x61, - 0x6e, 0x64, 0x5f, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x42, 0x09, 0x0a, 0x07, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x79, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xfd, 0x04, 0x0a, - 0x15, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x14, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, - 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x48, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, - 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x48, 0x01, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x48, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, - 0x73, 0x12, 0x4a, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x48, - 0x01, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x4d, 0x0a, - 0x0c, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x48, 0x01, 0x52, - 0x0b, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x0c, - 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x43, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x63, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x3d, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x07, 0x0a, 0x03, 0x49, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, - 0x41, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x02, - 0x12, 0x09, 0x0a, 0x05, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x53, - 0x54, 0x52, 0x55, 0x43, 0x54, 0x10, 0x04, 0x42, 0x0a, 0x0a, 0x08, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x5f, 0x69, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0xaf, 0x01, 0x0a, - 0x18, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, - 0x5f, 0x6e, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x01, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x4e, 0x6f, 0x6e, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, - 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x4d, 0x69, 0x73, 0x73, 0x69, - 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x76, 0x67, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61, 0x76, 0x67, 0x4e, - 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x5f, - 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, - 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x4e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xe7, - 0x01, 0x0a, 0x0f, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, - 0x69, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x03, 0x6e, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x03, 0x73, 0x74, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12, 0x41, - 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, - 0x67, 0x72, 0x61, 0x6d, 0x48, 0x00, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, - 0x6d, 0x12, 0x4e, 0x0a, 0x0e, 0x72, 0x61, 0x6e, 0x6b, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, - 0x48, 0x00, 0x52, 0x0d, 0x72, 0x61, 0x6e, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, - 0x6d, 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x92, 0x03, 0x0a, 0x11, 0x4e, 0x75, 0x6d, - 0x65, 0x72, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x4b, - 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x0b, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6d, - 0x65, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04, 0x6d, 0x65, 0x61, 0x6e, 0x12, - 0x17, 0x0a, 0x07, 0x73, 0x74, 0x64, 0x5f, 0x64, 0x65, 0x76, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, - 0x52, 0x06, 0x73, 0x74, 0x64, 0x44, 0x65, 0x76, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, - 0x7a, 0x65, 0x72, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6e, 0x75, 0x6d, - 0x5a, 0x65, 0x72, 0x6f, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x01, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x64, 0x69, 0x61, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x12, - 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x61, - 0x78, 0x12, 0x41, 0x0a, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x18, - 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x73, 0x12, 0x67, 0x0a, 0x16, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x5f, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x57, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x53, 0x74, 0x61, - 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x14, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, - 0x64, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x93, 0x04, - 0x0a, 0x10, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x12, 0x4b, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, - 0x16, 0x0a, 0x06, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x12, 0x54, 0x0a, 0x0a, 0x74, 0x6f, 0x70, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x74, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x69, - 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0x46, 0x72, 0x65, 0x71, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x09, 0x74, 0x6f, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x1d, 0x0a, - 0x0a, 0x61, 0x76, 0x67, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x02, 0x52, 0x09, 0x61, 0x76, 0x67, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x4c, 0x0a, 0x0e, - 0x72, 0x61, 0x6e, 0x6b, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x61, - 0x6e, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x0d, 0x72, 0x61, 0x6e, - 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x64, 0x0a, 0x15, 0x77, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x13, 0x77, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x6f, 0x63, 0x61, 0x62, 0x75, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x66, - 0x69, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x76, 0x6f, 0x63, 0x61, 0x62, - 0x75, 0x6c, 0x61, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x1a, 0x48, 0x0a, 0x0c, 0x46, 0x72, 0x65, - 0x71, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x1c, 0x0a, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x01, 0x52, 0x09, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x04, 0x08, - 0x01, 0x10, 0x02, 0x22, 0xa3, 0x01, 0x0a, 0x19, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, - 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x04, 0x6d, 0x65, 0x61, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x74, 0x64, 0x5f, 0x64, 0x65, 0x76, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x73, 0x74, 0x64, 0x44, 0x65, 0x76, 0x12, 0x16, - 0x0a, 0x06, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, - 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x0a, 0x68, - 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x18, 0x57, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, - 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x54, 0x0a, 0x0a, 0x74, 0x6f, 0x70, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, - 0x74, 0x69, 0x63, 0x73, 0x2e, 0x46, 0x72, 0x65, 0x71, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x09, 0x74, 0x6f, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x0e, - 0x72, 0x61, 0x6e, 0x6b, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x61, - 0x6e, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x0d, 0x72, 0x61, 0x6e, - 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x22, 0xe2, 0x01, 0x0a, 0x0f, 0x42, - 0x79, 0x74, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x4b, - 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x0b, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x75, - 0x6e, 0x69, 0x71, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x6e, 0x69, - 0x71, 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x76, 0x67, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0b, 0x61, 0x76, 0x67, 0x4e, - 0x75, 0x6d, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x5f, 0x6e, - 0x75, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0b, - 0x6d, 0x69, 0x6e, 0x4e, 0x75, 0x6d, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x6d, - 0x61, 0x78, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x02, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x4e, 0x75, 0x6d, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, - 0x5f, 0x0a, 0x10, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, - 0x69, 0x63, 0x73, 0x12, 0x4b, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x76, 0x30, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, - 0x69, 0x63, 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x22, 0x94, 0x04, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, - 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x5f, 0x6e, 0x6f, 0x6e, - 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, - 0x6e, 0x75, 0x6d, 0x4e, 0x6f, 0x6e, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, - 0x0b, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x24, - 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x4e, 0x75, 0x6d, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x61, - 0x78, 0x4e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x76, - 0x67, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x02, 0x52, 0x0c, 0x61, 0x76, 0x67, 0x4e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x4e, 0x75, 0x6d, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x53, 0x0a, 0x14, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x48, 0x69, - 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x12, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x64, 0x0a, 0x15, 0x77, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x65, 0x6e, - 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x76, 0x30, 0x2e, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x13, 0x77, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x73, 0x12, 0x64, 0x0a, 0x1d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6c, 0x69, 0x73, - 0x74, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, - 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, - 0x30, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x1a, 0x66, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x48, 0x69, - 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x22, 0x83, 0x03, 0x0a, 0x09, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x75, 0x6d, 0x5f, 0x6e, 0x61, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x4e, 0x61, 0x6e, 0x12, 0x23, - 0x0a, 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x65, 0x64, 0x12, 0x42, 0x0a, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x48, 0x69, - 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, - 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x1a, 0x6d, 0x0a, 0x06, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, - 0x77, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6c, - 0x6f, 0x77, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x68, 0x69, 0x67, - 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x73, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, - 0x2c, 0x0a, 0x0d, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x4e, 0x44, 0x41, 0x52, 0x44, 0x10, 0x00, 0x12, 0x0d, - 0x0a, 0x09, 0x51, 0x55, 0x41, 0x4e, 0x54, 0x49, 0x4c, 0x45, 0x53, 0x10, 0x01, 0x22, 0xec, 0x01, - 0x0a, 0x0d, 0x52, 0x61, 0x6e, 0x6b, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, - 0x46, 0x0a, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x48, 0x69, - 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, - 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x7f, 0x0a, 0x06, 0x42, - 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x61, 0x6e, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6c, 0x6f, 0x77, 0x52, 0x61, 0x6e, 0x6b, - 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, 0x69, 0x67, 0x68, 0x52, 0x61, 0x6e, 0x6b, 0x12, 0x14, 0x0a, - 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x42, 0x68, 0x0a, 0x1a, - 0x6f, 0x72, 0x67, 0x2e, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x30, 0x50, 0x01, 0x5a, 0x45, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2d, 0x64, - 0x65, 0x76, 0x2f, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x67, 0x6f, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x66, 0x6c, 0x6f, - 0x77, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x76, 0x30, 0xf8, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_tensorflow_metadata_proto_v0_statistics_proto_rawDescOnce sync.Once - file_tensorflow_metadata_proto_v0_statistics_proto_rawDescData = file_tensorflow_metadata_proto_v0_statistics_proto_rawDesc -) - -func file_tensorflow_metadata_proto_v0_statistics_proto_rawDescGZIP() []byte { - file_tensorflow_metadata_proto_v0_statistics_proto_rawDescOnce.Do(func() { - file_tensorflow_metadata_proto_v0_statistics_proto_rawDescData = protoimpl.X.CompressGZIP(file_tensorflow_metadata_proto_v0_statistics_proto_rawDescData) - }) - return file_tensorflow_metadata_proto_v0_statistics_proto_rawDescData -} - -var file_tensorflow_metadata_proto_v0_statistics_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes = make([]protoimpl.MessageInfo, 24) -var file_tensorflow_metadata_proto_v0_statistics_proto_goTypes = []interface{}{ - (FeatureNameStatistics_Type)(0), // 0: tensorflow.metadata.v0.FeatureNameStatistics.Type - (Histogram_HistogramType)(0), // 1: tensorflow.metadata.v0.Histogram.HistogramType - (*DatasetFeatureStatisticsList)(nil), // 2: tensorflow.metadata.v0.DatasetFeatureStatisticsList - (*DatasetFeatureStatistics)(nil), // 3: tensorflow.metadata.v0.DatasetFeatureStatistics - (*CrossFeatureStatistics)(nil), // 4: tensorflow.metadata.v0.CrossFeatureStatistics - (*NumericCrossStatistics)(nil), // 5: tensorflow.metadata.v0.NumericCrossStatistics - (*CategoricalCrossStatistics)(nil), // 6: tensorflow.metadata.v0.CategoricalCrossStatistics - (*LiftStatistics)(nil), // 7: tensorflow.metadata.v0.LiftStatistics - (*LiftSeries)(nil), // 8: tensorflow.metadata.v0.LiftSeries - (*FeatureNameStatistics)(nil), // 9: tensorflow.metadata.v0.FeatureNameStatistics - (*WeightedCommonStatistics)(nil), // 10: tensorflow.metadata.v0.WeightedCommonStatistics - (*CustomStatistic)(nil), // 11: tensorflow.metadata.v0.CustomStatistic - (*NumericStatistics)(nil), // 12: tensorflow.metadata.v0.NumericStatistics - (*StringStatistics)(nil), // 13: tensorflow.metadata.v0.StringStatistics - (*WeightedNumericStatistics)(nil), // 14: tensorflow.metadata.v0.WeightedNumericStatistics - (*WeightedStringStatistics)(nil), // 15: tensorflow.metadata.v0.WeightedStringStatistics - (*BytesStatistics)(nil), // 16: tensorflow.metadata.v0.BytesStatistics - (*StructStatistics)(nil), // 17: tensorflow.metadata.v0.StructStatistics - (*CommonStatistics)(nil), // 18: tensorflow.metadata.v0.CommonStatistics - (*Histogram)(nil), // 19: tensorflow.metadata.v0.Histogram - (*RankHistogram)(nil), // 20: tensorflow.metadata.v0.RankHistogram - (*LiftSeries_Bucket)(nil), // 21: tensorflow.metadata.v0.LiftSeries.Bucket - (*LiftSeries_LiftValue)(nil), // 22: tensorflow.metadata.v0.LiftSeries.LiftValue - (*StringStatistics_FreqAndValue)(nil), // 23: tensorflow.metadata.v0.StringStatistics.FreqAndValue - (*Histogram_Bucket)(nil), // 24: tensorflow.metadata.v0.Histogram.Bucket - (*RankHistogram_Bucket)(nil), // 25: tensorflow.metadata.v0.RankHistogram.Bucket - (*Path)(nil), // 26: tensorflow.metadata.v0.Path -} -var file_tensorflow_metadata_proto_v0_statistics_proto_depIdxs = []int32{ - 3, // 0: tensorflow.metadata.v0.DatasetFeatureStatisticsList.datasets:type_name -> tensorflow.metadata.v0.DatasetFeatureStatistics - 9, // 1: tensorflow.metadata.v0.DatasetFeatureStatistics.features:type_name -> tensorflow.metadata.v0.FeatureNameStatistics - 4, // 2: tensorflow.metadata.v0.DatasetFeatureStatistics.cross_features:type_name -> tensorflow.metadata.v0.CrossFeatureStatistics - 26, // 3: tensorflow.metadata.v0.CrossFeatureStatistics.path_x:type_name -> tensorflow.metadata.v0.Path - 26, // 4: tensorflow.metadata.v0.CrossFeatureStatistics.path_y:type_name -> tensorflow.metadata.v0.Path - 5, // 5: tensorflow.metadata.v0.CrossFeatureStatistics.num_cross_stats:type_name -> tensorflow.metadata.v0.NumericCrossStatistics - 6, // 6: tensorflow.metadata.v0.CrossFeatureStatistics.categorical_cross_stats:type_name -> tensorflow.metadata.v0.CategoricalCrossStatistics - 7, // 7: tensorflow.metadata.v0.CategoricalCrossStatistics.lift:type_name -> tensorflow.metadata.v0.LiftStatistics - 8, // 8: tensorflow.metadata.v0.LiftStatistics.lift_series:type_name -> tensorflow.metadata.v0.LiftSeries - 8, // 9: tensorflow.metadata.v0.LiftStatistics.weighted_lift_series:type_name -> tensorflow.metadata.v0.LiftSeries - 21, // 10: tensorflow.metadata.v0.LiftSeries.y_bucket:type_name -> tensorflow.metadata.v0.LiftSeries.Bucket - 22, // 11: tensorflow.metadata.v0.LiftSeries.lift_values:type_name -> tensorflow.metadata.v0.LiftSeries.LiftValue - 26, // 12: tensorflow.metadata.v0.FeatureNameStatistics.path:type_name -> tensorflow.metadata.v0.Path - 0, // 13: tensorflow.metadata.v0.FeatureNameStatistics.type:type_name -> tensorflow.metadata.v0.FeatureNameStatistics.Type - 12, // 14: tensorflow.metadata.v0.FeatureNameStatistics.num_stats:type_name -> tensorflow.metadata.v0.NumericStatistics - 13, // 15: tensorflow.metadata.v0.FeatureNameStatistics.string_stats:type_name -> tensorflow.metadata.v0.StringStatistics - 16, // 16: tensorflow.metadata.v0.FeatureNameStatistics.bytes_stats:type_name -> tensorflow.metadata.v0.BytesStatistics - 17, // 17: tensorflow.metadata.v0.FeatureNameStatistics.struct_stats:type_name -> tensorflow.metadata.v0.StructStatistics - 11, // 18: tensorflow.metadata.v0.FeatureNameStatistics.custom_stats:type_name -> tensorflow.metadata.v0.CustomStatistic - 19, // 19: tensorflow.metadata.v0.CustomStatistic.histogram:type_name -> tensorflow.metadata.v0.Histogram - 20, // 20: tensorflow.metadata.v0.CustomStatistic.rank_histogram:type_name -> tensorflow.metadata.v0.RankHistogram - 18, // 21: tensorflow.metadata.v0.NumericStatistics.common_stats:type_name -> tensorflow.metadata.v0.CommonStatistics - 19, // 22: tensorflow.metadata.v0.NumericStatistics.histograms:type_name -> tensorflow.metadata.v0.Histogram - 14, // 23: tensorflow.metadata.v0.NumericStatistics.weighted_numeric_stats:type_name -> tensorflow.metadata.v0.WeightedNumericStatistics - 18, // 24: tensorflow.metadata.v0.StringStatistics.common_stats:type_name -> tensorflow.metadata.v0.CommonStatistics - 23, // 25: tensorflow.metadata.v0.StringStatistics.top_values:type_name -> tensorflow.metadata.v0.StringStatistics.FreqAndValue - 20, // 26: tensorflow.metadata.v0.StringStatistics.rank_histogram:type_name -> tensorflow.metadata.v0.RankHistogram - 15, // 27: tensorflow.metadata.v0.StringStatistics.weighted_string_stats:type_name -> tensorflow.metadata.v0.WeightedStringStatistics - 19, // 28: tensorflow.metadata.v0.WeightedNumericStatistics.histograms:type_name -> tensorflow.metadata.v0.Histogram - 23, // 29: tensorflow.metadata.v0.WeightedStringStatistics.top_values:type_name -> tensorflow.metadata.v0.StringStatistics.FreqAndValue - 20, // 30: tensorflow.metadata.v0.WeightedStringStatistics.rank_histogram:type_name -> tensorflow.metadata.v0.RankHistogram - 18, // 31: tensorflow.metadata.v0.BytesStatistics.common_stats:type_name -> tensorflow.metadata.v0.CommonStatistics - 18, // 32: tensorflow.metadata.v0.StructStatistics.common_stats:type_name -> tensorflow.metadata.v0.CommonStatistics - 19, // 33: tensorflow.metadata.v0.CommonStatistics.num_values_histogram:type_name -> tensorflow.metadata.v0.Histogram - 10, // 34: tensorflow.metadata.v0.CommonStatistics.weighted_common_stats:type_name -> tensorflow.metadata.v0.WeightedCommonStatistics - 19, // 35: tensorflow.metadata.v0.CommonStatistics.feature_list_length_histogram:type_name -> tensorflow.metadata.v0.Histogram - 24, // 36: tensorflow.metadata.v0.Histogram.buckets:type_name -> tensorflow.metadata.v0.Histogram.Bucket - 1, // 37: tensorflow.metadata.v0.Histogram.type:type_name -> tensorflow.metadata.v0.Histogram.HistogramType - 25, // 38: tensorflow.metadata.v0.RankHistogram.buckets:type_name -> tensorflow.metadata.v0.RankHistogram.Bucket - 39, // [39:39] is the sub-list for method output_type - 39, // [39:39] is the sub-list for method input_type - 39, // [39:39] is the sub-list for extension type_name - 39, // [39:39] is the sub-list for extension extendee - 0, // [0:39] is the sub-list for field type_name -} - -func init() { file_tensorflow_metadata_proto_v0_statistics_proto_init() } -func file_tensorflow_metadata_proto_v0_statistics_proto_init() { - if File_tensorflow_metadata_proto_v0_statistics_proto != nil { - return - } - file_tensorflow_metadata_proto_v0_path_proto_init() - if !protoimpl.UnsafeEnabled { - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DatasetFeatureStatisticsList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DatasetFeatureStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CrossFeatureStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NumericCrossStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CategoricalCrossStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LiftStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LiftSeries); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureNameStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WeightedCommonStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CustomStatistic); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NumericStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StringStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WeightedNumericStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WeightedStringStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BytesStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StructStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CommonStatistics); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Histogram); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RankHistogram); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LiftSeries_Bucket); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LiftSeries_LiftValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StringStatistics_FreqAndValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Histogram_Bucket); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RankHistogram_Bucket); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*CrossFeatureStatistics_NumCrossStats)(nil), - (*CrossFeatureStatistics_CategoricalCrossStats)(nil), - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[6].OneofWrappers = []interface{}{ - (*LiftSeries_YInt)(nil), - (*LiftSeries_YString)(nil), - (*LiftSeries_YBucket)(nil), - (*LiftSeries_YCount)(nil), - (*LiftSeries_WeightedYCount)(nil), - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[7].OneofWrappers = []interface{}{ - (*FeatureNameStatistics_Name)(nil), - (*FeatureNameStatistics_Path)(nil), - (*FeatureNameStatistics_NumStats)(nil), - (*FeatureNameStatistics_StringStats)(nil), - (*FeatureNameStatistics_BytesStats)(nil), - (*FeatureNameStatistics_StructStats)(nil), - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[9].OneofWrappers = []interface{}{ - (*CustomStatistic_Num)(nil), - (*CustomStatistic_Str)(nil), - (*CustomStatistic_Histogram)(nil), - (*CustomStatistic_RankHistogram)(nil), - } - file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes[20].OneofWrappers = []interface{}{ - (*LiftSeries_LiftValue_XInt)(nil), - (*LiftSeries_LiftValue_XString)(nil), - (*LiftSeries_LiftValue_XCount)(nil), - (*LiftSeries_LiftValue_WeightedXCount)(nil), - (*LiftSeries_LiftValue_XAndYCount)(nil), - (*LiftSeries_LiftValue_WeightedXAndYCount)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_tensorflow_metadata_proto_v0_statistics_proto_rawDesc, - NumEnums: 2, - NumMessages: 24, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_tensorflow_metadata_proto_v0_statistics_proto_goTypes, - DependencyIndexes: file_tensorflow_metadata_proto_v0_statistics_proto_depIdxs, - EnumInfos: file_tensorflow_metadata_proto_v0_statistics_proto_enumTypes, - MessageInfos: file_tensorflow_metadata_proto_v0_statistics_proto_msgTypes, - }.Build() - File_tensorflow_metadata_proto_v0_statistics_proto = out.File - file_tensorflow_metadata_proto_v0_statistics_proto_rawDesc = nil - file_tensorflow_metadata_proto_v0_statistics_proto_goTypes = nil - file_tensorflow_metadata_proto_v0_statistics_proto_depIdxs = nil -} diff --git a/sdk/go/request.go b/sdk/go/request.go deleted file mode 100644 index 94fecea01ba..00000000000 --- a/sdk/go/request.go +++ /dev/null @@ -1,113 +0,0 @@ -package feast - -import ( - "fmt" - "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - "github.com/feast-dev/feast/sdk/go/protos/feast/types" - "strings" -) - -var ( - // ErrInvalidFeatureRef indicates that the user has provided a feature reference - // with the wrong structure or contents - ErrInvalidFeatureRef = "Invalid Feature Reference %s provided, " + - "feature reference must be in the format featureTableName:featureName" -) - -// OnlineFeaturesRequest wrapper on feast.serving.GetOnlineFeaturesRequestV2. -type OnlineFeaturesRequest struct { - // Features is the list of features to obtain from Feast. Each feature can be given as - // the format feature_table:feature, where "feature_table" & "feature" are feature table name - // and feature name respectively. The only required components is feature name. - Features []string - - // Entities is the list of entity rows to retrieve features on. Each row is a map of entity name to entity value. - Entities []Row - - // Project optionally specifies the project override. If specified, uses given project for retrieval. - // Overrides the projects specified in Feature References if also specified. - Project string -} - -// Builds the feast-specified request payload from the wrapper. -func (r OnlineFeaturesRequest) buildRequest() (*serving.GetOnlineFeaturesRequest, error) { - _, err := buildFeatureRefs(r.Features) - if err != nil { - return nil, err - } - if len(r.Entities) == 0 { - return nil, fmt.Errorf("Entities must be provided") - } - - firstRow := r.Entities[0] - columnSize := len(firstRow) - - // build request entity rows from native entities - entityColumns := make(map[string][]*types.Value, columnSize) - for rowIdx, entityRow := range r.Entities { - for name, val := range entityRow { - if _, ok := entityColumns[name]; !ok { - entityColumns[name] = make([]*types.Value, len(r.Entities)) - } - - entityColumns[name][rowIdx] = val - } - } - - entities := make(map[string]*types.RepeatedValue, len(entityColumns)) - for column, values := range entityColumns { - entities[column] = &types.RepeatedValue{ - Val: values, - } - } - - return &serving.GetOnlineFeaturesRequest{ - Kind: &serving.GetOnlineFeaturesRequest_Features{ - Features: &serving.FeatureList{ - Val: r.Features, - }, - }, - Entities: entities, - }, nil -} - -// Creates a slice of FeatureReferences from string representation in -// the format featuretable:feature. -// featureRefStrs - string feature references to parse. -// Returns parsed FeatureReferences. -// Returns an error when the format of the string feature reference is invalid -func buildFeatureRefs(featureRefStrs []string) ([]*serving.FeatureReferenceV2, error) { - var featureRefs []*serving.FeatureReferenceV2 - - for _, featureRefStr := range featureRefStrs { - featureRef, err := parseFeatureRef(featureRefStr) - if err != nil { - return nil, err - } - featureRefs = append(featureRefs, featureRef) - } - return featureRefs, nil -} - -// Parses a string FeatureReference into FeatureReference proto -// featureRefStr - the string feature reference to parse. -// Returns parsed FeatureReference. -// Returns an error when the format of the string feature reference is invalid -func parseFeatureRef(featureRefStr string) (*serving.FeatureReferenceV2, error) { - if len(featureRefStr) == 0 { - return nil, fmt.Errorf(ErrInvalidFeatureRef, featureRefStr) - } - - var featureRef serving.FeatureReferenceV2 - if strings.Contains(featureRefStr, "/") || !strings.Contains(featureRefStr, ":") { - return nil, fmt.Errorf(ErrInvalidFeatureRef, featureRefStr) - } - // parse featuretable if specified - if strings.Contains(featureRefStr, ":") { - refSplit := strings.Split(featureRefStr, ":") - featureRef.FeatureViewName, featureRefStr = refSplit[0], refSplit[1] - } - featureRef.FeatureName = featureRefStr - - return &featureRef, nil -} diff --git a/sdk/go/request_test.go b/sdk/go/request_test.go deleted file mode 100644 index 9122c8ca401..00000000000 --- a/sdk/go/request_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package feast - -import ( - "fmt" - "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - "github.com/feast-dev/feast/sdk/go/protos/feast/types" - json "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" - "testing" -) - -func TestGetOnlineFeaturesRequest(t *testing.T) { - tt := []struct { - name string - req OnlineFeaturesRequest - want *serving.GetOnlineFeaturesRequest - wantErr bool - err error - }{ - { - name: "valid", - req: OnlineFeaturesRequest{ - Features: []string{ - "driver:driver_id", - }, - Entities: []Row{ - {"entity1": Int64Val(1), "entity2": StrVal("bob")}, - {"entity1": Int64Val(1), "entity2": StrVal("annie")}, - {"entity1": Int64Val(1), "entity2": StrVal("jane")}, - }, - Project: "driver_project", - }, - want: &serving.GetOnlineFeaturesRequest{ - Kind: &serving.GetOnlineFeaturesRequest_Features{ - Features: &serving.FeatureList{ - Val: []string{"driver:driver_id"}, - }, - }, - Entities: map[string]*types.RepeatedValue{ - "entity1": { - Val: []*types.Value{ - Int64Val(1), Int64Val(1), Int64Val(1), - }, - }, - "entity2": { - Val: []*types.Value{ - StrVal("bob"), StrVal("annie"), StrVal("jane"), - }, - }, - }, - }, - wantErr: false, - err: nil, - }, - { - name: "invalid_feature_name/wrong_format", - req: OnlineFeaturesRequest{ - Features: []string{"/fs1:feature1"}, - Entities: []Row{}, - Project: "my_project", - }, - wantErr: true, - err: fmt.Errorf(ErrInvalidFeatureRef, "/fs1:feature1"), - }, - { - name: "invalid_feature_name", - req: OnlineFeaturesRequest{ - Features: []string{"feature1"}, - Entities: []Row{}, - Project: "my_project", - }, - wantErr: true, - err: fmt.Errorf(ErrInvalidFeatureRef, "feature1"), - }, - } - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - got, err := tc.req.buildRequest() - - if (err != nil) != tc.wantErr { - t.Errorf("error = %v, wantErr %v", err, tc.wantErr) - return - } - - if tc.wantErr && err.Error() != tc.err.Error() { - t.Errorf("error = %v, expected err = %v", err, tc.err) - return - } - - if !proto.Equal(got, tc.want) { - m := json.Marshaler{} - gotJSON, _ := m.MarshalToString(got) - wantJSON, _ := m.MarshalToString(tc.want) - t.Errorf("got: \n%v\nwant:\n%v", gotJSON, wantJSON) - } - }) - } -} diff --git a/sdk/go/response.go b/sdk/go/response.go deleted file mode 100644 index cdb2cbee382..00000000000 --- a/sdk/go/response.go +++ /dev/null @@ -1,149 +0,0 @@ -package feast - -import ( - "fmt" - "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - "github.com/feast-dev/feast/sdk/go/protos/feast/types" -) - -var ( - // ErrLengthMismatch indicates that the number of values returned is not the same as the number of values requested - ErrLengthMismatch = "Length mismatch; number of na values (%d) not equal to number of features requested (%d)." - - // ErrFeatureNotFound indicates that the a requested feature was not found in the response - ErrFeatureNotFound = "Feature %s not found in response." - - // ErrTypeMismatch indicates that the there was a type mismatch in the returned values - ErrTypeMismatch = "Requested output of type %s does not match type of feature value returned." -) - -// OnlineFeaturesResponse is a wrapper around serving.GetOnlineFeaturesResponse. -type OnlineFeaturesResponse struct { - RawResponse *serving.GetOnlineFeaturesResponse -} - -// Rows retrieves the result of the request as a list of Rows. -func (r OnlineFeaturesResponse) Rows() []Row { - if len(r.RawResponse.Results) == 0 { - return []Row{} - } - - rowsCount := len(r.RawResponse.Results[0].Values) - rows := make([]Row, rowsCount) - for rowIdx := 0; rowIdx < rowsCount; rowIdx++ { - row := make(map[string]*types.Value) - for featureIdx := 0; featureIdx < len(r.RawResponse.Results); featureIdx++ { - row[r.RawResponse.Metadata.FeatureNames.Val[featureIdx]] = r.RawResponse.Results[featureIdx].Values[rowIdx] - } - - rows[rowIdx] = row - } - return rows -} - -// Statuses retrieves field level status metadata for each row in Rows(). -// Each status map returned maps status 1:1 to each returned row from Rows() -func (r OnlineFeaturesResponse) Statuses() []map[string]serving.FieldStatus { - if len(r.RawResponse.Results) == 0 { - return []map[string]serving.FieldStatus{} - } - - rowsCount := len(r.RawResponse.Results[0].Statuses) - rows := make([]map[string]serving.FieldStatus, rowsCount) - - for rowIdx := 0; rowIdx < rowsCount; rowIdx++ { - row := make(map[string]serving.FieldStatus) - for featureIdx := 0; featureIdx < len(r.RawResponse.Results); featureIdx++ { - row[r.RawResponse.Metadata.FeatureNames.Val[featureIdx]] = r.RawResponse.Results[featureIdx].Statuses[rowIdx] - } - - rows[rowIdx] = row - } - return rows -} - -// Int64Arrays retrieves the result of the request as a list of int64 slices. Any missing values will be filled -// with the missing values provided. -func (r OnlineFeaturesResponse) Int64Arrays(order []string, fillNa []int64) ([][]int64, error) { - if len(fillNa) != len(order) { - return nil, fmt.Errorf(ErrLengthMismatch, len(fillNa), len(order)) - } - - if len(r.RawResponse.Results) == 0 { - return [][]int64{}, nil - } - - rowsCount := len(r.RawResponse.Results[0].Values) - rows := make([][]int64, rowsCount) - - featureNameToIdx := make(map[string]int) - - for idx, featureName := range r.RawResponse.Metadata.FeatureNames.Val { - featureNameToIdx[featureName] = idx - } - - for rowIdx := 0; rowIdx < rowsCount; rowIdx++ { - row := make([]int64, len(order)) - for idx, feature := range order { - featureIdx, exists := featureNameToIdx[feature] - if !exists { - return nil, fmt.Errorf(ErrFeatureNotFound, feature) - } - - valType := r.RawResponse.Results[featureIdx].Values[rowIdx].GetVal() - if valType == nil { - row[idx] = fillNa[idx] - } else if int64Val, ok := valType.(*types.Value_Int64Val); ok { - row[idx] = int64Val.Int64Val - } else { - return nil, fmt.Errorf(ErrTypeMismatch, "int64") - } - } - - rows[rowIdx] = row - } - return rows, nil -} - -// Float64Arrays retrieves the result of the request as a list of float64 slices. Any missing values will be filled -// with the missing values provided. -func (r OnlineFeaturesResponse) Float64Arrays(order []string, fillNa []float64) ([][]float64, error) { - if len(fillNa) != len(order) { - return nil, fmt.Errorf(ErrLengthMismatch, len(fillNa), len(order)) - } - - if len(r.RawResponse.Results) == 0 { - return [][]float64{}, nil - } - - rowsCount := len(r.RawResponse.Results[0].Values) - rows := make([][]float64, rowsCount) - - featureNameToIdx := make(map[string]int) - - for idx, featureName := range r.RawResponse.Metadata.FeatureNames.Val { - featureNameToIdx[featureName] = idx - } - - for rowIdx := 0; rowIdx < rowsCount; rowIdx++ { - row := make([]float64, len(order)) - for idx, feature := range order { - featureIdx, exists := featureNameToIdx[feature] - if !exists { - return nil, fmt.Errorf(ErrFeatureNotFound, feature) - } - - valType := r.RawResponse.Results[featureIdx].Values[rowIdx].GetVal() - if valType == nil { - row[idx] = fillNa[idx] - } else if doubleVal, ok := valType.(*types.Value_DoubleVal); ok { - row[idx] = doubleVal.DoubleVal - } else { - return nil, fmt.Errorf(ErrTypeMismatch, "float64") - } - } - - rows[rowIdx] = row - } - return rows, nil -} diff --git a/sdk/go/response_test.go b/sdk/go/response_test.go deleted file mode 100644 index 693faae7e46..00000000000 --- a/sdk/go/response_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package feast - -import ( - "fmt" - "github.com/feast-dev/feast/sdk/go/protos/feast/serving" - "github.com/feast-dev/feast/sdk/go/protos/feast/types" - "github.com/google/go-cmp/cmp" - "testing" -) - -var response = OnlineFeaturesResponse{ - RawResponse: &serving.GetOnlineFeaturesResponse{ - Results: []*serving.GetOnlineFeaturesResponse_FeatureVector{ - { - Values: []*types.Value{Int64Val(1), Int64Val(2)}, - Statuses: []serving.FieldStatus{ - serving.FieldStatus_PRESENT, - serving.FieldStatus_PRESENT, - }, - }, - { - Values: []*types.Value{{}, Int64Val(2)}, - Statuses: []serving.FieldStatus{ - serving.FieldStatus_NULL_VALUE, - serving.FieldStatus_PRESENT, - }, - }, - }, - Metadata: &serving.GetOnlineFeaturesResponseMetadata{ - FeatureNames: &serving.FeatureList{ - Val: []string{"featuretable1:feature1", "featuretable1:feature2"}, - }, - }, - }, -} - -func TestOnlineFeaturesResponseToRow(t *testing.T) { - actual := response.Rows() - expected := []Row{ - {"featuretable1:feature1": Int64Val(1), "featuretable1:feature2": &types.Value{}}, - {"featuretable1:feature1": Int64Val(2), "featuretable1:feature2": Int64Val(2)}, - } - if len(expected) != len(actual) { - t.Errorf("expected: %v, got: %v", expected, actual) - } - for i := range expected { - if !expected[i].equalTo(actual[i]) { - t.Errorf("expected: %v, got: %v", expected, actual) - } - } -} - -func TestOnlineFeaturesResponseoToStatuses(t *testing.T) { - actual := response.Statuses() - expected := []map[string]serving.FieldStatus{ - { - "featuretable1:feature1": serving.FieldStatus_PRESENT, - "featuretable1:feature2": serving.FieldStatus_NULL_VALUE, - }, - { - "featuretable1:feature1": serving.FieldStatus_PRESENT, - "featuretable1:feature2": serving.FieldStatus_PRESENT, - }, - } - if len(expected) != len(actual) { - t.Errorf("expected: %v, got: %v", expected, actual) - } - for i := range expected { - if !cmp.Equal(expected[i], actual[i]) { - t.Errorf("expected: %v, got: %v", expected, actual) - } - } -} - -func TestOnlineFeaturesResponseToInt64Array(t *testing.T) { - type args struct { - order []string - fillNa []int64 - } - tt := []struct { - name string - args args - want [][]int64 - wantErr bool - err error - }{ - { - name: "valid", - args: args{ - order: []string{"featuretable1:feature2", "featuretable1:feature1"}, - fillNa: []int64{-1, -1}, - }, - want: [][]int64{{-1, 1}, {2, 2}}, - wantErr: false, - }, - { - name: "length mismatch", - args: args{ - order: []string{"ft:feature2", "ft:feature1"}, - fillNa: []int64{-1}, - }, - want: nil, - wantErr: true, - err: fmt.Errorf(ErrLengthMismatch, 1, 2), - }, - { - name: "length mismatch", - args: args{ - order: []string{"featuretable1:feature2", "featuretable1:feature3"}, - fillNa: []int64{-1, -1}, - }, - want: nil, - wantErr: true, - err: fmt.Errorf(ErrFeatureNotFound, "featuretable1:feature3"), - }, - } - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - got, err := response.Int64Arrays(tc.args.order, tc.args.fillNa) - if (err != nil) != tc.wantErr { - t.Errorf("error = %v, wantErr %v", err, tc.wantErr) - return - } - if tc.wantErr && err.Error() != tc.err.Error() { - t.Errorf("error = %v, expected err = %v", err, tc.err) - return - } - if !cmp.Equal(got, tc.want) { - t.Errorf("got: \n%v\nwant:\n%v", got, tc.want) - } - }) - } -} diff --git a/sdk/go/types.go b/sdk/go/types.go deleted file mode 100644 index 600af0b658a..00000000000 --- a/sdk/go/types.go +++ /dev/null @@ -1,57 +0,0 @@ -package feast - -import ( - "github.com/feast-dev/feast/sdk/go/protos/feast/types" - "github.com/golang/protobuf/proto" -) - -// Row is a map of fields -type Row map[string]*types.Value - -func (r Row) equalTo(other Row) bool { - for k, v := range r { - if otherV, ok := other[k]; !ok { - return false - } else { - if !proto.Equal(v, otherV) { - return false - } - } - } - return true -} - -// StrVal is a string type feast value -func StrVal(val string) *types.Value { - return &types.Value{Val: &types.Value_StringVal{StringVal: val}} -} - -// Int32Val is a int32 type feast value -func Int32Val(val int32) *types.Value { - return &types.Value{Val: &types.Value_Int32Val{Int32Val: val}} -} - -// Int64Val is a int64 type feast value -func Int64Val(val int64) *types.Value { - return &types.Value{Val: &types.Value_Int64Val{Int64Val: val}} -} - -// FloatVal is a float32 type feast value -func FloatVal(val float32) *types.Value { - return &types.Value{Val: &types.Value_FloatVal{FloatVal: val}} -} - -// DoubleVal is a float64 type feast value -func DoubleVal(val float64) *types.Value { - return &types.Value{Val: &types.Value_DoubleVal{DoubleVal: val}} -} - -// BoolVal is a bool type feast value -func BoolVal(val bool) *types.Value { - return &types.Value{Val: &types.Value_BoolVal{BoolVal: val}} -} - -// BytesVal is a bytes type feast value -func BytesVal(val []byte) *types.Value { - return &types.Value{Val: &types.Value_BytesVal{BytesVal: val}} -} diff --git a/sdk/python/MANIFEST.in b/sdk/python/MANIFEST.in index 2852924ea94..0eeaa181b23 100644 --- a/sdk/python/MANIFEST.in +++ b/sdk/python/MANIFEST.in @@ -1 +1,4 @@ -recursive-include feast/protos/ *.py \ No newline at end of file +recursive-include feast/protos/ *.py +recursive-include feast py.typed *.pyi + +recursive-include feast/embedded_go/lib/ *.py *.so diff --git a/sdk/python/docs/index.rst b/sdk/python/docs/index.rst index 602c384cc57..52783b40e3d 100644 --- a/sdk/python/docs/index.rst +++ b/sdk/python/docs/index.rst @@ -1,5 +1,5 @@ Feast Python API Documentation -============================= +============================== Feature Store @@ -38,6 +38,28 @@ Redshift Source :members: :exclude-members: RedshiftOptions +Snowflake Source +------------------ + +.. automodule:: feast.infra.offline_stores.snowflake_source + :members: + :exclude-members: SnowflakeOptions + +Spark Source +------------------ + +.. automodule:: feast.infra.offline_stores.contrib.spark_offline_store.spark_source + :members: + :exclude-members: SparkOptions + +Trino Source +------------------ + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino_source + :members: + :exclude-members: TrinoOptions + + File Source ------------------ @@ -59,7 +81,7 @@ Feature View :members: On Demand Feature View -================== +====================== .. automodule:: feast.on_demand_feature_view :members: @@ -85,6 +107,15 @@ Registry :inherited-members: :members: +Registry Store +================== + +.. automodule:: feast.registry_store + :inherited-members: + :members: + :exclude-members: NoopRegistryStore + + Provider ================== @@ -93,7 +124,7 @@ Provider :members: Passthrough Provider ------------------- +-------------------- .. automodule:: feast.infra.passthrough_provider :members: @@ -132,17 +163,36 @@ File Offline Store :members: BigQuery Offline Store ------------------- +---------------------- .. automodule:: feast.infra.offline_stores.bigquery :members: Redshift Offline Store ------------------- +---------------------- .. automodule:: feast.infra.offline_stores.redshift :members: +Snowflake Offline Store +----------------------- + +.. automodule:: feast.infra.offline_stores.snowflake + :members: + +Spark Offline Store +------------------- + +.. automodule:: feast.infra.offline_stores.contrib.spark_offline_store.spark + :members: + +Trino Offline Store +------------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino + :members: + + Online Store ================== @@ -151,19 +201,19 @@ Online Store :members: Sqlite Online Store ------------------- +------------------- .. automodule:: feast.infra.online_stores.sqlite :members: Datastore Online Store ------------------- +---------------------- .. automodule:: feast.infra.online_stores.datastore :members: DynamoDB Online Store ------------------- +--------------------- .. automodule:: feast.infra.online_stores.dynamodb :members: @@ -172,4 +222,5 @@ Redis Online Store ------------------ .. automodule:: feast.infra.online_stores.redis - :members: \ No newline at end of file + :members: + :noindex: \ No newline at end of file diff --git a/sdk/python/docs/source/feast.diff.rst b/sdk/python/docs/source/feast.diff.rst new file mode 100644 index 00000000000..e4142171711 --- /dev/null +++ b/sdk/python/docs/source/feast.diff.rst @@ -0,0 +1,37 @@ +feast.diff package +================== + +Submodules +---------- + +feast.diff.infra\_diff module +----------------------------- + +.. automodule:: feast.diff.infra_diff + :members: + :undoc-members: + :show-inheritance: + +feast.diff.property\_diff module +-------------------------------- + +.. automodule:: feast.diff.property_diff + :members: + :undoc-members: + :show-inheritance: + +feast.diff.registry\_diff module +-------------------------------- + +.. automodule:: feast.diff.registry_diff + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.diff + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.dqm.profilers.rst b/sdk/python/docs/source/feast.dqm.profilers.rst new file mode 100644 index 00000000000..24f452ada8f --- /dev/null +++ b/sdk/python/docs/source/feast.dqm.profilers.rst @@ -0,0 +1,29 @@ +feast.dqm.profilers package +=========================== + +Submodules +---------- + +feast.dqm.profilers.ge\_profiler module +--------------------------------------- + +.. automodule:: feast.dqm.profilers.ge_profiler + :members: + :undoc-members: + :show-inheritance: + +feast.dqm.profilers.profiler module +----------------------------------- + +.. automodule:: feast.dqm.profilers.profiler + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.dqm.profilers + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.dqm.rst b/sdk/python/docs/source/feast.dqm.rst new file mode 100644 index 00000000000..0c1b82f0fa2 --- /dev/null +++ b/sdk/python/docs/source/feast.dqm.rst @@ -0,0 +1,29 @@ +feast.dqm package +================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + feast.dqm.profilers + +Submodules +---------- + +feast.dqm.errors module +----------------------- + +.. automodule:: feast.dqm.errors + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.dqm + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.offline_stores.contrib.rst b/sdk/python/docs/source/feast.infra.offline_stores.contrib.rst new file mode 100644 index 00000000000..4fabad68446 --- /dev/null +++ b/sdk/python/docs/source/feast.infra.offline_stores.contrib.rst @@ -0,0 +1,30 @@ +feast.infra.offline\_stores.contrib package +=========================================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + feast.infra.offline_stores.contrib.spark_offline_store + feast.infra.offline_stores.contrib.trino_offline_store + +Submodules +---------- + +feast.infra.offline\_stores.contrib.contrib\_repo\_configuration module +----------------------------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.contrib.contrib_repo_configuration + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.offline_stores.contrib + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.offline_stores.contrib.spark_offline_store.rst b/sdk/python/docs/source/feast.infra.offline_stores.contrib.spark_offline_store.rst new file mode 100644 index 00000000000..d91389faabf --- /dev/null +++ b/sdk/python/docs/source/feast.infra.offline_stores.contrib.spark_offline_store.rst @@ -0,0 +1,29 @@ +feast.infra.offline\_stores.contrib.spark\_offline\_store package +================================================================= + +Submodules +---------- + +feast.infra.offline\_stores.contrib.spark\_offline\_store.spark module +---------------------------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.contrib.spark_offline_store.spark + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.contrib.spark\_offline\_store.spark\_source module +------------------------------------------------------------------------------ + +.. automodule:: feast.infra.offline_stores.contrib.spark_offline_store.spark_source + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.offline_stores.contrib.spark_offline_store + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.connectors.rst b/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.connectors.rst new file mode 100644 index 00000000000..a0ee8dceabf --- /dev/null +++ b/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.connectors.rst @@ -0,0 +1,21 @@ +feast.infra.offline\_stores.contrib.trino\_offline\_store.connectors package +============================================================================ + +Submodules +---------- + +feast.infra.offline\_stores.contrib.trino\_offline\_store.connectors.upload module +---------------------------------------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.connectors.upload + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.connectors + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.rst b/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.rst new file mode 100644 index 00000000000..0fe9cdc4610 --- /dev/null +++ b/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.rst @@ -0,0 +1,54 @@ +feast.infra.offline\_stores.contrib.trino\_offline\_store package +================================================================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + feast.infra.offline_stores.contrib.trino_offline_store.connectors + feast.infra.offline_stores.contrib.trino_offline_store.test_config + +Submodules +---------- + +feast.infra.offline\_stores.contrib.trino\_offline\_store.trino module +---------------------------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.contrib.trino\_offline\_store.trino\_queries module +------------------------------------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino_queries + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.contrib.trino\_offline\_store.trino\_source module +------------------------------------------------------------------------------ + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino_source + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.contrib.trino\_offline\_store.trino\_type\_map module +--------------------------------------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino_type_map + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.test_config.rst b/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.test_config.rst new file mode 100644 index 00000000000..ef43a191d0a --- /dev/null +++ b/sdk/python/docs/source/feast.infra.offline_stores.contrib.trino_offline_store.test_config.rst @@ -0,0 +1,21 @@ +feast.infra.offline\_stores.contrib.trino\_offline\_store.test\_config package +============================================================================== + +Submodules +---------- + +feast.infra.offline\_stores.contrib.trino\_offline\_store.test\_config.manual\_tests module +------------------------------------------------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.test_config.manual_tests + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.test_config + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.offline_stores.rst b/sdk/python/docs/source/feast.infra.offline_stores.rst index a40c8b115ee..7949c9efb32 100644 --- a/sdk/python/docs/source/feast.infra.offline_stores.rst +++ b/sdk/python/docs/source/feast.infra.offline_stores.rst @@ -1,6 +1,14 @@ feast.infra.offline\_stores package =================================== +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + feast.infra.offline_stores.contrib + Submodules ---------- @@ -12,6 +20,14 @@ feast.infra.offline\_stores.bigquery module :undoc-members: :show-inheritance: +feast.infra.offline\_stores.bigquery\_source module +--------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.bigquery_source + :members: + :undoc-members: + :show-inheritance: + feast.infra.offline\_stores.file module --------------------------------------- @@ -20,10 +36,10 @@ feast.infra.offline\_stores.file module :undoc-members: :show-inheritance: -feast.infra.offline\_stores.helpers module ------------------------------------------- +feast.infra.offline\_stores.file\_source module +----------------------------------------------- -.. automodule:: feast.infra.offline_stores.helpers +.. automodule:: feast.infra.offline_stores.file_source :members: :undoc-members: :show-inheritance: @@ -36,6 +52,46 @@ feast.infra.offline\_stores.offline\_store module :undoc-members: :show-inheritance: +feast.infra.offline\_stores.offline\_utils module +------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.offline_utils + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.redshift module +------------------------------------------- + +.. automodule:: feast.infra.offline_stores.redshift + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.redshift\_source module +--------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.redshift_source + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.snowflake module +-------------------------------------------- + +.. automodule:: feast.infra.offline_stores.snowflake + :members: + :undoc-members: + :show-inheritance: + +feast.infra.offline\_stores.snowflake\_source module +---------------------------------------------------- + +.. automodule:: feast.infra.offline_stores.snowflake_source + :members: + :undoc-members: + :show-inheritance: + Module contents --------------- diff --git a/sdk/python/docs/source/feast.infra.online_stores.rst b/sdk/python/docs/source/feast.infra.online_stores.rst new file mode 100644 index 00000000000..5c23796bf8a --- /dev/null +++ b/sdk/python/docs/source/feast.infra.online_stores.rst @@ -0,0 +1,61 @@ +feast.infra.online\_stores package +================================== + +Submodules +---------- + +feast.infra.online\_stores.datastore module +------------------------------------------- + +.. automodule:: feast.infra.online_stores.datastore + :members: + :undoc-members: + :show-inheritance: + +feast.infra.online\_stores.dynamodb module +------------------------------------------ + +.. automodule:: feast.infra.online_stores.dynamodb + :members: + :undoc-members: + :show-inheritance: + +feast.infra.online\_stores.helpers module +----------------------------------------- + +.. automodule:: feast.infra.online_stores.helpers + :members: + :undoc-members: + :show-inheritance: + +feast.infra.online\_stores.online\_store module +----------------------------------------------- + +.. automodule:: feast.infra.online_stores.online_store + :members: + :undoc-members: + :show-inheritance: + +feast.infra.online\_stores.redis module +--------------------------------------- + +.. automodule:: feast.infra.online_stores.redis + :members: + :undoc-members: + :show-inheritance: + +feast.infra.online\_stores.sqlite module +---------------------------------------- + +.. automodule:: feast.infra.online_stores.sqlite + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.online_stores + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.rst b/sdk/python/docs/source/feast.infra.rst index 63dcb737ec2..5473c3927e5 100644 --- a/sdk/python/docs/source/feast.infra.rst +++ b/sdk/python/docs/source/feast.infra.rst @@ -8,10 +8,20 @@ Subpackages :maxdepth: 4 feast.infra.offline_stores + feast.infra.online_stores + feast.infra.utils Submodules ---------- +feast.infra.aws module +---------------------- + +.. automodule:: feast.infra.aws + :members: + :undoc-members: + :show-inheritance: + feast.infra.gcp module ---------------------- @@ -20,6 +30,14 @@ feast.infra.gcp module :undoc-members: :show-inheritance: +feast.infra.infra\_object module +-------------------------------- + +.. automodule:: feast.infra.infra_object + :members: + :undoc-members: + :show-inheritance: + feast.infra.key\_encoding\_utils module --------------------------------------- @@ -36,6 +54,14 @@ feast.infra.local module :undoc-members: :show-inheritance: +feast.infra.passthrough\_provider module +---------------------------------------- + +.. automodule:: feast.infra.passthrough_provider + :members: + :undoc-members: + :show-inheritance: + feast.infra.provider module --------------------------- diff --git a/sdk/python/docs/source/feast.infra.utils.rst b/sdk/python/docs/source/feast.infra.utils.rst new file mode 100644 index 00000000000..9655acc206d --- /dev/null +++ b/sdk/python/docs/source/feast.infra.utils.rst @@ -0,0 +1,29 @@ +feast.infra.utils package +========================= + +Submodules +---------- + +feast.infra.utils.aws\_utils module +----------------------------------- + +.. automodule:: feast.infra.utils.aws_utils + :members: + :undoc-members: + :show-inheritance: + +feast.infra.utils.snowflake\_utils module +----------------------------------------- + +.. automodule:: feast.infra.utils.snowflake_utils + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.loaders.rst b/sdk/python/docs/source/feast.loaders.rst index da3cbc13ad5..d4968a29999 100644 --- a/sdk/python/docs/source/feast.loaders.rst +++ b/sdk/python/docs/source/feast.loaders.rst @@ -4,30 +4,6 @@ feast.loaders package Submodules ---------- -feast.loaders.abstract\_producer module ---------------------------------------- - -.. automodule:: feast.loaders.abstract_producer - :members: - :undoc-members: - :show-inheritance: - -feast.loaders.file module -------------------------- - -.. automodule:: feast.loaders.file - :members: - :undoc-members: - :show-inheritance: - -feast.loaders.ingest module ---------------------------- - -.. automodule:: feast.loaders.ingest - :members: - :undoc-members: - :show-inheritance: - feast.loaders.yaml module ------------------------- diff --git a/sdk/python/docs/source/feast.protos.feast.core.rst b/sdk/python/docs/source/feast.protos.feast.core.rst index ce25dda21f7..f29a51719c1 100644 --- a/sdk/python/docs/source/feast.protos.feast.core.rst +++ b/sdk/python/docs/source/feast.protos.feast.core.rst @@ -4,22 +4,6 @@ feast.protos.feast.core package Submodules ---------- -feast.protos.feast.core.CoreService\_pb2 module ------------------------------------------------ - -.. automodule:: feast.protos.feast.core.CoreService_pb2 - :members: - :undoc-members: - :show-inheritance: - -feast.protos.feast.core.CoreService\_pb2\_grpc module ------------------------------------------------------ - -.. automodule:: feast.protos.feast.core.CoreService_pb2_grpc - :members: - :undoc-members: - :show-inheritance: - feast.protos.feast.core.DataFormat\_pb2 module ---------------------------------------------- @@ -52,6 +36,38 @@ feast.protos.feast.core.DataSource\_pb2\_grpc module :undoc-members: :show-inheritance: +feast.protos.feast.core.DatastoreTable\_pb2 module +-------------------------------------------------- + +.. automodule:: feast.protos.feast.core.DatastoreTable_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.DatastoreTable\_pb2\_grpc module +-------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.DatastoreTable_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.DynamoDBTable\_pb2 module +------------------------------------------------- + +.. automodule:: feast.protos.feast.core.DynamoDBTable_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.DynamoDBTable\_pb2\_grpc module +------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.DynamoDBTable_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + feast.protos.feast.core.Entity\_pb2 module ------------------------------------------ @@ -68,6 +84,22 @@ feast.protos.feast.core.Entity\_pb2\_grpc module :undoc-members: :show-inheritance: +feast.protos.feast.core.FeatureService\_pb2 module +-------------------------------------------------- + +.. automodule:: feast.protos.feast.core.FeatureService_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.FeatureService\_pb2\_grpc module +-------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.FeatureService_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + feast.protos.feast.core.FeatureTable\_pb2 module ------------------------------------------------ @@ -84,6 +116,22 @@ feast.protos.feast.core.FeatureTable\_pb2\_grpc module :undoc-members: :show-inheritance: +feast.protos.feast.core.FeatureViewProjection\_pb2 module +--------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.FeatureViewProjection_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.FeatureViewProjection\_pb2\_grpc module +--------------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.FeatureViewProjection_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + feast.protos.feast.core.FeatureView\_pb2 module ----------------------------------------------- @@ -116,6 +164,38 @@ feast.protos.feast.core.Feature\_pb2\_grpc module :undoc-members: :show-inheritance: +feast.protos.feast.core.InfraObject\_pb2 module +----------------------------------------------- + +.. automodule:: feast.protos.feast.core.InfraObject_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.InfraObject\_pb2\_grpc module +----------------------------------------------------- + +.. automodule:: feast.protos.feast.core.InfraObject_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.OnDemandFeatureView\_pb2 module +------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.OnDemandFeatureView_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.OnDemandFeatureView\_pb2\_grpc module +------------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.OnDemandFeatureView_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + feast.protos.feast.core.Registry\_pb2 module -------------------------------------------- @@ -132,6 +212,54 @@ feast.protos.feast.core.Registry\_pb2\_grpc module :undoc-members: :show-inheritance: +feast.protos.feast.core.RequestFeatureView\_pb2 module +------------------------------------------------------ + +.. automodule:: feast.protos.feast.core.RequestFeatureView_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.RequestFeatureView\_pb2\_grpc module +------------------------------------------------------------ + +.. automodule:: feast.protos.feast.core.RequestFeatureView_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.SavedDataset\_pb2 module +------------------------------------------------ + +.. automodule:: feast.protos.feast.core.SavedDataset_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.SavedDataset\_pb2\_grpc module +------------------------------------------------------ + +.. automodule:: feast.protos.feast.core.SavedDataset_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.SqliteTable\_pb2 module +----------------------------------------------- + +.. automodule:: feast.protos.feast.core.SqliteTable_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.SqliteTable\_pb2\_grpc module +----------------------------------------------------- + +.. automodule:: feast.protos.feast.core.SqliteTable_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + feast.protos.feast.core.Store\_pb2 module ----------------------------------------- @@ -148,6 +276,22 @@ feast.protos.feast.core.Store\_pb2\_grpc module :undoc-members: :show-inheritance: +feast.protos.feast.core.ValidationProfile\_pb2 module +----------------------------------------------------- + +.. automodule:: feast.protos.feast.core.ValidationProfile_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.core.ValidationProfile\_pb2\_grpc module +----------------------------------------------------------- + +.. automodule:: feast.protos.feast.core.ValidationProfile_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + Module contents --------------- diff --git a/sdk/python/docs/source/feast.protos.feast.rst b/sdk/python/docs/source/feast.protos.feast.rst index f519165db8e..456d960d738 100644 --- a/sdk/python/docs/source/feast.protos.feast.rst +++ b/sdk/python/docs/source/feast.protos.feast.rst @@ -10,7 +10,6 @@ Subpackages feast.protos.feast.core feast.protos.feast.serving feast.protos.feast.storage - feast.protos.feast.types Module contents --------------- diff --git a/sdk/python/docs/source/feast.protos.feast.serving.rst b/sdk/python/docs/source/feast.protos.feast.serving.rst index 06ee4e61f4c..792335b189d 100644 --- a/sdk/python/docs/source/feast.protos.feast.serving.rst +++ b/sdk/python/docs/source/feast.protos.feast.serving.rst @@ -4,6 +4,22 @@ feast.protos.feast.serving package Submodules ---------- +feast.protos.feast.serving.Connector\_pb2 module +------------------------------------------------ + +.. automodule:: feast.protos.feast.serving.Connector_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.serving.Connector\_pb2\_grpc module +------------------------------------------------------ + +.. automodule:: feast.protos.feast.serving.Connector_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + feast.protos.feast.serving.ServingService\_pb2 module ----------------------------------------------------- @@ -20,6 +36,22 @@ feast.protos.feast.serving.ServingService\_pb2\_grpc module :undoc-members: :show-inheritance: +feast.protos.feast.serving.TransformationService\_pb2 module +------------------------------------------------------------ + +.. automodule:: feast.protos.feast.serving.TransformationService_pb2 + :members: + :undoc-members: + :show-inheritance: + +feast.protos.feast.serving.TransformationService\_pb2\_grpc module +------------------------------------------------------------------ + +.. automodule:: feast.protos.feast.serving.TransformationService_pb2_grpc + :members: + :undoc-members: + :show-inheritance: + Module contents --------------- diff --git a/sdk/python/docs/source/feast.protos.feast.types.rst b/sdk/python/docs/source/feast.protos.feast.types.rst deleted file mode 100644 index aeb31bc9ad3..00000000000 --- a/sdk/python/docs/source/feast.protos.feast.types.rst +++ /dev/null @@ -1,61 +0,0 @@ -feast.protos.feast.types package -================================ - -Submodules ----------- - -feast.protos.feast.types.EntityKey\_pb2 module ----------------------------------------------- - -.. automodule:: feast.protos.feast.types.EntityKey_pb2 - :members: - :undoc-members: - :show-inheritance: - -feast.protos.feast.types.EntityKey\_pb2\_grpc module ----------------------------------------------------- - -.. automodule:: feast.protos.feast.types.EntityKey_pb2_grpc - :members: - :undoc-members: - :show-inheritance: - -feast.protos.feast.types.Field\_pb2 module ------------------------------------------- - -.. automodule:: feast.protos.feast.types.Field_pb2 - :members: - :undoc-members: - :show-inheritance: - -feast.protos.feast.types.Field\_pb2\_grpc module ------------------------------------------------- - -.. automodule:: feast.protos.feast.types.Field_pb2_grpc - :members: - :undoc-members: - :show-inheritance: - -feast.protos.feast.types.Value\_pb2 module ------------------------------------------- - -.. automodule:: feast.protos.feast.types.Value_pb2 - :members: - :undoc-members: - :show-inheritance: - -feast.protos.feast.types.Value\_pb2\_grpc module ------------------------------------------------- - -.. automodule:: feast.protos.feast.types.Value_pb2_grpc - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: feast.protos.feast.types - :members: - :undoc-members: - :show-inheritance: diff --git a/sdk/python/docs/source/feast.rst b/sdk/python/docs/source/feast.rst index 3e1ee906034..35220913be4 100644 --- a/sdk/python/docs/source/feast.rst +++ b/sdk/python/docs/source/feast.rst @@ -7,34 +7,27 @@ Subpackages .. toctree:: :maxdepth: 4 + feast.diff + feast.dqm feast.infra feast.loaders feast.protos - feast.staging Submodules ---------- -feast.cli module ----------------- - -.. automodule:: feast.cli - :members: - :undoc-members: - :show-inheritance: +feast.base\_feature\_view module +-------------------------------- -feast.client module -------------------- - -.. automodule:: feast.client +.. automodule:: feast.base_feature_view :members: :undoc-members: :show-inheritance: -feast.config module -------------------- +feast.cli module +---------------- -.. automodule:: feast.config +.. automodule:: feast.cli :members: :undoc-members: :show-inheritance: @@ -87,6 +80,14 @@ feast.errors module :undoc-members: :show-inheritance: +feast.feast\_object module +-------------------------- + +.. automodule:: feast.feast_object + :members: + :undoc-members: + :show-inheritance: + feast.feature module -------------------- @@ -95,18 +96,26 @@ feast.feature module :undoc-members: :show-inheritance: -feast.feature\_store module ---------------------------- +feast.feature\_server module +---------------------------- -.. automodule:: feast.feature_store +.. automodule:: feast.feature_server + :members: + :undoc-members: + :show-inheritance: + +feast.feature\_service module +----------------------------- + +.. automodule:: feast.feature_service :members: :undoc-members: :show-inheritance: -feast.feature\_table module +feast.feature\_store module --------------------------- -.. automodule:: feast.feature_table +.. automodule:: feast.feature_store :members: :undoc-members: :show-inheritance: @@ -119,6 +128,54 @@ feast.feature\_view module :undoc-members: :show-inheritance: +feast.feature\_view\_projection module +-------------------------------------- + +.. automodule:: feast.feature_view_projection + :members: + :undoc-members: + :show-inheritance: + +feast.field module +------------------ + +.. automodule:: feast.field + :members: + :undoc-members: + :show-inheritance: + +feast.flags module +------------------ + +.. automodule:: feast.flags + :members: + :undoc-members: + :show-inheritance: + +feast.flags\_helper module +-------------------------- + +.. automodule:: feast.flags_helper + :members: + :undoc-members: + :show-inheritance: + +feast.importer module +--------------------- + +.. automodule:: feast.importer + :members: + :undoc-members: + :show-inheritance: + +feast.inference module +---------------------- + +.. automodule:: feast.inference + :members: + :undoc-members: + :show-inheritance: + feast.names module ------------------ @@ -127,6 +184,14 @@ feast.names module :undoc-members: :show-inheritance: +feast.on\_demand\_feature\_view module +-------------------------------------- + +.. automodule:: feast.on_demand_feature_view + :members: + :undoc-members: + :show-inheritance: + feast.online\_response module ----------------------------- @@ -135,6 +200,14 @@ feast.online\_response module :undoc-members: :show-inheritance: +feast.proto\_json module +------------------------ + +.. automodule:: feast.proto_json + :members: + :undoc-members: + :show-inheritance: + feast.registry module --------------------- @@ -143,6 +216,14 @@ feast.registry module :undoc-members: :show-inheritance: +feast.registry\_store module +---------------------------- + +.. automodule:: feast.registry_store + :members: + :undoc-members: + :show-inheritance: + feast.repo\_config module ------------------------- @@ -151,6 +232,14 @@ feast.repo\_config module :undoc-members: :show-inheritance: +feast.repo\_contents module +--------------------------- + +.. automodule:: feast.repo_contents + :members: + :undoc-members: + :show-inheritance: + feast.repo\_operations module ----------------------------- @@ -159,10 +248,26 @@ feast.repo\_operations module :undoc-members: :show-inheritance: -feast.telemetry module ----------------------- +feast.request\_feature\_view module +----------------------------------- + +.. automodule:: feast.request_feature_view + :members: + :undoc-members: + :show-inheritance: + +feast.saved\_dataset module +--------------------------- -.. automodule:: feast.telemetry +.. automodule:: feast.saved_dataset + :members: + :undoc-members: + :show-inheritance: + +feast.transformation\_server module +----------------------------------- + +.. automodule:: feast.transformation_server :members: :undoc-members: :show-inheritance: @@ -175,6 +280,22 @@ feast.type\_map module :undoc-members: :show-inheritance: +feast.types module +------------------ + +.. automodule:: feast.types + :members: + :undoc-members: + :show-inheritance: + +feast.usage module +------------------ + +.. automodule:: feast.usage + :members: + :undoc-members: + :show-inheritance: + feast.utils module ------------------ diff --git a/sdk/python/docs/source/feast.staging.rst b/sdk/python/docs/source/feast.staging.rst deleted file mode 100644 index 5ad63281a6a..00000000000 --- a/sdk/python/docs/source/feast.staging.rst +++ /dev/null @@ -1,29 +0,0 @@ -feast.staging package -===================== - -Submodules ----------- - -feast.staging.entities module ------------------------------ - -.. automodule:: feast.staging.entities - :members: - :undoc-members: - :show-inheritance: - -feast.staging.storage\_client module ------------------------------------- - -.. automodule:: feast.staging.storage_client - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: feast.staging - :members: - :undoc-members: - :show-inheritance: diff --git a/sdk/python/docs/source/index.rst b/sdk/python/docs/source/index.rst index 602c384cc57..52783b40e3d 100644 --- a/sdk/python/docs/source/index.rst +++ b/sdk/python/docs/source/index.rst @@ -1,5 +1,5 @@ Feast Python API Documentation -============================= +============================== Feature Store @@ -38,6 +38,28 @@ Redshift Source :members: :exclude-members: RedshiftOptions +Snowflake Source +------------------ + +.. automodule:: feast.infra.offline_stores.snowflake_source + :members: + :exclude-members: SnowflakeOptions + +Spark Source +------------------ + +.. automodule:: feast.infra.offline_stores.contrib.spark_offline_store.spark_source + :members: + :exclude-members: SparkOptions + +Trino Source +------------------ + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino_source + :members: + :exclude-members: TrinoOptions + + File Source ------------------ @@ -59,7 +81,7 @@ Feature View :members: On Demand Feature View -================== +====================== .. automodule:: feast.on_demand_feature_view :members: @@ -85,6 +107,15 @@ Registry :inherited-members: :members: +Registry Store +================== + +.. automodule:: feast.registry_store + :inherited-members: + :members: + :exclude-members: NoopRegistryStore + + Provider ================== @@ -93,7 +124,7 @@ Provider :members: Passthrough Provider ------------------- +-------------------- .. automodule:: feast.infra.passthrough_provider :members: @@ -132,17 +163,36 @@ File Offline Store :members: BigQuery Offline Store ------------------- +---------------------- .. automodule:: feast.infra.offline_stores.bigquery :members: Redshift Offline Store ------------------- +---------------------- .. automodule:: feast.infra.offline_stores.redshift :members: +Snowflake Offline Store +----------------------- + +.. automodule:: feast.infra.offline_stores.snowflake + :members: + +Spark Offline Store +------------------- + +.. automodule:: feast.infra.offline_stores.contrib.spark_offline_store.spark + :members: + +Trino Offline Store +------------------- + +.. automodule:: feast.infra.offline_stores.contrib.trino_offline_store.trino + :members: + + Online Store ================== @@ -151,19 +201,19 @@ Online Store :members: Sqlite Online Store ------------------- +------------------- .. automodule:: feast.infra.online_stores.sqlite :members: Datastore Online Store ------------------- +---------------------- .. automodule:: feast.infra.online_stores.datastore :members: DynamoDB Online Store ------------------- +--------------------- .. automodule:: feast.infra.online_stores.dynamodb :members: @@ -172,4 +222,5 @@ Redis Online Store ------------------ .. automodule:: feast.infra.online_stores.redis - :members: \ No newline at end of file + :members: + :noindex: \ No newline at end of file diff --git a/sdk/python/docs/source/modules.rst b/sdk/python/docs/source/modules.rst deleted file mode 100644 index 3a6f8333abd..00000000000 --- a/sdk/python/docs/source/modules.rst +++ /dev/null @@ -1,7 +0,0 @@ -feast -===== - -.. toctree:: - :maxdepth: 4 - - feast diff --git a/sdk/python/feast/__init__.py b/sdk/python/feast/__init__.py index 0af226aa056..5127e03b560 100644 --- a/sdk/python/feast/__init__.py +++ b/sdk/python/feast/__init__.py @@ -3,19 +3,23 @@ from pkg_resources import DistributionNotFound, get_distribution from feast.infra.offline_stores.bigquery_source import BigQuerySource -from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( - SparkSource, -) from feast.infra.offline_stores.file_source import FileSource from feast.infra.offline_stores.redshift_source import RedshiftSource from feast.infra.offline_stores.snowflake_source import SnowflakeSource -from .data_source import KafkaSource, KinesisSource, SourceType +from .data_source import ( + KafkaSource, + KinesisSource, + PushSource, + RequestSource, + SourceType, +) from .entity import Entity from .feature import Feature from .feature_service import FeatureService from .feature_store import FeatureStore from .feature_view import FeatureView +from .field import Field from .on_demand_feature_view import OnDemandFeatureView from .repo_config import RepoConfig from .request_feature_view import RequestFeatureView @@ -38,6 +42,7 @@ "KafkaSource", "KinesisSource", "Feature", + "Field", "FeatureService", "FeatureStore", "FeatureView", @@ -50,5 +55,6 @@ "RedshiftSource", "RequestFeatureView", "SnowflakeSource", - "SparkSource", + "PushSource", + "RequestSource", ] diff --git a/sdk/python/feast/base_feature_view.py b/sdk/python/feast/base_feature_view.py index b0cd70617fc..67435fa44c8 100644 --- a/sdk/python/feast/base_feature_view.py +++ b/sdk/python/feast/base_feature_view.py @@ -11,33 +11,77 @@ # 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. -import warnings from abc import ABC, abstractmethod from datetime import datetime -from typing import List, Optional, Type +from typing import Dict, List, Optional, Type from google.protobuf.json_format import MessageToJson from proto import Message -from feast.feature import Feature from feast.feature_view_projection import FeatureViewProjection - -warnings.simplefilter("once", DeprecationWarning) +from feast.field import Field class BaseFeatureView(ABC): - """A FeatureView defines a logical grouping of features to be served.""" - + """ + A BaseFeatureView defines a logical group of features. + + Attributes: + name: The unique name of the base feature view. + features: The list of features defined as part of this base feature view. + description: A human-readable description. + tags: A dictionary of key-value pairs to store arbitrary metadata. + owner: The owner of the base feature view, typically the email of the primary + maintainer. + projection: The feature view projection storing modifications to be applied to + this base feature view at retrieval time. + created_timestamp (optional): The time when the base feature view was created. + last_updated_timestamp (optional): The time when the base feature view was last + updated. + """ + + name: str + features: List[Field] + description: str + tags: Dict[str, str] + owner: str + projection: FeatureViewProjection created_timestamp: Optional[datetime] last_updated_timestamp: Optional[datetime] @abstractmethod - def __init__(self, name: str, features: List[Feature]): + def __init__( + self, + *, + name: str, + features: Optional[List[Field]] = None, + description: str = "", + tags: Optional[Dict[str, str]] = None, + owner: str = "", + ): + """ + Creates a BaseFeatureView object. + + Args: + name: The unique name of the base feature view. + features (optional): The list of features defined as part of this base feature view. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the base feature view, typically the email of the + primary maintainer. + + Raises: + ValueError: A field mapping conflicts with an Entity or a Feature. + """ + assert name is not None self.name = name - self.features = features + self.features = features or [] + self.description = description + self.tags = tags or {} + self.owner = owner self.projection = FeatureViewProjection.from_definition(self) - self.created_timestamp: Optional[datetime] = None - self.last_updated_timestamp: Optional[datetime] = None + self.created_timestamp = None + self.last_updated_timestamp = None @property @abstractmethod @@ -55,12 +99,7 @@ def from_proto(cls, feature_view_proto): @abstractmethod def __copy__(self): - """ - Generates a deep copy of this feature view - - Returns: - A copy of this FeatureView - """ + """Returns a deep copy of this base feature view.""" pass def __repr__(self): @@ -92,10 +131,13 @@ def __eq__(self, other): "Comparisons should only involve BaseFeatureView class objects." ) - if self.name != other.name: - return False - - if sorted(self.features) != sorted(other.features): + if ( + self.name != other.name + or sorted(self.features) != sorted(other.features) + or self.description != other.description + or self.tags != other.tags + or self.owner != other.owner + ): return False return True @@ -112,15 +154,11 @@ def ensure_valid(self): def with_name(self, name: str): """ - Renames this feature view by returning a copy of this feature view with an alias - set for the feature view name. This rename operation is only used as part of query - operations and will not modify the underlying FeatureView. + Returns a renamed copy of this base feature view. This renamed copy should only be + used for query operations and will not modify the underlying base feature view. Args: - name: Name to assign to the FeatureView copy. - - Returns: - A copy of this FeatureView with the name replaced with the 'name' input. + name: The name to assign to the copy. """ cp = self.__copy__() cp.projection.name_alias = name @@ -129,15 +167,13 @@ def with_name(self, name: str): def set_projection(self, feature_view_projection: FeatureViewProjection) -> None: """ - Setter for the projection object held by this FeatureView. A projection is an - object that stores the modifications to a FeatureView that is applied to the FeatureView - when the FeatureView is used such as during feature_store.get_historical_features. - This method also performs checks to ensure the projection is consistent with this - FeatureView before doing the set. + Sets the feature view projection of this base feature view to the given projection. Args: - feature_view_projection: The FeatureViewProjection object to set this FeatureView's - 'projection' field to. + feature_view_projection: The feature view projection to be set. + + Raises: + ValueError: The name or features of the projection do not match. """ if feature_view_projection.name != self.name: raise ValueError( @@ -157,18 +193,14 @@ def set_projection(self, feature_view_projection: FeatureViewProjection) -> None def with_projection(self, feature_view_projection: FeatureViewProjection): """ - Sets the feature view projection by returning a copy of this on-demand feature view - with its projection set to the given projection. A projection is an - object that stores the modifications to a feature view that is used during - query operations. + Returns a copy of this base feature view with the feature view projection set to + the given projection. Args: - feature_view_projection: The FeatureViewProjection object to link to this - OnDemandFeatureView. + feature_view_projection: The feature view projection to assign to the copy. - Returns: - A copy of this OnDemandFeatureView with its projection replaced with the - 'feature_view_projection' argument. + Raises: + ValueError: The name or features of the projection do not match. """ if feature_view_projection.name != self.name: raise ValueError( diff --git a/sdk/python/feast/cli.py b/sdk/python/feast/cli.py index d2a71bc561b..7dc8e198599 100644 --- a/sdk/python/feast/cli.py +++ b/sdk/python/feast/cli.py @@ -13,6 +13,7 @@ # limitations under the License. import logging +import warnings from datetime import datetime from pathlib import Path from typing import List, Optional @@ -21,6 +22,7 @@ import pkg_resources import yaml from colorama import Fore, Style +from dateutil import parser from feast import flags, flags_helper, utils from feast.constants import DEFAULT_FEATURE_TRANSFORMATION_SERVER_PORT @@ -40,7 +42,6 @@ ) _logger = logging.getLogger(__name__) -DATETIME_ISO = "%Y-%m-%dT%H:%M:%s" class NoOptionDefaultFormat(click.Command): @@ -151,6 +152,11 @@ def data_source_describe(ctx: click.Context, name: str): print(e) exit(1) + warnings.warn( + "Describing data sources will only work properly if all data sources have names or table names specified. " + "Starting Feast 0.21, data source unique names will be required to encourage data source discovery.", + RuntimeWarning, + ) print( yaml.dump( yaml.safe_load(str(data_source)), default_flow_style=False, sort_keys=False @@ -173,6 +179,11 @@ def data_source_list(ctx: click.Context): from tabulate import tabulate + warnings.warn( + "Listing data sources will only work properly if all data sources have names or table names specified. " + "Starting Feast 0.21, data source unique names will be required to encourage data source discovery", + RuntimeWarning, + ) print(tabulate(table, headers=["NAME", "CLASS"], tablefmt="plain")) @@ -334,7 +345,7 @@ def feature_view_list(ctx: click.Context): if isinstance(feature_view, FeatureView): entities.update(feature_view.entities) elif isinstance(feature_view, OnDemandFeatureView): - for backing_fv in feature_view.input_feature_view_projections.values(): + for backing_fv in feature_view.source_feature_view_projections.values(): entities.update(store.get_feature_view(backing_fv.name).entities) table.append( [ @@ -490,8 +501,8 @@ def materialize_command( store = FeatureStore(repo_path=str(repo)) store.materialize( feature_views=None if not views else views, - start_date=utils.make_tzaware(datetime.fromisoformat(start_ts)), - end_date=utils.make_tzaware(datetime.fromisoformat(end_ts)), + start_date=utils.make_tzaware(parser.parse(start_ts)), + end_date=utils.make_tzaware(parser.parse(end_ts)), ) diff --git a/sdk/python/feast/data_source.py b/sdk/python/feast/data_source.py index 15ce0c23773..0e264117ae5 100644 --- a/sdk/python/feast/data_source.py +++ b/sdk/python/feast/data_source.py @@ -12,15 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. - import enum +import warnings from abc import ABC, abstractmethod -from typing import Any, Callable, Dict, Iterable, Optional, Tuple +from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union + +from google.protobuf.json_format import MessageToJson from feast import type_map from feast.data_format import StreamFormat +from feast.field import Field, from_value_type from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.repo_config import RepoConfig, get_data_source_class_from_type +from feast.types import VALUE_TYPES_TO_FEAST_TYPES from feast.value_type import ValueType @@ -34,6 +38,7 @@ class SourceType(enum.Enum): BATCH_BIGQUERY = 2 STREAM_KAFKA = 3 STREAM_KINESIS = 4 + BATCH_TRINO = 5 class KafkaOptions: @@ -134,13 +139,27 @@ def to_proto(self) -> DataSourceProto.KinesisOptions: return kinesis_options_proto +_DATA_SOURCE_OPTIONS = { + DataSourceProto.SourceType.BATCH_FILE: "feast.infra.offline_stores.file_source.FileSource", + DataSourceProto.SourceType.BATCH_BIGQUERY: "feast.infra.offline_stores.bigquery_source.BigQuerySource", + DataSourceProto.SourceType.BATCH_REDSHIFT: "feast.infra.offline_stores.redshift_source.RedshiftSource", + DataSourceProto.SourceType.BATCH_SNOWFLAKE: "feast.infra.offline_stores.snowflake_source.SnowflakeSource", + DataSourceProto.SourceType.BATCH_TRINO: "feast.infra.offline_stores.contrib.trino_offline_store.trino_source.TrinoSource", + DataSourceProto.SourceType.BATCH_SPARK: "feast.infra.offline_stores.contrib.spark_offline_store.spark_source.SparkSource", + DataSourceProto.SourceType.STREAM_KAFKA: "feast.data_source.KafkaSource", + DataSourceProto.SourceType.STREAM_KINESIS: "feast.data_source.KinesisSource", + DataSourceProto.SourceType.REQUEST_SOURCE: "feast.data_source.RequestSource", + DataSourceProto.SourceType.PUSH_SOURCE: "feast.data_source.PushSource", +} + + class DataSource(ABC): """ DataSource that can be used to source features. Args: name: Name of data source, which should be unique within a project - event_timestamp_column (optional): Event timestamp column used for point in time + timestamp_field (optional): (Deprecated) Event timestamp column used for point in time joins of feature values. created_timestamp_column (optional): Timestamp column indicating when the row was created, used for deduplicating rows. @@ -148,27 +167,72 @@ class DataSource(ABC): source to feature names in a feature table or view. Only used for feature columns, not entity or timestamp columns. date_partition_column (optional): Timestamp column used for partitioning. + description (optional) A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the data source, typically the email of the primary + maintainer. + timestamp_field (optional): Event timestamp field used for point in time + joins of feature values. """ name: str - event_timestamp_column: str + timestamp_field: str created_timestamp_column: str field_mapping: Dict[str, str] date_partition_column: str + description: str + tags: Dict[str, str] + owner: str def __init__( self, - name: str, event_timestamp_column: Optional[str] = None, created_timestamp_column: Optional[str] = None, field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = None, + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + name: Optional[str] = None, + timestamp_field: Optional[str] = None, ): - """Creates a DataSource object.""" - self.name = name - self.event_timestamp_column = ( - event_timestamp_column if event_timestamp_column else "" - ) + """ + Creates a DataSource object. + Args: + name: Name of data source, which should be unique within a project + event_timestamp_column (optional): (Deprecated) Event timestamp column used for point in time + joins of feature values. + created_timestamp_column (optional): Timestamp column indicating when the row + was created, used for deduplicating rows. + field_mapping (optional): A dictionary mapping of column names in this data + source to feature names in a feature table or view. Only used for feature + columns, not entity or timestamp columns. + date_partition_column (optional): Timestamp column used for partitioning. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the data source, typically the email of the primary + maintainer. + timestamp_field (optional): Event timestamp field used for point + in time joins of feature values. + """ + if not name: + warnings.warn( + ( + "Names for data sources need to be supplied. " + "Data sources without names will not be supported after Feast 0.23." + ), + UserWarning, + ) + self.name = name or "" + if not timestamp_field and event_timestamp_column: + warnings.warn( + ( + "The argument 'event_timestamp_column' is being deprecated. Please use 'timestamp_field' instead. " + "instead. Feast 0.23 and onwards will not support the argument 'event_timestamp_column' for datasources." + ), + DeprecationWarning, + ) + self.timestamp_field = timestamp_field or event_timestamp_column or "" self.created_timestamp_column = ( created_timestamp_column if created_timestamp_column else "" ) @@ -176,20 +240,32 @@ def __init__( self.date_partition_column = ( date_partition_column if date_partition_column else "" ) + self.description = description or "" + self.tags = tags or {} + self.owner = owner or "" def __hash__(self): return hash((id(self), self.name)) + def __str__(self): + return str(MessageToJson(self.to_proto())) + def __eq__(self, other): + if other is None: + return False + if not isinstance(other, DataSource): raise TypeError("Comparisons should only involve DataSource class objects.") if ( self.name != other.name - or self.event_timestamp_column != other.event_timestamp_column + or self.timestamp_field != other.timestamp_field or self.created_timestamp_column != other.created_timestamp_column or self.field_mapping != other.field_mapping or self.date_partition_column != other.date_partition_column + or self.tags != other.tags + or self.owner != other.owner + or self.description != other.description ): return False @@ -210,48 +286,20 @@ def from_proto(data_source: DataSourceProto) -> Any: Raises: ValueError: The type of DataSource could not be identified. """ - if data_source.data_source_class_type: - cls = get_data_source_class_from_type(data_source.data_source_class_type) - return cls.from_proto(data_source) - - if data_source.request_data_options and data_source.request_data_options.schema: - data_source_obj = RequestDataSource.from_proto(data_source) - elif data_source.file_options.file_format and data_source.file_options.file_url: - from feast.infra.offline_stores.file_source import FileSource - - data_source_obj = FileSource.from_proto(data_source) - elif ( - data_source.bigquery_options.table_ref or data_source.bigquery_options.query - ): - from feast.infra.offline_stores.bigquery_source import BigQuerySource - - data_source_obj = BigQuerySource.from_proto(data_source) - elif data_source.redshift_options.table or data_source.redshift_options.query: - from feast.infra.offline_stores.redshift_source import RedshiftSource - - data_source_obj = RedshiftSource.from_proto(data_source) - - elif data_source.snowflake_options.table or data_source.snowflake_options.query: - from feast.infra.offline_stores.snowflake_source import SnowflakeSource - - data_source_obj = SnowflakeSource.from_proto(data_source) - - elif ( - data_source.kafka_options.bootstrap_servers - and data_source.kafka_options.topic - and data_source.kafka_options.message_format - ): - data_source_obj = KafkaSource.from_proto(data_source) - elif ( - data_source.kinesis_options.record_format - and data_source.kinesis_options.region - and data_source.kinesis_options.stream_name + data_source_type = data_source.type + if not data_source_type or ( + data_source_type + not in list(_DATA_SOURCE_OPTIONS.keys()) + + [DataSourceProto.SourceType.CUSTOM_SOURCE] ): - data_source_obj = KinesisSource.from_proto(data_source) - else: raise ValueError("Could not identify the source type being added.") - return data_source_obj + if data_source_type == DataSourceProto.SourceType.CUSTOM_SOURCE: + cls = get_data_source_class_from_type(data_source.data_source_class_type) + return cls.from_proto(data_source) + + cls = get_data_source_class_from_type(_DATA_SOURCE_OPTIONS[data_source_type]) + return cls.from_proto(data_source) @abstractmethod def to_proto(self) -> DataSourceProto: @@ -314,14 +362,24 @@ def __init__( created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = "", + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = "", + batch_source: Optional[DataSource] = None, ): super().__init__( - name, - event_timestamp_column, - created_timestamp_column, - field_mapping, - date_partition_column, + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + date_partition_column=date_partition_column, + description=description, + tags=tags, + owner=owner, + name=name, + timestamp_field=timestamp_field, ) + self.batch_source = batch_source self.kafka_options = KafkaOptions( bootstrap_servers=bootstrap_servers, message_format=message_format, @@ -348,15 +406,20 @@ def __eq__(self, other): def from_proto(data_source: DataSourceProto): return KafkaSource( name=data_source.name, + event_timestamp_column=data_source.timestamp_field, field_mapping=dict(data_source.field_mapping), bootstrap_servers=data_source.kafka_options.bootstrap_servers, message_format=StreamFormat.from_proto( data_source.kafka_options.message_format ), topic=data_source.kafka_options.topic, - event_timestamp_column=data_source.event_timestamp_column, created_timestamp_column=data_source.created_timestamp_column, + timestamp_field=data_source.timestamp_field, date_partition_column=data_source.date_partition_column, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, + batch_source=DataSource.from_proto(data_source.batch_source), ) def to_proto(self) -> DataSourceProto: @@ -365,12 +428,16 @@ def to_proto(self) -> DataSourceProto: type=DataSourceProto.STREAM_KAFKA, field_mapping=self.field_mapping, kafka_options=self.kafka_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column data_source_proto.date_partition_column = self.date_partition_column - + if self.batch_source: + data_source_proto.batch_source.MergeFrom(self.batch_source.to_proto()) return data_source_proto @staticmethod @@ -381,24 +448,51 @@ def get_table_query_string(self) -> str: raise NotImplementedError -class RequestDataSource(DataSource): +class RequestSource(DataSource): """ - RequestDataSource that can be used to provide input features for on demand transforms + RequestSource that can be used to provide input features for on demand transforms Args: name: Name of the request data source - schema: Schema mapping from the input feature name to a ValueType + schema Union[Dict[str, ValueType], List[Field]]: Schema mapping from the input feature name to a ValueType + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the request data source, typically the email of the primary + maintainer. """ name: str - schema: Dict[str, ValueType] + schema: List[Field] def __init__( - self, name: str, schema: Dict[str, ValueType], + self, + name: str, + schema: Union[Dict[str, ValueType], List[Field]], + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", ): - """Creates a RequestDataSource object.""" - super().__init__(name) - self.schema = schema + """Creates a RequestSource object.""" + super().__init__(name=name, description=description, tags=tags, owner=owner) + if isinstance(schema, Dict): + warnings.warn( + "Schema in RequestSource is changing type. The schema data type Dict[str, ValueType] is being deprecated in Feast 0.23. " + "Please use List[Field] instead for the schema", + DeprecationWarning, + ) + schemaList = [] + for key, valueType in schema.items(): + schemaList.append( + Field(name=key, dtype=VALUE_TYPES_TO_FEAST_TYPES[valueType]) + ) + self.schema = schemaList + elif isinstance(schema, List): + self.schema = schema + else: + raise Exception( + "Schema type must be either dictionary or list, not " + + str(type(schema)) + ) def validate(self, config: RepoConfig): pass @@ -408,24 +502,86 @@ def get_table_column_names_and_types( ) -> Iterable[Tuple[str, str]]: pass + def __eq__(self, other): + if not isinstance(other, RequestSource): + raise TypeError( + "Comparisons should only involve RequestSource class objects." + ) + if ( + self.name != other.name + or self.description != other.description + or self.owner != other.owner + or self.tags != other.tags + ): + return False + if isinstance(self.schema, List) and isinstance(other.schema, List): + for field1, field2 in zip(self.schema, other.schema): + if field1 != field2: + return False + return True + else: + return False + + def __hash__(self): + return super().__hash__() + @staticmethod def from_proto(data_source: DataSourceProto): + + deprecated_schema = data_source.request_data_options.deprecated_schema schema_pb = data_source.request_data_options.schema - schema = {} - for key in schema_pb.keys(): - schema[key] = ValueType(schema_pb.get(key)) - return RequestDataSource(name=data_source.name, schema=schema) + + if deprecated_schema and not schema_pb: + warnings.warn( + "Schema in RequestSource is changing type. The schema data type Dict[str, ValueType] is being deprecated in Feast 0.23. " + "Please use List[Field] instead for the schema", + DeprecationWarning, + ) + dict_schema = {} + for key, val in deprecated_schema.items(): + dict_schema[key] = ValueType(val) + return RequestSource( + name=data_source.name, + schema=dict_schema, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, + ) + else: + list_schema = [] + for field_proto in schema_pb: + list_schema.append(Field.from_proto(field_proto)) + + return RequestSource( + name=data_source.name, + schema=list_schema, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, + ) def to_proto(self) -> DataSourceProto: - schema_pb = {} - for key, value in self.schema.items(): - schema_pb[key] = value.value - options = DataSourceProto.RequestDataOptions(schema=schema_pb) + + schema_pb = [] + + if isinstance(self.schema, Dict): + for key, value in self.schema.items(): + schema_pb.append( + Field( + name=key, dtype=VALUE_TYPES_TO_FEAST_TYPES[value.value] + ).to_proto() + ) + else: + for field in self.schema: + schema_pb.append(field.to_proto()) data_source_proto = DataSourceProto( name=self.name, type=DataSourceProto.REQUEST_SOURCE, - request_data_options=options, + description=self.description, + tags=self.tags, + owner=self.owner, ) + data_source_proto.request_data_options.schema.extend(schema_pb) return data_source_proto @@ -437,6 +593,15 @@ def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: raise NotImplementedError +class RequestDataSource(RequestSource): + def __init__(self, *args, **kwargs): + warnings.warn( + "The 'RequestDataSource' class is deprecated and was renamed to RequestSource. Please use RequestSource instead. This class name will be removed in Feast 0.23.", + DeprecationWarning, + ) + super().__init__(*args, **kwargs) + + class KinesisSource(DataSource): def validate(self, config: RepoConfig): pass @@ -450,15 +615,20 @@ def get_table_column_names_and_types( def from_proto(data_source: DataSourceProto): return KinesisSource( name=data_source.name, + event_timestamp_column=data_source.timestamp_field, field_mapping=dict(data_source.field_mapping), record_format=StreamFormat.from_proto( data_source.kinesis_options.record_format ), region=data_source.kinesis_options.region, stream_name=data_source.kinesis_options.stream_name, - event_timestamp_column=data_source.event_timestamp_column, created_timestamp_column=data_source.created_timestamp_column, + timestamp_field=data_source.timestamp_field, date_partition_column=data_source.date_partition_column, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, + batch_source=DataSource.from_proto(data_source.batch_source), ) @staticmethod @@ -478,14 +648,24 @@ def __init__( stream_name: str, field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = "", + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = "", + batch_source: Optional[DataSource] = None, ): super().__init__( - name, - event_timestamp_column, - created_timestamp_column, - field_mapping, - date_partition_column, + name=name, + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + date_partition_column=date_partition_column, + description=description, + tags=tags, + owner=owner, + timestamp_field=timestamp_field, ) + self.batch_source = batch_source self.kinesis_options = KinesisOptions( record_format=record_format, region=region, stream_name=stream_name ) @@ -515,10 +695,118 @@ def to_proto(self) -> DataSourceProto: type=DataSourceProto.STREAM_KINESIS, field_mapping=self.field_mapping, kinesis_options=self.kinesis_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column data_source_proto.date_partition_column = self.date_partition_column + if self.batch_source: + data_source_proto.batch_source.MergeFrom(self.batch_source.to_proto()) + + return data_source_proto + + +class PushSource(DataSource): + """ + A source that can be used to ingest features on request + """ + + name: str + schema: List[Field] + batch_source: DataSource + timestamp_field: str + + def __init__( + self, + *, + name: str, + schema: List[Field], + batch_source: DataSource, + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = "", + ): + """ + Creates a PushSource object. + Args: + name: Name of the push source + schema: Schema mapping from the input feature name to a ValueType + batch_source: The batch source that backs this push source. It's used when materializing from the offline + store to the online store, and when retrieving historical features. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the data source, typically the email of the primary + maintainer. + timestamp_field (optional): Event timestamp foe;d used for point in time + joins of feature values. + + """ + super().__init__(name=name, description=description, tags=tags, owner=owner) + self.schema = sorted(schema) # TODO: add schema inference from a batch source + self.batch_source = batch_source + if not self.batch_source: + raise ValueError(f"batch_source is needed for push source {self.name}") + if not timestamp_field: + raise ValueError(f"timestamp field is needed for push source {self.name}") + self.timestamp_field = timestamp_field + + def validate(self, config: RepoConfig): + pass + + def get_table_column_names_and_types( + self, config: RepoConfig + ) -> Iterable[Tuple[str, str]]: + pass + + @staticmethod + def from_proto(data_source: DataSourceProto): + schema_pb = data_source.push_options.schema + schema = [] + for key, val in schema_pb.items(): + schema.append(Field(name=key, dtype=from_value_type(ValueType(val)))) + + assert data_source.HasField("batch_source") + batch_source = DataSource.from_proto(data_source.batch_source) + + return PushSource( + name=data_source.name, + schema=sorted(schema), + batch_source=batch_source, + timestamp_field=data_source.timestamp_field, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, + ) + + def to_proto(self) -> DataSourceProto: + schema_pb = {} + for field in self.schema: + schema_pb[field.name] = field.dtype.to_value_type().value + batch_source_proto = None + if self.batch_source: + batch_source_proto = self.batch_source.to_proto() + + options = DataSourceProto.PushOptions(schema=schema_pb,) + data_source_proto = DataSourceProto( + name=self.name, + type=DataSourceProto.PUSH_SOURCE, + push_options=options, + timestamp_field=self.timestamp_field, + description=self.description, + tags=self.tags, + owner=self.owner, + batch_source=batch_source_proto, + ) return data_source_proto + + def get_table_query_string(self) -> str: + raise NotImplementedError + + @staticmethod + def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: + raise NotImplementedError diff --git a/sdk/python/feast/diff/registry_diff.py b/sdk/python/feast/diff/registry_diff.py index 4558a149a5c..10bd88c56f8 100644 --- a/sdk/python/feast/diff/registry_diff.py +++ b/sdk/python/feast/diff/registry_diff.py @@ -60,6 +60,9 @@ def to_string(self): continue if feast_object_diff.transition_type == TransitionType.UNCHANGED: continue + if feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: + # TODO(adchia): Print statements out starting in Feast 0.21 + continue action, color = message_action_map[feast_object_diff.transition_type] log_string += f"{action} {feast_object_diff.feast_object_type.value} {Style.BRIGHT + color}{feast_object_diff.name}{Style.RESET_ALL}\n" if feast_object_diff.transition_type == TransitionType.UPDATE: @@ -78,8 +81,11 @@ def to_string(self): def tag_objects_for_keep_delete_update_add( existing_objs: Iterable[FeastObject], desired_objs: Iterable[FeastObject] ) -> Tuple[Set[FeastObject], Set[FeastObject], Set[FeastObject], Set[FeastObject]]: - existing_obj_names = {e.name for e in existing_objs} - desired_obj_names = {e.name for e in desired_objs} + # TODO(adchia): Remove the "if X.name" condition when data sources are forced to have names + existing_obj_names = {e.name for e in existing_objs if e.name} + desired_objs = [obj for obj in desired_objs if obj.name] + existing_objs = [obj for obj in existing_objs if obj.name] + desired_obj_names = {e.name for e in desired_objs if e.name} objs_to_add = {e for e in desired_objs if e.name not in existing_obj_names} objs_to_update = {e for e in desired_objs if e.name in existing_obj_names} diff --git a/sdk/python/feast/protos/feast/__init__.py b/sdk/python/feast/embedded_go/lib/__init__.py similarity index 100% rename from sdk/python/feast/protos/feast/__init__.py rename to sdk/python/feast/embedded_go/lib/__init__.py diff --git a/sdk/python/feast/embedded_go/online_features_service.py b/sdk/python/feast/embedded_go/online_features_service.py new file mode 100644 index 00000000000..e2da2dfbd8f --- /dev/null +++ b/sdk/python/feast/embedded_go/online_features_service.py @@ -0,0 +1,295 @@ +from functools import partial +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union + +import pyarrow as pa +from google.protobuf.timestamp_pb2 import Timestamp +from pyarrow.cffi import ffi + +from feast.errors import ( + FeatureNameCollisionError, + RequestDataNotFoundInEntityRowsException, +) +from feast.feature_service import FeatureService +from feast.online_response import OnlineResponse +from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesResponse +from feast.protos.feast.types import Value_pb2 +from feast.repo_config import RepoConfig +from feast.value_type import ValueType + +from .lib.embedded import DataTable, NewOnlineFeatureService, OnlineFeatureServiceConfig +from .lib.go import Slice_string + +if TYPE_CHECKING: + from feast.feature_store import FeatureStore + + +ARROW_TYPE_TO_PROTO_FIELD = { + pa.int32(): "int32_val", + pa.int64(): "int64_val", + pa.float32(): "float_val", + pa.float64(): "double_val", + pa.bool_(): "bool_val", + pa.string(): "string_val", + pa.binary(): "bytes_val", + pa.time64("ns"): "unix_timestamp_val", +} + +ARROW_LIST_TYPE_TO_PROTO_FIELD = { + pa.int32(): "int32_list_val", + pa.int64(): "int64_list_val", + pa.float32(): "float_list_val", + pa.float64(): "double_list_val", + pa.bool_(): "bool_list_val", + pa.string(): "string_list_val", + pa.binary(): "bytes_list_val", + pa.time64("ns"): "unix_timestamp_list_val", +} + +ARROW_LIST_TYPE_TO_PROTO_LIST_CLASS = { + pa.int32(): Value_pb2.Int32List, + pa.int64(): Value_pb2.Int64List, + pa.float32(): Value_pb2.FloatList, + pa.float64(): Value_pb2.DoubleList, + pa.bool_(): Value_pb2.BoolList, + pa.string(): Value_pb2.StringList, + pa.binary(): Value_pb2.BytesList, + pa.time64("ns"): Value_pb2.Int64List, +} + +# used for entity types only +PROTO_TYPE_TO_ARROW_TYPE = { + ValueType.INT32: pa.int32(), + ValueType.INT64: pa.int64(), + ValueType.FLOAT: pa.float32(), + ValueType.DOUBLE: pa.float64(), + ValueType.STRING: pa.string(), + ValueType.BYTES: pa.binary(), +} + + +class EmbeddedOnlineFeatureServer: + def __init__( + self, repo_path: str, repo_config: RepoConfig, feature_store: "FeatureStore" + ): + # keep callback in self to prevent it from GC + self._transformation_callback = partial(transformation_callback, feature_store) + + self._service = NewOnlineFeatureService( + OnlineFeatureServiceConfig( + RepoPath=repo_path, RepoConfig=repo_config.json() + ), + self._transformation_callback, + ) + + def get_online_features( + self, + features_refs: List[str], + feature_service: Optional[FeatureService], + entities: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], + request_data: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], + full_feature_names: bool = False, + ): + + if feature_service: + join_keys_types = self._service.GetEntityTypesMapByFeatureService( + feature_service.name + ) + else: + join_keys_types = self._service.GetEntityTypesMap( + Slice_string(features_refs) + ) + + join_keys_types = { + join_key: ValueType(enum_value) for join_key, enum_value in join_keys_types + } + + # Here we create C structures that will be shared between Python and Go. + # We will pass entities as arrow Record Batch to Go part (in_c_array & in_c_schema) + # and receive features as Record Batch from Go (out_c_array & out_c_schema) + # This objects needs to be initialized here in order to correctly + # free them later using Python GC. + ( + entities_c_schema, + entities_ptr_schema, + entities_c_array, + entities_ptr_array, + ) = allocate_schema_and_array() + ( + req_data_c_schema, + req_data_ptr_schema, + req_data_c_array, + req_data_ptr_array, + ) = allocate_schema_and_array() + + ( + features_c_schema, + features_ptr_schema, + features_c_array, + features_ptr_array, + ) = allocate_schema_and_array() + + batch, schema = map_to_record_batch(entities, join_keys_types) + schema._export_to_c(entities_ptr_schema) + batch._export_to_c(entities_ptr_array) + + batch, schema = map_to_record_batch(request_data) + schema._export_to_c(req_data_ptr_schema) + batch._export_to_c(req_data_ptr_array) + + try: + self._service.GetOnlineFeatures( + featureRefs=Slice_string(features_refs), + featureServiceName=feature_service and feature_service.name or "", + entities=DataTable( + SchemaPtr=entities_ptr_schema, DataPtr=entities_ptr_array + ), + requestData=DataTable( + SchemaPtr=req_data_ptr_schema, DataPtr=req_data_ptr_array + ), + fullFeatureNames=full_feature_names, + output=DataTable( + SchemaPtr=features_ptr_schema, DataPtr=features_ptr_array + ), + ) + except RuntimeError as exc: + (msg,) = exc.args + if msg.startswith("featureNameCollisionError"): + feature_refs = msg[len("featureNameCollisionError: ") : msg.find(";")] + feature_refs = feature_refs.split(",") + raise FeatureNameCollisionError( + feature_refs_collisions=feature_refs, + full_feature_names=full_feature_names, + ) + + if msg.startswith("requestDataNotFoundInEntityRowsException"): + feature_refs = msg[len("requestDataNotFoundInEntityRowsException: ") :] + feature_refs = feature_refs.split(",") + raise RequestDataNotFoundInEntityRowsException(feature_refs) + + raise + + record_batch = pa.RecordBatch._import_from_c( + features_ptr_array, features_ptr_schema + ) + resp = record_batch_to_online_response(record_batch) + return OnlineResponse(resp) + + +def _to_arrow(value, type_hint: Optional[ValueType]) -> pa.Array: + if isinstance(value, Value_pb2.RepeatedValue): + _proto_to_arrow(value) + + if type_hint in PROTO_TYPE_TO_ARROW_TYPE: + return pa.array(value, PROTO_TYPE_TO_ARROW_TYPE[type_hint]) + + return pa.array(value) + + +def _proto_to_arrow(value: Value_pb2.RepeatedValue) -> pa.Array: + """ + ToDo: support entity rows already packed in protos + """ + raise NotImplementedError + + +def transformation_callback( + fs: "FeatureStore", + on_demand_feature_view_name: str, + input_arr_ptr: int, + input_schema_ptr: int, + output_arr_ptr: int, + output_schema_ptr: int, + full_feature_names: bool, +) -> int: + odfv = fs.get_on_demand_feature_view(on_demand_feature_view_name) + + input_record = pa.RecordBatch._import_from_c(input_arr_ptr, input_schema_ptr) + + output = odfv.get_transformed_features_df( + input_record.to_pandas(), full_feature_names=full_feature_names + ) + output_record = pa.RecordBatch.from_pandas(output) + + output_record.schema._export_to_c(output_schema_ptr) + output_record._export_to_c(output_arr_ptr) + + return output_record.num_rows + + +def allocate_schema_and_array(): + c_schema = ffi.new("struct ArrowSchema*") + ptr_schema = int(ffi.cast("uintptr_t", c_schema)) + + c_array = ffi.new("struct ArrowArray*") + ptr_array = int(ffi.cast("uintptr_t", c_array)) + return c_schema, ptr_schema, c_array, ptr_array + + +def map_to_record_batch( + map: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], + type_hint: Optional[Dict[str, ValueType]] = None, +) -> Tuple[pa.RecordBatch, pa.Schema]: + fields = [] + columns = [] + type_hint = type_hint or {} + + for name, values in map.items(): + arr = _to_arrow(values, type_hint.get(name)) + fields.append((name, arr.type)) + columns.append(arr) + + schema = pa.schema(fields) + batch = pa.RecordBatch.from_arrays(columns, schema=schema) + return batch, schema + + +def record_batch_to_online_response(record_batch): + resp = GetOnlineFeaturesResponse() + + for idx, field in enumerate(record_batch.schema): + if field.name.endswith("__timestamp") or field.name.endswith("__status"): + continue + + feature_vector = GetOnlineFeaturesResponse.FeatureVector( + statuses=record_batch.columns[idx + 1].to_pylist(), + event_timestamps=[ + Timestamp(seconds=seconds) + for seconds in record_batch.columns[idx + 2].to_pylist() + ], + ) + + if field.type == pa.null(): + feature_vector.values.extend( + [Value_pb2.Value()] * len(record_batch.columns[idx]) + ) + else: + if isinstance(field.type, pa.ListType): + proto_list_class = ARROW_LIST_TYPE_TO_PROTO_LIST_CLASS[ + field.type.value_type + ] + proto_field_name = ARROW_LIST_TYPE_TO_PROTO_FIELD[field.type.value_type] + + column = record_batch.columns[idx] + if field.type.value_type == pa.time64("ns"): + column = column.cast(pa.list_(pa.int64())) + + for v in column.tolist(): + feature_vector.values.append( + Value_pb2.Value(**{proto_field_name: proto_list_class(val=v)}) + ) + else: + proto_field_name = ARROW_TYPE_TO_PROTO_FIELD[field.type] + + column = record_batch.columns[idx] + if field.type == pa.time64("ns"): + column = column.cast(pa.int64()) + + for v in column.tolist(): + feature_vector.values.append( + Value_pb2.Value(**{proto_field_name: v}) + ) + + resp.results.append(feature_vector) + resp.metadata.feature_names.val.append(field.name) + + return resp diff --git a/sdk/python/feast/entity.py b/sdk/python/feast/entity.py index efac8c17dab..39886268609 100644 --- a/sdk/python/feast/entity.py +++ b/sdk/python/feast/entity.py @@ -13,7 +13,7 @@ # limitations under the License. import warnings from datetime import datetime -from typing import Dict, Optional +from typing import Dict, List, Optional from google.protobuf.json_format import MessageToJson @@ -23,8 +23,6 @@ from feast.usage import log_exceptions from feast.value_type import ValueType -warnings.simplefilter("once", DeprecationWarning) - class Entity: """ @@ -39,10 +37,12 @@ class Entity: with their associated features. If not specified, defaults to the name. description: A human-readable description. tags: A dictionary of key-value pairs to store arbitrary metadata. - owner: The owner of the feature service, typically the email of the primary - maintainer. + owner: The owner of the entity, typically the email of the primary maintainer. created_timestamp: The time when the entity was created. last_updated_timestamp: The time when the entity was last updated. + join_keys: A list of property that uniquely identifies different entities within the + collection. This is meant to replace the `join_key` parameter, but currently only + supports a list of size one. """ name: str @@ -53,36 +53,53 @@ class Entity: owner: str created_timestamp: Optional[datetime] last_updated_timestamp: Optional[datetime] + join_keys: List[str] @log_exceptions def __init__( self, - name: str, + *args, + name: Optional[str] = None, value_type: ValueType = ValueType.UNKNOWN, description: str = "", join_key: Optional[str] = None, - tags: Dict[str, str] = None, - labels: Optional[Dict[str, str]] = None, + tags: Optional[Dict[str, str]] = None, owner: str = "", + join_keys: Optional[List[str]] = None, ): """Creates an Entity object.""" - self.name = name - self.value_type = value_type - self.join_key = join_key if join_key else name - self.description = description - - if labels is not None: - self.tags = labels + if len(args) == 1: warnings.warn( ( - "The parameter 'labels' is being deprecated. Please use 'tags' instead. " - "Feast 0.20 and onwards will not support the parameter 'labels'." + "Entity name should be specified as a keyword argument instead of a positional arg." + "Feast 0.23+ will not support positional arguments to construct Entities" ), DeprecationWarning, ) - else: - self.tags = labels or tags or {} + if len(args) > 1: + raise ValueError( + "All arguments to construct an entity should be specified as keyword arguments only" + ) + + self.name = args[0] if len(args) > 0 else name + if not self.name: + raise ValueError("Name needs to be specified") + + self.value_type = value_type + + self.join_keys = join_keys or [] + if join_keys and len(join_keys) > 1: + raise ValueError( + "An entity may only have single join key. " + "Multiple join keys will be supported in the future." + ) + if join_keys and len(join_keys) == 1: + self.join_key = join_keys[0] + else: + self.join_key = join_key if join_key else self.name + self.description = description + self.tags = tags if tags is not None else {} self.owner = owner self.created_timestamp = None self.last_updated_timestamp = None diff --git a/sdk/python/feast/errors.py b/sdk/python/feast/errors.py index 942d3e9c166..e680337d98c 100644 --- a/sdk/python/feast/errors.py +++ b/sdk/python/feast/errors.py @@ -1,4 +1,4 @@ -from typing import List, Set +from typing import Any, List, Set from colorama import Fore, Style @@ -345,3 +345,10 @@ def __init__(self, e: KeyError): class SnowflakeQueryUnknownError(Exception): def __init__(self, query: str): super().__init__(f"Snowflake query failed: {query}") + + +class InvalidFeaturesParameterType(Exception): + def __init__(self, features: Any): + super().__init__( + f"Invalid `features` parameter type {type(features)}. Expected one of List[str] and FeatureService." + ) diff --git a/sdk/python/feast/feature.py b/sdk/python/feast/feature.py index b37e0f562b2..57f75c90d76 100644 --- a/sdk/python/feast/feature.py +++ b/sdk/python/feast/feature.py @@ -15,7 +15,7 @@ from typing import Dict, Optional from feast.protos.feast.core.Feature_pb2 import FeatureSpecV2 as FeatureSpecProto -from feast.protos.feast.types import Value_pb2 as ValueTypeProto +from feast.protos.feast.types.Value_pb2 import ValueType as ValueTypeProto from feast.value_type import ValueType @@ -88,7 +88,7 @@ def to_proto(self) -> FeatureSpecProto: Returns: A FeatureSpecProto protobuf. """ - value_type = ValueTypeProto.ValueType.Enum.Value(self.dtype.name) + value_type = ValueTypeProto.Enum.Value(self.dtype.name) return FeatureSpecProto( name=self.name, value_type=value_type, labels=self.labels, diff --git a/sdk/python/feast/feature_server.py b/sdk/python/feast/feature_server.py index 585075843a6..20fcd410c20 100644 --- a/sdk/python/feast/feature_server.py +++ b/sdk/python/feast/feature_server.py @@ -1,16 +1,33 @@ +import json import traceback +import warnings +import pandas as pd import uvicorn from fastapi import FastAPI, HTTPException, Request from fastapi.logger import logger from fastapi.params import Depends from google.protobuf.json_format import MessageToDict, Parse +from pydantic import BaseModel import feast from feast import proto_json from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesRequest +# TODO: deprecate this in favor of push features +class WriteToFeatureStoreRequest(BaseModel): + feature_view_name: str + df: dict + allow_registry_cache: bool = True + + +class PushFeaturesRequest(BaseModel): + push_source_name: str + df: dict + allow_registry_cache: bool = True + + def get_app(store: "feast.FeatureStore"): proto_json.patch() @@ -42,8 +59,8 @@ def get_online_features(body=Depends(get_body)): raise HTTPException(status_code=500, detail="Uneven number of columns") response_proto = store._get_online_features( - features, - request_proto.entities, + features=features, + entity_values=request_proto.entities, full_feature_names=full_feature_names, native_entity_values=False, ).proto @@ -58,6 +75,44 @@ def get_online_features(body=Depends(get_body)): # Raise HTTPException to return the error message to the client raise HTTPException(status_code=500, detail=str(e)) + @app.post("/push") + def push(body=Depends(get_body)): + try: + request = PushFeaturesRequest(**json.loads(body)) + df = pd.DataFrame(request.df) + store.push( + push_source_name=request.push_source_name, + df=df, + allow_registry_cache=request.allow_registry_cache, + ) + except Exception as e: + # Print the original exception on the server side + logger.exception(traceback.format_exc()) + # Raise HTTPException to return the error message to the client + raise HTTPException(status_code=500, detail=str(e)) + + @app.post("/write-to-online-store") + def write_to_online_store(body=Depends(get_body)): + warnings.warn( + "write_to_online_store is an experimental feature. " + "This API is unstable and it could be changed in the future. " + "We do not guarantee that future changes will maintain backward compatibility.", + RuntimeWarning, + ) + try: + request = WriteToFeatureStoreRequest(**json.loads(body)) + df = pd.DataFrame(request.df) + store.write_to_online_store( + feature_view_name=request.feature_view_name, + df=df, + allow_registry_cache=request.allow_registry_cache, + ) + except Exception as e: + # Print the original exception on the server side + logger.exception(traceback.format_exc()) + # Raise HTTPException to return the error message to the client + raise HTTPException(status_code=500, detail=str(e)) + return app diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index 89e4df1d5fc..33d297f3ca8 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -19,6 +19,7 @@ from datetime import datetime from pathlib import Path from typing import ( + TYPE_CHECKING, Any, Dict, Iterable, @@ -42,7 +43,6 @@ from feast.data_source import DataSource from feast.diff.infra_diff import InfraDiff, diff_infra_protos from feast.diff.registry_diff import RegistryDiff, apply_diff_to_registry, diff_between -from feast.dqm.profilers.ge_profiler import GEProfiler from feast.entity import Entity from feast.errors import ( EntityNotFoundException, @@ -82,7 +82,10 @@ from feast.repo_contents import RepoContents from feast.request_feature_view import RequestFeatureView from feast.saved_dataset import SavedDataset, SavedDatasetStorage -from feast.type_map import python_values_to_proto_values +from feast.type_map import ( + feast_value_type_to_python_type, + python_values_to_proto_values, +) from feast.usage import log_exceptions, log_exceptions_and_usage, set_usage_attribute from feast.value_type import ValueType from feast.version import get_version @@ -90,6 +93,10 @@ warnings.simplefilter("once", DeprecationWarning) +if TYPE_CHECKING: + from feast.embedded_go.online_features_service import EmbeddedOnlineFeatureServer + + class FeatureStore: """ A FeatureStore object is used to define, create, and retrieve features. @@ -104,6 +111,7 @@ class FeatureStore: repo_path: Path _registry: Registry _provider: Provider + _go_server: Optional["EmbeddedOnlineFeatureServer"] @log_exceptions def __init__( @@ -130,6 +138,7 @@ def __init__( self._registry = Registry(registry_config, repo_path=self.repo_path) self._registry._initialize_registry() self._provider = get_provider(self.config, self.repo_path) + self._go_server = None @log_exceptions def version(self) -> str: @@ -157,13 +166,13 @@ def refresh_registry(self): Explicitly calling this method allows for direct control of the state of the registry cache. Every time this method is called the complete registry state will be retrieved from the remote registry store backend (e.g., GCS, S3), and the cache timer will be reset. If refresh_registry() is run before get_online_features() - is called, then get_online_feature() will use the cached registry instead of retrieving (and caching) the + is called, then get_online_features() will use the cached registry instead of retrieving (and caching) the registry itself. Additionally, the TTL for the registry cache can be set to infinity (by setting it to 0), which means that refresh_registry() will become the only way to update the cached registry. If the TTL is set to a value greater than 0, then once the cache becomes stale (more time than the TTL has passed), a new cache will be - downloaded synchronously, which may increase latencies if the triggering method is get_online_features() + downloaded synchronously, which may increase latencies if the triggering method is get_online_features(). """ registry_config = self.config.get_registry_config() registry = Registry(registry_config, repo_path=self.repo_path) @@ -276,12 +285,13 @@ def list_data_sources(self, allow_cache: bool = False) -> List[DataSource]: return self._registry.list_data_sources(self.project, allow_cache=allow_cache) @log_exceptions_and_usage - def get_entity(self, name: str) -> Entity: + def get_entity(self, name: str, allow_registry_cache: bool = False) -> Entity: """ Retrieves an entity. Args: name: Name of entity. + allow_registry_cache: (Optional) Whether to allow returning this entity from a cached registry Returns: The specified entity. @@ -289,7 +299,9 @@ def get_entity(self, name: str) -> Entity: Raises: EntityNotFoundException: The entity could not be found. """ - return self._registry.get_entity(name, self.project) + return self._registry.get_entity( + name, self.project, allow_cache=allow_registry_cache + ) @log_exceptions_and_usage def get_feature_service( @@ -311,12 +323,15 @@ def get_feature_service( return self._registry.get_feature_service(name, self.project, allow_cache) @log_exceptions_and_usage - def get_feature_view(self, name: str) -> FeatureView: + def get_feature_view( + self, name: str, allow_registry_cache: bool = False + ) -> FeatureView: """ Retrieves a feature view. Args: name: Name of feature view. + allow_registry_cache: (Optional) Whether to allow returning this entity from a cached registry Returns: The specified feature view. @@ -324,12 +339,17 @@ def get_feature_view(self, name: str) -> FeatureView: Raises: FeatureViewNotFoundException: The feature view could not be found. """ - return self._get_feature_view(name) + return self._get_feature_view(name, allow_registry_cache=allow_registry_cache) def _get_feature_view( - self, name: str, hide_dummy_entity: bool = True + self, + name: str, + hide_dummy_entity: bool = True, + allow_registry_cache: bool = False, ) -> FeatureView: - feature_view = self._registry.get_feature_view(name, self.project) + feature_view = self._registry.get_feature_view( + name, self.project, allow_cache=allow_registry_cache + ) if hide_dummy_entity and feature_view.entities[0] == DUMMY_ENTITY_NAME: feature_view.entities = [] return feature_view @@ -382,14 +402,14 @@ def delete_feature_view(self, name: str): @log_exceptions_and_usage def delete_feature_service(self, name: str): """ - Deletes a feature service. + Deletes a feature service. - Args: - name: Name of feature service. + Args: + name: Name of feature service. - Raises: - FeatureServiceNotFoundException: The feature view could not be found. - """ + Raises: + FeatureServiceNotFoundException: The feature view could not be found. + """ return self._registry.delete_feature_service(name, self.project) def _get_features( @@ -486,13 +506,10 @@ def _plan( The plan method dry-runs registering one or more definitions (e.g., Entity, FeatureView), and produces a list of all the changes the that would be introduced in the feature repo. The changes computed by the plan - command are for informational purpose, and are not actually applied to the registry. + command are for informational purposes, and are not actually applied to the registry. Args: - objects: A single object, or a list of objects that are intended to be registered with the Feature Store. - objects_to_delete: A list of objects to be deleted from the registry. - partial: If True, apply will only handle the specified objects; if False, apply will also delete - all the objects in objects_to_delete. + desired_repo_contents: The desired repo state. Raises: ValueError: The 'objects' parameter could not be parsed properly. @@ -507,7 +524,7 @@ def _plan( >>> driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id") >>> driver_hourly_stats = FileSource( ... path="feature_repo/data/driver_stats.parquet", - ... event_timestamp_column="event_timestamp", + ... timestamp_field="event_timestamp", ... created_timestamp_column="created", ... ) >>> driver_hourly_stats_view = FeatureView( @@ -557,7 +574,7 @@ def _plan( new_infra_proto = new_infra.to_proto() infra_diff = diff_infra_protos(current_infra_proto, new_infra_proto) - return (registry_diff, infra_diff, new_infra) + return registry_diff, infra_diff, new_infra @log_exceptions_and_usage def _apply_diffs( @@ -618,7 +635,7 @@ def apply( >>> driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id") >>> driver_hourly_stats = FileSource( ... path="feature_repo/data/driver_stats.parquet", - ... event_timestamp_column="event_timestamp", + ... timestamp_field="event_timestamp", ... created_timestamp_column="created", ... ) >>> driver_hourly_stats_view = FeatureView( @@ -645,16 +662,30 @@ def apply( ] odfvs_to_update = [ob for ob in objects if isinstance(ob, OnDemandFeatureView)] services_to_update = [ob for ob in objects if isinstance(ob, FeatureService)] - data_sources_to_update = [ob for ob in objects if isinstance(ob, DataSource)] - - if len(entities_to_update) + len(views_to_update) + len( - request_views_to_update - ) + len(odfvs_to_update) + len(services_to_update) + len( - data_sources_to_update - ) != len( - objects - ): - raise ValueError("Unknown object type provided as part of apply() call") + data_sources_set_to_update = { + ob for ob in objects if isinstance(ob, DataSource) + } + + for fv in views_to_update: + data_sources_set_to_update.add(fv.batch_source) + if fv.stream_source: + data_sources_set_to_update.add(fv.stream_source) + + if request_views_to_update: + warnings.warn( + "Request feature view is deprecated. " + "Please use request data source instead", + DeprecationWarning, + ) + + for rfv in request_views_to_update: + data_sources_set_to_update.add(rfv.request_data_source) + + for odfv in odfvs_to_update: + for v in odfv.source_request_sources.values(): + data_sources_set_to_update.add(v) + + data_sources_to_update = list(data_sources_set_to_update) # Validate all feature views and make inferences. self._validate_all_feature_views( @@ -738,6 +769,11 @@ def apply( self._registry.commit() + # go server needs to be reloaded to apply new configuration. + # we're stopping it here + # new server will be instantiated on the next online request + self._teardown_go_server() + @log_exceptions_and_usage def teardown(self): """Tears down all local and cloud resources for the feature store.""" @@ -750,6 +786,7 @@ def teardown(self): self._get_provider().teardown_infra(self.project, tables, entities) self._registry.teardown() + self._teardown_go_server() @log_exceptions_and_usage def get_historical_features( @@ -776,12 +813,12 @@ def get_historical_features( columns (e.g., customer_id, driver_id) on which features need to be joined, as well as a event_timestamp column used to ensure point-in-time correctness. Either a Pandas DataFrame can be provided or a string SQL query. The query must be of a format supported by the configured offline store (e.g., BigQuery) - features: A list of features, that should be retrieved from the offline store. - Either a list of string feature references can be provided or a FeatureService object. - Feature references are of the format "feature_view:feature", e.g., "customer_fv:daily_transactions". - full_feature_names: A boolean that provides the option to add the feature view prefixes to the feature names, - changing them from the format "feature" to "feature_view__feature" (e.g., "daily_transactions" changes to - "customer_fv__daily_transactions"). By default, this value is set to False. + features: The list of features that should be retrieved from the offline store. These features can be + specified either as a list of string feature references or as a feature service. String feature + references must have format "feature_view:feature", e.g. "customer_fv:daily_transactions". + full_feature_names: If True, feature names will be prefixed with the corresponding feature view name, + changing them from the format "feature" to "feature_view__feature" (e.g. "daily_transactions" + changes to "customer_fv__daily_transactions"). Returns: RetrievalJob which can be used to materialize the results. @@ -814,7 +851,6 @@ def get_historical_features( ... ) >>> feature_data = retrieval_job.to_df() """ - _feature_refs = self._get_features(features) ( all_feature_views, @@ -822,6 +858,13 @@ def get_historical_features( all_on_demand_feature_views, ) = self._get_feature_views_to_use(features) + if all_request_feature_views: + warnings.warn( + "Request feature view is deprecated. " + "Please use request data source instead", + DeprecationWarning, + ) + # TODO(achal): _group_feature_refs returns the on demand feature views, but it's no passed into the provider. # This is a weird interface quirk - we should revisit the `get_historical_features` to # pass in the on demand feature views as well. @@ -881,20 +924,19 @@ def create_saved_dataset( storage: SavedDatasetStorage, tags: Optional[Dict[str, str]] = None, feature_service: Optional[FeatureService] = None, - profiler: Optional[GEProfiler] = None, ) -> SavedDataset: """ - Execute provided retrieval job and persist its outcome in given storage. - Storage type (eg, BigQuery or Redshift) must be the same as globally configured offline store. - After data successfully persisted saved dataset object with dataset metadata is committed to the registry. - Name for the saved dataset should be unique within project, since it's possible to overwrite previously stored dataset - with the same name. + Execute provided retrieval job and persist its outcome in given storage. + Storage type (eg, BigQuery or Redshift) must be the same as globally configured offline store. + After data successfully persisted saved dataset object with dataset metadata is committed to the registry. + Name for the saved dataset should be unique within project, since it's possible to overwrite previously stored dataset + with the same name. - Returns: - SavedDataset object with attached RetrievalJob + Returns: + SavedDataset object with attached RetrievalJob - Raises: - ValueError if given retrieval job doesn't have metadata + Raises: + ValueError if given retrieval job doesn't have metadata """ warnings.warn( "Saving dataset is an experimental feature. " @@ -1143,6 +1185,31 @@ def tqdm_builder(length): feature_view, self.project, start_date, end_date, ) + @log_exceptions_and_usage + def push(self, push_source_name: str, df: pd.DataFrame): + """ + Push features to a push source. This updates all the feature views that have the push source as stream source. + Args: + push_source_name: The name of the push source we want to push data to. + df: the data being pushed. + """ + from feast.data_source import PushSource + + all_fvs = self.list_feature_views(allow_cache=True) + + fvs_with_push_sources = { + fv + for fv in all_fvs + if ( + fv.stream_source is not None + and isinstance(fv.stream_source, PushSource) + and fv.stream_source.name == push_source_name + ) + } + + for fv in fvs_with_push_sources: + self.write_to_online_store(fv.name, df, allow_registry_cache=True) + @log_exceptions_and_usage def write_to_online_store( self, @@ -1153,18 +1220,15 @@ def write_to_online_store( """ ingests data directly into the Online store """ - if not flags_helper.enable_direct_ingestion_to_online_store(self.config): - raise ExperimentalFeatureNotEnabled( - flags.FLAG_DIRECT_INGEST_TO_ONLINE_STORE - ) - # TODO: restrict this to work with online StreamFeatureViews and validate the FeatureView type - feature_view = self._registry.get_feature_view( - feature_view_name, self.project, allow_cache=allow_registry_cache + feature_view = self.get_feature_view( + feature_view_name, allow_registry_cache=allow_registry_cache ) entities = [] for entity_name in feature_view.entities: - entities.append(self._registry.get_entity(entity_name, self.project)) + entities.append( + self.get_entity(entity_name, allow_registry_cache=allow_registry_cache) + ) provider = self._get_provider() provider.ingest_df(feature_view, entities, df) @@ -1187,12 +1251,13 @@ def get_online_features( infinity (cache forever). Args: - features: List of feature references that will be returned for each entity. - Each feature reference should have the following format: - "feature_view:feature" where "feature_view" & "feature" refer to - the Feature and FeatureView names respectively. - Only the feature name is required. + features: The list of features that should be retrieved from the online store. These features can be + specified either as a list of string feature references or as a feature service. String feature + references must have format "feature_view:feature", e.g. "customer_fv:daily_transactions". entity_rows: A list of dictionaries where each key-value is an entity-name, entity-value pair. + full_feature_names: If True, feature names will be prefixed with the corresponding feature view name, + changing them from the format "feature" to "feature_view__feature" (e.g. "daily_transactions" + changes to "customer_fv__daily_transactions"). Returns: OnlineResponse containing the feature data in records. @@ -1201,8 +1266,7 @@ def get_online_features( Exception: No entity with the specified name exists. Examples: - Materialize all features into the online store over the interval - from 3 hours ago to 10 minutes ago, and then retrieve these online features. + Retrieve online features from an online store. >>> from feast import FeatureStore, RepoConfig >>> fs = FeatureStore(repo_path="feature_repo") @@ -1240,6 +1304,49 @@ def _get_online_features( full_feature_names: bool = False, native_entity_values: bool = True, ): + # Extract Sequence from RepeatedValue Protobuf. + entity_value_lists: Dict[str, Union[List[Any], List[Value]]] = { + k: list(v) if isinstance(v, Sequence) else list(v.val) + for k, v in entity_values.items() + } + + # If Go feature server is enabled, send request to it instead of going through regular Python logic + if self.config.go_feature_retrieval: + from feast.embedded_go.online_features_service import ( + EmbeddedOnlineFeatureServer, + ) + + # Lazily start the go server on the first request + if self._go_server is None: + self._go_server = EmbeddedOnlineFeatureServer( + str(self.repo_path.absolute()), self.config, self + ) + + entity_native_values: Dict[str, List[Any]] + if not native_entity_values: + # Convert proto types to native types since Go feature server currently + # only handles native types. + # TODO(felixwang9817): Remove this logic once native types are supported. + entity_native_values = { + k: [ + feast_value_type_to_python_type(proto_value) + for proto_value in v + ] + for k, v in entity_value_lists.items() + } + else: + entity_native_values = entity_value_lists + + return self._go_server.get_online_features( + features_refs=features if isinstance(features, list) else [], + feature_service=features + if isinstance(features, FeatureService) + else None, + entities=entity_native_values, + request_data={}, # TODO: add request data parameter to public API + full_feature_names=full_feature_names, + ) + _feature_refs = self._get_features(features, allow_cache=True) ( requested_feature_views, @@ -1249,15 +1356,18 @@ def _get_online_features( features=features, allow_cache=True, hide_dummy_entity=False ) - entity_name_to_join_key_map, entity_type_map = self._get_entity_maps( - requested_feature_views - ) + if requested_request_feature_views: + warnings.warn( + "Request feature view is deprecated. " + "Please use request data source instead", + DeprecationWarning, + ) - # Extract Sequence from RepeatedValue Protobuf. - entity_value_lists: Dict[str, Union[List[Any], List[Value]]] = { - k: list(v) if isinstance(v, Sequence) else list(v.val) - for k, v in entity_values.items() - } + ( + entity_name_to_join_key_map, + entity_type_map, + join_keys_set, + ) = self._get_entity_maps(requested_feature_views) entity_proto_values: Dict[str, List[Value]] if native_entity_values: @@ -1305,22 +1415,32 @@ def _get_online_features( join_key_values: Dict[str, List[Value]] = {} request_data_features: Dict[str, List[Value]] = {} # Entity rows may be either entities or request data. - for entity_name, values in entity_proto_values.items(): + for join_key_or_entity_name, values in entity_proto_values.items(): # Found request data if ( - entity_name in needed_request_data - or entity_name in needed_request_fv_features + join_key_or_entity_name in needed_request_data + or join_key_or_entity_name in needed_request_fv_features ): - if entity_name in needed_request_fv_features: + if join_key_or_entity_name in needed_request_fv_features: # If the data was requested as a feature then # make sure it appears in the result. - requested_result_row_names.add(entity_name) - request_data_features[entity_name] = values + requested_result_row_names.add(join_key_or_entity_name) + request_data_features[join_key_or_entity_name] = values else: - try: - join_key = entity_name_to_join_key_map[entity_name] - except KeyError: - raise EntityNotFoundException(entity_name, self.project) + if join_key_or_entity_name in join_keys_set: + join_key = join_key_or_entity_name + else: + try: + join_key = entity_name_to_join_key_map[join_key_or_entity_name] + except KeyError: + raise EntityNotFoundException( + join_key_or_entity_name, self.project + ) + else: + warnings.warn( + "Using entity name is deprecated. Use join_key instead." + ) + # All join keys should be returned in the result. requested_result_row_names.add(join_key) join_key_values[join_key] = values @@ -1330,9 +1450,7 @@ def _get_online_features( ) # Populate online features response proto with join keys and request data features - online_features_response = GetOnlineFeaturesResponse( - results=[GetOnlineFeaturesResponse.FeatureVector() for _ in range(num_rows)] - ) + online_features_response = GetOnlineFeaturesResponse(results=[]) self._populate_result_rows_from_columnar( online_features_response=online_features_response, data=dict(**join_key_values, **request_data_features), @@ -1405,7 +1523,9 @@ def _get_columnar_entity_values( return res return cast(Dict[str, List[Any]], columnar) - def _get_entity_maps(self, feature_views): + def _get_entity_maps( + self, feature_views + ) -> Tuple[Dict[str, str], Dict[str, ValueType], Set[str]]: entities = self._list_entities(allow_cache=True, hide_dummy_entity=False) entity_name_to_join_key_map: Dict[str, str] = {} entity_type_map: Dict[str, ValueType] = {} @@ -1427,7 +1547,11 @@ def _get_entity_maps(self, feature_views): ) entity_name_to_join_key_map[entity_name] = join_key entity_type_map[join_key] = entity.value_type - return entity_name_to_join_key_map, entity_type_map + return ( + entity_name_to_join_key_map, + entity_type_map, + set(entity_name_to_join_key_map.values()), + ) @staticmethod def _get_table_entity_values( @@ -1460,14 +1584,14 @@ def _populate_result_rows_from_columnar( timestamp = Timestamp() # Only initialize this timestamp once. # Add more values to the existing result rows for feature_name, feature_values in data.items(): - online_features_response.metadata.feature_names.val.append(feature_name) - - for row_idx, proto_value in enumerate(feature_values): - result_row = online_features_response.results[row_idx] - result_row.values.append(proto_value) - result_row.statuses.append(FieldStatus.PRESENT) - result_row.event_timestamps.append(timestamp) + online_features_response.results.append( + GetOnlineFeaturesResponse.FeatureVector( + values=feature_values, + statuses=[FieldStatus.PRESENT] * len(feature_values), + event_timestamps=[timestamp] * len(feature_values), + ) + ) @staticmethod def get_needed_request_data( @@ -1510,11 +1634,11 @@ def _get_unique_entities( join_key_values: Dict[str, List[Value]], entity_name_to_join_key_map: Dict[str, str], ) -> Tuple[Tuple[Dict[str, Value], ...], Tuple[List[int], ...]]: - """ Return the set of unique composite Entities for a Feature View and the indexes at which they appear. + """Return the set of unique composite Entities for a Feature View and the indexes at which they appear. - This method allows us to query the OnlineStore for data we need only once - rather than requesting and processing data for the same combination of - Entities multiple times. + This method allows us to query the OnlineStore for data we need only once + rather than requesting and processing data for the same combination of + Entities multiple times. """ # Get the correct set of entity values with the correct join keys. table_entity_values = self._get_table_entity_values( @@ -1550,14 +1674,14 @@ def _read_from_online_store( requested_features: List[str], table: FeatureView, ) -> List[Tuple[List[Timestamp], List["FieldStatus.ValueType"], List[Value]]]: - """ Read and process data from the OnlineStore for a given FeatureView. + """Read and process data from the OnlineStore for a given FeatureView. - This method guarentees that the order of the data in each element of the - List returned is the same as the order of `requested_features`. + This method guarantees that the order of the data in each element of the + List returned is the same as the order of `requested_features`. - This method assumes that `provider.online_read` returns data for each - combination of Entities in `entity_rows` in the same order as they - are provided. + This method assumes that `provider.online_read` returns data for each + combination of Entities in `entity_rows` in the same order as they + are provided. """ # Instantiate one EntityKeyProto per Entity. entity_key_protos = [ @@ -1580,6 +1704,7 @@ def _read_from_online_store( for read_row in read_rows: row_ts_proto = Timestamp() row_ts, feature_data = read_row + # TODO (Ly): reuse whatever timestamp if row_ts is None? if row_ts is not None: row_ts_proto.FromDatetime(row_ts) event_timestamps = [row_ts_proto] * len(requested_features) @@ -1607,29 +1732,29 @@ def _populate_response_from_feature_data( Iterable[Timestamp], Iterable["FieldStatus.ValueType"], Iterable[Value] ] ], - indexes: Iterable[Iterable[int]], + indexes: Iterable[List[int]], online_features_response: GetOnlineFeaturesResponse, full_feature_names: bool, requested_features: Iterable[str], table: FeatureView, ): - """ Populate the GetOnlineFeaturesReponse with feature data. - - This method assumes that `_read_from_online_store` returns data for each - combination of Entities in `entity_rows` in the same order as they - are provided. - - Args: - feature_data: A list of data in Protobuf form which was retrieved from the OnlineStore. - indexes: A list of indexes which should be the same length as `feature_data`. Each list - of indexes corresponds to a set of result rows in `online_features_response`. - online_features_response: The object to populate. - full_feature_names: A boolean that provides the option to add the feature view prefixes to the feature names, - changing them from the format "feature" to "feature_view__feature" (e.g., "daily_transactions" changes to - "customer_fv__daily_transactions"). - requested_features: The names of the features in `feature_data`. This should be ordered in the same way as the - data in `feature_data`. - table: The FeatureView that `feature_data` was retrieved from. + """Populate the GetOnlineFeaturesResponse with feature data. + + This method assumes that `_read_from_online_store` returns data for each + combination of Entities in `entity_rows` in the same order as they + are provided. + + Args: + feature_data: A list of data in Protobuf form which was retrieved from the OnlineStore. + indexes: A list of indexes which should be the same length as `feature_data`. Each list + of indexes corresponds to a set of result rows in `online_features_response`. + online_features_response: The object to populate. + full_feature_names: A boolean that provides the option to add the feature view prefixes to the feature names, + changing them from the format "feature" to "feature_view__feature" (e.g., "daily_transactions" changes to + "customer_fv__daily_transactions"). + requested_features: The names of the features in `feature_data`. This should be ordered in the same way as the + data in `feature_data`. + table: The FeatureView that `feature_data` was retrieved from. """ # Add the feature names to the response. requested_feature_refs = [ @@ -1642,15 +1767,21 @@ def _populate_response_from_feature_data( requested_feature_refs ) + timestamps, statuses, values = zip(*feature_data) + # Populate the result with data fetched from the OnlineStore - # which is guarenteed to be aligned with `requested_features`. - for feature_row, dest_idxs in zip(feature_data, indexes): - event_timestamps, statuses, values = feature_row - for dest_idx in dest_idxs: - result_row = online_features_response.results[dest_idx] - result_row.event_timestamps.extend(event_timestamps) - result_row.statuses.extend(statuses) - result_row.values.extend(values) + # which is guaranteed to be aligned with `requested_features`. + for ( + feature_idx, + (timestamp_vector, statuses_vector, values_vector), + ) in enumerate(zip(zip(*timestamps), zip(*statuses), zip(*values))): + online_features_response.results.append( + GetOnlineFeaturesResponse.FeatureVector( + values=apply_list_mapping(values_vector, indexes), + statuses=apply_list_mapping(statuses_vector, indexes), + event_timestamps=apply_list_mapping(timestamp_vector, indexes), + ) + ) @staticmethod def _augment_response_with_on_demand_transforms( @@ -1672,7 +1803,6 @@ def _augment_response_with_on_demand_transforms( full_feature_names: A boolean that provides the option to add the feature view prefixes to the feature names, changing them from the format "feature" to "feature_view__feature" (e.g., "daily_transactions" changes to "customer_fv__daily_transactions"). - result_rows: List of result rows to be augmented with on demand feature values. """ requested_odfv_map = { odfv.name: odfv for odfv in requested_on_demand_feature_views @@ -1713,13 +1843,14 @@ def _augment_response_with_on_demand_transforms( odfv_result_names |= set(selected_subset) online_features_response.metadata.feature_names.val.extend(selected_subset) - - for row_idx in range(len(online_features_response.results)): - result_row = online_features_response.results[row_idx] - for feature_idx, transformed_feature in enumerate(selected_subset): - result_row.values.append(proto_values[feature_idx][row_idx]) - result_row.statuses.append(FieldStatus.PRESENT) - result_row.event_timestamps.append(Timestamp()) + for feature_idx in range(len(selected_subset)): + online_features_response.results.append( + GetOnlineFeaturesResponse.FeatureVector( + values=proto_values[feature_idx], + statuses=[FieldStatus.PRESENT] * len(proto_values[feature_idx]), + event_timestamps=[Timestamp()] * len(proto_values[feature_idx]), + ) + ) @staticmethod def _drop_unneeded_columns( @@ -1746,13 +1877,7 @@ def _drop_unneeded_columns( for idx in reversed(unneeded_feature_indices): del online_features_response.metadata.feature_names.val[idx] - - for row_idx in range(len(online_features_response.results)): - result_row = online_features_response.results[row_idx] - for idx in reversed(unneeded_feature_indices): - del result_row.values[idx] - del result_row.statuses[idx] - del result_row.event_timestamps[idx] + del online_features_response.results[idx] def _get_feature_views_to_use( self, @@ -1798,7 +1923,7 @@ def _get_feature_views_to_use( odfv = od_fvs[fv_name].with_projection(copy.copy(projection)) od_fvs_to_use.append(odfv) # Let's make sure to include an FVs which the ODFV requires Features from. - for projection in odfv.input_feature_view_projections.values(): + for projection in odfv.source_feature_view_projections.values(): fv = fvs[projection.name].with_projection(copy.copy(projection)) if fv not in fvs_to_use: fvs_to_use.append(fv) @@ -1838,6 +1963,9 @@ def serve_transformations(self, port: int) -> None: transformation_server.start_server(self, port) + def _teardown_go_server(self): + self._go_server = None + def _validate_entity_values(join_key_values: Dict[str, List[Value]]): set_of_row_lengths = {len(v) for v in join_key_values.values()} @@ -1847,6 +1975,18 @@ def _validate_entity_values(join_key_values: Dict[str, List[Value]]): def _validate_feature_refs(feature_refs: List[str], full_feature_names: bool = False): + """ + Validates that there are no collisions among the feature references. + + Args: + feature_refs: List of feature references to validate. Feature references must have format + "feature_view:feature", e.g. "customer_fv:daily_transactions". + full_feature_names: If True, the full feature references are compared for collisions; if False, + only the feature names are compared. + + Raises: + FeatureNameCollisionError: There is a collision among the feature references. + """ collided_feature_refs = [] if full_feature_names: @@ -1854,9 +1994,7 @@ def _validate_feature_refs(feature_refs: List[str], full_feature_names: bool = F ref for ref, occurrences in Counter(feature_refs).items() if occurrences > 1 ] else: - feature_names = [ - ref.split(":")[1] if ":" in ref else ref for ref in feature_refs - ] + feature_names = [ref.split(":")[1] for ref in feature_refs] collided_feature_names = [ ref for ref, occurrences in Counter(feature_names).items() @@ -1883,7 +2021,7 @@ def _group_feature_refs( List[Tuple[RequestFeatureView, List[str]]], Set[str], ]: - """ Get list of feature views and corresponding feature names based on feature references""" + """Get list of feature views and corresponding feature names based on feature references""" # view name to view proto view_index = {view.projection.name_to_use(): view for view in all_feature_views} @@ -1915,7 +2053,7 @@ def _group_feature_refs( # Let's also add in any FV Feature dependencies here. for input_fv_projection in on_demand_view_index[ view_name - ].input_feature_view_projections.values(): + ].source_feature_view_projections.values(): for input_feat in input_fv_projection.features: views_features[input_fv_projection.name].add(input_feat.name) elif view_name in request_view_index: @@ -1956,7 +2094,7 @@ def _print_materialization_log( def _validate_feature_views(feature_views: List[BaseFeatureView]): - """ Verify feature views have case-insensitively unique names""" + """Verify feature views have case-insensitively unique names""" fv_names = set() for fv in feature_views: case_insensitive_fv_name = fv.name.lower() @@ -1971,15 +2109,30 @@ def _validate_feature_views(feature_views: List[BaseFeatureView]): def _validate_data_sources(data_sources: List[DataSource]): - """ Verify data sources have case-insensitively unique names""" + """Verify data sources have case-insensitively unique names""" ds_names = set() - for fv in data_sources: - case_insensitive_ds_name = fv.name.lower() + for ds in data_sources: + case_insensitive_ds_name = ds.name.lower() if case_insensitive_ds_name in ds_names: - raise ValueError( - f"More than one data source with name {case_insensitive_ds_name} found. " - f"Please ensure that all data source names are case-insensitively unique. " - f"It may be necessary to ignore certain files in your feature repository by using a .feastignore file." - ) + if case_insensitive_ds_name.strip(): + warnings.warn( + f"More than one data source with name {case_insensitive_ds_name} found. " + f"Please ensure that all data source names are case-insensitively unique. " + f"It may be necessary to ignore certain files in your feature repository by using a .feastignore " + f"file. Starting in Feast 0.21, unique names (perhaps inferred from the table name) will be " + f"required in data sources to encourage data source discovery" + ) else: ds_names.add(case_insensitive_ds_name) + + +def apply_list_mapping( + lst: Iterable[Any], mapping_indexes: Iterable[List[int]] +) -> Iterable[Any]: + output_len = sum(len(item) for item in mapping_indexes) + output = [None] * output_len + for elem, destinations in zip(lst, mapping_indexes): + for idx in destinations: + output[idx] = elem + + return output diff --git a/sdk/python/feast/feature_view.py b/sdk/python/feast/feature_view.py index 2c1d0675d4a..7d29a4b69bb 100644 --- a/sdk/python/feast/feature_view.py +++ b/sdk/python/feast/feature_view.py @@ -20,10 +20,11 @@ from feast import utils from feast.base_feature_view import BaseFeatureView -from feast.data_source import DataSource +from feast.data_source import DataSource, KafkaSource, KinesisSource, PushSource from feast.entity import Entity from feast.feature import Feature from feast.feature_view_projection import FeatureViewProjection +from feast.field import Field from feast.protos.feast.core.FeatureView_pb2 import FeatureView as FeatureViewProto from feast.protos.feast.core.FeatureView_pb2 import ( FeatureViewMeta as FeatureViewMetaProto, @@ -50,91 +51,225 @@ class FeatureView(BaseFeatureView): """ - A FeatureView defines a logical grouping of serveable features. + A FeatureView defines a logical group of features. - Args: - name: Name of the group of features. - entities: The entities to which this group of features is associated. + Attributes: + name: The unique name of the feature view. + entities: The list of entities with which this group of features is associated. ttl: The amount of time this group of features lives. A ttl of 0 indicates that this group of features lives forever. Note that large ttl's or a ttl of 0 can result in extremely computationally intensive queries. - input: The source of data where this group of features is stored. batch_source (optional): The batch source of data where this group of features - is stored. + is stored. This is optional ONLY if a push source is specified as the + stream_source, since push sources contain their own batch sources. This is deprecated in favor of `source`. stream_source (optional): The stream source of data where this group of features - is stored. - features (optional): The set of features defined as part of this FeatureView. - tags (optional): A dictionary of key-value pairs used for organizing - FeatureViews. + is stored. This is deprecated in favor of `source`. + schema: The schema of the feature view, including feature, timestamp, and entity + columns. + features: The list of features defined as part of this feature view. Each + feature should also be included in the schema. + online: A boolean indicating whether online retrieval is enabled for this feature + view. + description: A human-readable description. + tags: A dictionary of key-value pairs to store arbitrary metadata. + owner: The owner of the feature view, typically the email of the primary + maintainer. + source (optional): The source of data for this group of features. May be a stream source, or a batch source. + If a stream source, the source should contain a batch_source for backfills & batch materialization. """ + name: str entities: List[str] - tags: Optional[Dict[str, str]] - ttl: timedelta - online: bool - input: DataSource + ttl: Optional[timedelta] batch_source: DataSource stream_source: Optional[DataSource] + schema: List[Field] + features: List[Field] + online: bool + description: str + tags: Dict[str, str] + owner: str materialization_intervals: List[Tuple[datetime, datetime]] + source: Optional[DataSource] @log_exceptions def __init__( self, - name: str, - entities: List[str], - ttl: Union[Duration, timedelta], - input: Optional[DataSource] = None, + *args, + name: Optional[str] = None, + entities: Optional[Union[List[Entity], List[str]]] = None, + ttl: Optional[Union[Duration, timedelta]] = None, batch_source: Optional[DataSource] = None, stream_source: Optional[DataSource] = None, features: Optional[List[Feature]] = None, tags: Optional[Dict[str, str]] = None, online: bool = True, + description: str = "", + owner: str = "", + schema: Optional[List[Field]] = None, + source: Optional[DataSource] = None, ): """ Creates a FeatureView object. + Args: + name: The unique name of the feature view. + entities: The list of entities with which this group of features is associated. + ttl: The amount of time this group of features lives. A ttl of 0 indicates that + this group of features lives forever. Note that large ttl's or a ttl of 0 + can result in extremely computationally intensive queries. + batch_source: The batch source of data where this group of features is stored. + stream_source (optional): The stream source of data where this group of features + is stored. + features (deprecated): The list of features defined as part of this feature view. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + online (optional): A boolean indicating whether online retrieval is enabled for + this feature view. + description (optional): A human-readable description. + owner (optional): The owner of the feature view, typically the email of the + primary maintainer. + schema (optional): The schema of the feature view, including feature, timestamp, + and entity columns. + source (optional): The source of data for this group of features. May be a stream source, or a batch source. + If a stream source, the source should contain a batch_source for backfills & batch materialization. + Raises: ValueError: A field mapping conflicts with an Entity or a Feature. """ - if input is not None: + + positional_attributes = ["name, entities, ttl"] + + _name = name + _entities = entities + _ttl = ttl + + if args: warnings.warn( ( - "The argument 'input' is being deprecated. Please use 'batch_source' " - "instead. Feast 0.13 and onwards will not support the argument 'input'." + "feature view parameters should be specified as a keyword argument instead of a positional arg." + "Feast 0.23+ will not support positional arguments to construct feature views" ), DeprecationWarning, ) + if len(args) > len(positional_attributes): + raise ValueError( + f"Only {', '.join(positional_attributes)} are allowed as positional args when defining " + f"feature views, for backwards compatibility." + ) + if len(args) >= 1: + _name = args[0] + if len(args) >= 2: + _entities = args[1] + if len(args) >= 3: + _ttl = args[2] + + if not _name: + raise ValueError("feature view name needs to be specified") + + self.name = _name + self.entities = ( + [e.name if isinstance(e, Entity) else e for e in _entities] + if _entities + else [DUMMY_ENTITY_NAME] + ) - _input = input or batch_source - assert _input is not None + self._initialize_sources(_name, batch_source, stream_source, source) - _features = features or [] + if isinstance(_ttl, Duration): + self.ttl = timedelta(seconds=int(_ttl.seconds)) + warnings.warn( + ( + "The option to pass a Duration object to the ttl parameter is being deprecated. " + "Please pass a timedelta object instead. Feast 0.21 and onwards will not support " + "Duration objects." + ), + DeprecationWarning, + ) + elif isinstance(_ttl, timedelta) or _ttl is None: + self.ttl = _ttl + else: + raise ValueError(f"unknown value type specified for ttl {type(_ttl)}") - cols = [entity for entity in entities] + [feat.name for feat in _features] + if features is not None: + warnings.warn( + ( + "The `features` parameter is being deprecated in favor of the `schema` parameter. " + "Please switch from using `features` to `schema`. This will also requiring switching " + "feature definitions from using `Feature` to `Field`. Feast 0.21 and onwards will not " + "support the `features` parameter." + ), + DeprecationWarning, + ) + + _schema = schema or [] + if len(_schema) == 0 and features is not None: + _schema = [Field.from_feature(feature) for feature in features] + self.schema = _schema + + # TODO(felixwang9817): Infer which fields in the schema are features, timestamps, + # and entities. For right now we assume that all fields are features, since the + # current `features` parameter only accepts feature columns. + _features = _schema + + cols = [entity for entity in self.entities] + [ + field.name for field in _features + ] for col in cols: - if _input.field_mapping is not None and col in _input.field_mapping.keys(): + if ( + self.batch_source.field_mapping is not None + and col in self.batch_source.field_mapping.keys() + ): raise ValueError( - f"The field {col} is mapped to {_input.field_mapping[col]} for this data source. " - f"Please either remove this field mapping or use {_input.field_mapping[col]} as the " + f"The field {col} is mapped to {self.batch_source.field_mapping[col]} for this data source. " + f"Please either remove this field mapping or use {self.batch_source.field_mapping[col]} as the " f"Entity or Feature name." ) - super().__init__(name, _features) - self.entities = entities if entities else [DUMMY_ENTITY_NAME] - self.tags = tags if tags is not None else {} - - if isinstance(ttl, Duration): - self.ttl = timedelta(seconds=int(ttl.seconds)) - else: - self.ttl = ttl - + super().__init__( + name=_name, + features=_features, + description=description, + tags=tags, + owner=owner, + ) self.online = online - self.input = _input - self.batch_source = _input - self.stream_source = stream_source - self.materialization_intervals = [] + def _initialize_sources(self, name, batch_source, stream_source, source): + if source: + if ( + isinstance(source, PushSource) + or isinstance(source, KafkaSource) + or isinstance(source, KinesisSource) + ): + self.stream_source = source + if not source.batch_source: + raise ValueError( + f"A batch_source needs to be specified for stream source `{source.name}`" + ) + else: + self.batch_source = source.batch_source + else: + self.stream_source = stream_source + self.batch_source = source + else: + warnings.warn( + "batch_source and stream_source have been deprecated in favor of `source`." + "The deprecated fields will be removed in Feast 0.23.", + DeprecationWarning, + ) + if stream_source is not None and isinstance(stream_source, PushSource): + self.stream_source = stream_source + self.batch_source = stream_source.batch_source + else: + if batch_source is None: + raise ValueError( + f"A batch_source needs to be specified for feature view `{name}`" + ) + self.stream_source = stream_source + self.batch_source = batch_source + self.source = source + # Note: Python requires redefining hash in child classes that override __eq__ def __hash__(self): return super().__hash__() @@ -144,10 +279,9 @@ def __copy__(self): name=self.name, entities=self.entities, ttl=self.ttl, - input=self.input, - batch_source=self.batch_source, + source=self.batch_source, stream_source=self.stream_source, - features=self.features, + schema=self.schema, tags=self.tags, online=self.online, ) @@ -195,26 +329,9 @@ def ensure_valid(self): def proto_class(self) -> Type[FeatureViewProto]: return FeatureViewProto - def with_name(self, name: str): - """ - Renames this feature view by returning a copy of this feature view with an alias - set for the feature view name. This rename operation is only used as part of query - operations and will not modify the underlying FeatureView. - - Args: - name: Name to assign to the FeatureView copy. - - Returns: - A copy of this FeatureView with the name replaced with the 'name' input. - """ - cp = self.__copy__() - cp.projection.name_alias = name - - return cp - def with_join_key_map(self, join_key_map: Dict[str, str]): """ - Sets the join_key_map by returning a copy of this feature view with that field set. + Returns a copy of this feature view with the join key map set to the given map. This join_key mapping operation is only used as part of query operations and will not modify the underlying FeatureView. @@ -222,9 +339,6 @@ def with_join_key_map(self, join_key_map: Dict[str, str]): join_key_map: A map of join keys in which the left is the join_key that corresponds with the feature data and the right corresponds with the entity data. - Returns: - A copy of this FeatureView with the join_key_map replaced with the 'join_key_map' input. - Examples: Join a location feature data table to both the origin column and destination column of the entity data. @@ -250,40 +364,6 @@ def with_join_key_map(self, join_key_map: Dict[str, str]): return cp - def with_projection(self, feature_view_projection: FeatureViewProjection): - """ - Sets the feature view projection by returning a copy of this feature view - with its projection set to the given projection. A projection is an - object that stores the modifications to a feature view that is used during - query operations. - - Args: - feature_view_projection: The FeatureViewProjection object to link to this - OnDemandFeatureView. - - Returns: - A copy of this FeatureView with its projection replaced with the 'feature_view_projection' - argument. - """ - if feature_view_projection.name != self.name: - raise ValueError( - f"The projection for the {self.name} FeatureView cannot be applied because it differs in name. " - f"The projection is named {feature_view_projection.name} and the name indicates which " - "FeatureView the projection is for." - ) - - for feature in feature_view_projection.features: - if feature not in self.features: - raise ValueError( - f"The projection for {self.name} cannot be applied because it contains {feature.name} which the " - "FeatureView doesn't have." - ) - - cp = self.__copy__() - cp.projection = feature_view_projection - - return cp - def to_proto(self) -> FeatureViewProto: """ Converts a feature view object to its protobuf representation. @@ -318,8 +398,10 @@ def to_proto(self) -> FeatureViewProto: spec = FeatureViewSpecProto( name=self.name, entities=self.entities, - features=[feature.to_proto() for feature in self.features], + features=[field.to_proto() for field in self.schema], + description=self.description, tags=self.tags, + owner=self.owner, ttl=(ttl_duration if ttl_duration is not None else None), online=self.online, batch_source=batch_source_proto, @@ -348,23 +430,20 @@ def from_proto(cls, feature_view_proto: FeatureViewProto): feature_view = cls( name=feature_view_proto.spec.name, entities=[entity for entity in feature_view_proto.spec.entities], - features=[ - Feature( - name=feature.name, - dtype=ValueType(feature.value_type), - labels=dict(feature.labels), - ) - for feature in feature_view_proto.spec.features + schema=[ + Field.from_proto(field_proto) + for field_proto in feature_view_proto.spec.features ], + description=feature_view_proto.spec.description, tags=dict(feature_view_proto.spec.tags), + owner=feature_view_proto.spec.owner, online=feature_view_proto.spec.online, ttl=( - None - if feature_view_proto.spec.ttl.seconds == 0 - and feature_view_proto.spec.ttl.nanos == 0 - else feature_view_proto.spec.ttl + timedelta(days=0) + if feature_view_proto.spec.ttl.ToNanoseconds() == 0 + else feature_view_proto.spec.ttl.ToTimedelta() ), - batch_source=batch_source, + source=batch_source, stream_source=stream_source, ) diff --git a/sdk/python/feast/feature_view_projection.py b/sdk/python/feast/feature_view_projection.py index 04d923122c5..a8e0e8cfe52 100644 --- a/sdk/python/feast/feature_view_projection.py +++ b/sdk/python/feast/feature_view_projection.py @@ -1,12 +1,15 @@ -from typing import Dict, List, Optional +from typing import TYPE_CHECKING, Dict, List, Optional from attr import dataclass -from feast.feature import Feature +from feast.field import Field from feast.protos.feast.core.FeatureViewProjection_pb2 import ( FeatureViewProjection as FeatureViewProjectionProto, ) +if TYPE_CHECKING: + from feast.base_feature_view import BaseFeatureView + @dataclass class FeatureViewProjection: @@ -24,7 +27,7 @@ class FeatureViewProjection: name: str name_alias: Optional[str] - features: List[Feature] + features: List[Field] join_key_map: Dict[str, str] = {} def name_to_use(self): @@ -50,14 +53,14 @@ def from_proto(proto: FeatureViewProjectionProto): join_key_map=dict(proto.join_key_map), ) for feature_column in proto.feature_columns: - feature_view_projection.features.append(Feature.from_proto(feature_column)) + feature_view_projection.features.append(Field.from_proto(feature_column)) return feature_view_projection @staticmethod - def from_definition(feature_grouping): + def from_definition(base_feature_view: "BaseFeatureView"): return FeatureViewProjection( - name=feature_grouping.name, + name=base_feature_view.name, name_alias=None, - features=feature_grouping.features, + features=base_feature_view.features, ) diff --git a/sdk/python/feast/field.py b/sdk/python/feast/field.py new file mode 100644 index 00000000000..f6c88f1850d --- /dev/null +++ b/sdk/python/feast/field.py @@ -0,0 +1,87 @@ +# Copyright 2022 The Feast Authors +# +# 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 +# +# https://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. + +from feast.feature import Feature +from feast.protos.feast.core.Feature_pb2 import FeatureSpecV2 as FieldProto +from feast.types import FeastType, from_value_type +from feast.value_type import ValueType + + +class Field: + """ + A Field represents a set of values with the same structure. + + Attributes: + name: The name of the field. + dtype: The type of the field, such as string or float. + """ + + name: str + dtype: FeastType + + def __init__( + self, *, name: str, dtype: FeastType, + ): + """ + Creates a Field object. + + Args: + name: The name of the field. + dtype: The type of the field, such as string or float. + """ + self.name = name + self.dtype = dtype + + def __eq__(self, other): + if self.name != other.name or self.dtype != other.dtype: + return False + return True + + def __hash__(self): + return hash((self.name, hash(self.dtype))) + + def __lt__(self, other): + return self.name < other.name + + def __repr__(self): + return f"{self.name}-{self.dtype}" + + def __str__(self): + return f"Field(name={self.name}, dtype={self.dtype})" + + def to_proto(self) -> FieldProto: + """Converts a Field object to its protobuf representation.""" + value_type = self.dtype.to_value_type() + return FieldProto(name=self.name, value_type=value_type.value) + + @classmethod + def from_proto(cls, field_proto: FieldProto): + """ + Creates a Field object from a protobuf representation. + + Args: + field_proto: FieldProto protobuf object + """ + value_type = ValueType(field_proto.value_type) + return cls(name=field_proto.name, dtype=from_value_type(value_type=value_type)) + + @classmethod + def from_feature(cls, feature: Feature): + """ + Creates a Field object from a Feature object. + + Args: + feature: Feature object to convert. + """ + return cls(name=feature.name, dtype=from_value_type(feature.dtype)) diff --git a/sdk/python/feast/flags.py b/sdk/python/feast/flags.py index a1ca0c3b736..26e20d81f66 100644 --- a/sdk/python/feast/flags.py +++ b/sdk/python/feast/flags.py @@ -1,12 +1,10 @@ FLAG_ALPHA_FEATURES_NAME = "alpha_features" FLAG_ON_DEMAND_TRANSFORM_NAME = "on_demand_transforms" FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME = "aws_lambda_feature_server" -FLAG_DIRECT_INGEST_TO_ONLINE_STORE = "direct_ingest_to_online_store" ENV_FLAG_IS_TEST = "IS_TEST" FLAG_NAMES = { FLAG_ALPHA_FEATURES_NAME, FLAG_ON_DEMAND_TRANSFORM_NAME, FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME, - FLAG_DIRECT_INGEST_TO_ONLINE_STORE, } diff --git a/sdk/python/feast/flags_helper.py b/sdk/python/feast/flags_helper.py index 89905e7d36a..7cf16dbf0b2 100644 --- a/sdk/python/feast/flags_helper.py +++ b/sdk/python/feast/flags_helper.py @@ -37,7 +37,3 @@ def enable_on_demand_feature_views(repo_config: RepoConfig) -> bool: def enable_aws_lambda_feature_server(repo_config: RepoConfig) -> bool: return feature_flag_enabled(repo_config, flags.FLAG_AWS_LAMBDA_FEATURE_SERVER_NAME) - - -def enable_direct_ingestion_to_online_store(repo_config: RepoConfig) -> bool: - return feature_flag_enabled(repo_config, flags.FLAG_DIRECT_INGEST_TO_ONLINE_STORE) diff --git a/sdk/python/feast/inference.py b/sdk/python/feast/inference.py index d233631d3da..9d15a6a25f7 100644 --- a/sdk/python/feast/inference.py +++ b/sdk/python/feast/inference.py @@ -1,18 +1,11 @@ import re from typing import List -from feast import ( - BigQuerySource, - Entity, - Feature, - FileSource, - RedshiftSource, - SnowflakeSource, - SparkSource, -) -from feast.data_source import DataSource, RequestDataSource +from feast import BigQuerySource, Entity, FileSource, RedshiftSource, SnowflakeSource +from feast.data_source import DataSource, RequestSource from feast.errors import RegistryInferenceFailure from feast.feature_view import FeatureView +from feast.field import Field, from_value_type from feast.repo_config import RepoConfig from feast.value_type import ValueType @@ -79,16 +72,15 @@ def update_data_sources_with_inferred_event_timestamp_col( ERROR_MSG_PREFIX = "Unable to infer DataSource event_timestamp_column" for data_source in data_sources: - if isinstance(data_source, RequestDataSource): + if isinstance(data_source, RequestSource): continue - if ( - data_source.event_timestamp_column is None - or data_source.event_timestamp_column == "" - ): + if data_source.timestamp_field is None or data_source.timestamp_field == "": # prepare right match pattern for data source ts_column_type_regex_pattern = "" - if isinstance(data_source, FileSource) or isinstance( - data_source, SparkSource + # TODO(adchia): Move Spark source inference out of this logic + if ( + isinstance(data_source, FileSource) + or "SparkSource" == data_source.__class__.__name__ ): ts_column_type_regex_pattern = r"^timestamp" elif isinstance(data_source, BigQuerySource): @@ -101,7 +93,7 @@ def update_data_sources_with_inferred_event_timestamp_col( raise RegistryInferenceFailure( "DataSource", f""" - DataSource inferencing of event_timestamp_column is currently only supported + DataSource inferencing of timestamp_field is currently only supported for FileSource, SparkSource, BigQuerySource, RedshiftSource, and SnowflakeSource. Attempting to infer from {data_source}. """, @@ -110,11 +102,13 @@ def update_data_sources_with_inferred_event_timestamp_col( assert ( isinstance(data_source, FileSource) or isinstance(data_source, BigQuerySource) + or isinstance(data_source, RedshiftSource) or isinstance(data_source, SnowflakeSource) + or "SparkSource" == data_source.__class__.__name__ ) # loop through table columns to find singular match - event_timestamp_column, matched_flag = None, False + timestamp_field, matched_flag = None, False for ( col_name, col_datatype, @@ -129,10 +123,10 @@ def update_data_sources_with_inferred_event_timestamp_col( """, ) matched_flag = True - event_timestamp_column = col_name + timestamp_field = col_name if matched_flag: - assert event_timestamp_column - data_source.event_timestamp_column = event_timestamp_column + assert timestamp_field + data_source.timestamp_field = timestamp_field else: raise RegistryInferenceFailure( "DataSource", @@ -160,17 +154,15 @@ def update_feature_views_with_inferred_features( for fv in fvs: if not fv.features: columns_to_exclude = { - fv.batch_source.event_timestamp_column, + fv.batch_source.timestamp_field, fv.batch_source.created_timestamp_column, } | { entity_name_to_join_key_map[entity_name] for entity_name in fv.entities } - if fv.batch_source.event_timestamp_column in fv.batch_source.field_mapping: + if fv.batch_source.timestamp_field in fv.batch_source.field_mapping: columns_to_exclude.add( - fv.batch_source.field_mapping[ - fv.batch_source.event_timestamp_column - ] + fv.batch_source.field_mapping[fv.batch_source.timestamp_field] ) if ( fv.batch_source.created_timestamp_column @@ -195,14 +187,18 @@ def update_feature_views_with_inferred_features( if col_name in fv.batch_source.field_mapping else col_name ) - fv.features.append( - Feature( - feature_name, + field = Field( + name=feature_name, + dtype=from_value_type( fv.batch_source.source_datatype_to_feast_value_type()( col_datatype - ), - ) + ) + ), ) + # Note that schema and features are two different attributes of a + # FeatureView, and that features should be present in both. + fv.schema.append(field) + fv.features.append(field) if not fv.features: raise RegistryInferenceFailure( diff --git a/sdk/python/feast/infra/aws.py b/sdk/python/feast/infra/aws.py index 104e20388a2..b7cc61de0e5 100644 --- a/sdk/python/feast/infra/aws.py +++ b/sdk/python/feast/infra/aws.py @@ -119,6 +119,8 @@ def _deploy_feature_server(self, project: str, image_uri: str): lambda_client = boto3.client("lambda") api_gateway_client = boto3.client("apigatewayv2") function = aws_utils.get_lambda_function(lambda_client, resource_name) + _logger.debug("Using function name: %s", resource_name) + _logger.debug("Found function: %s", function) if function is None: # If the Lambda function does not exist, create it. @@ -309,7 +311,7 @@ def _create_or_get_repository_uri(self, ecr_client): def _get_lambda_name(project: str): lambda_prefix = AWS_LAMBDA_FEATURE_SERVER_REPOSITORY - lambda_suffix = f"{project}-{_get_docker_image_version()}" + lambda_suffix = f"{project}-{_get_docker_image_version().replace('.', '_')}" # AWS Lambda name can't have the length greater than 64 bytes. # This usually occurs during integration tests where feast version is long if len(lambda_prefix) + len(lambda_suffix) >= 63: @@ -338,7 +340,7 @@ def _get_docker_image_version() -> str: else: version = get_version() if "dev" in version: - version = version[: version.find("dev") - 1].replace(".", "_") + version = version[: version.find("dev") - 1] _logger.warning( "You are trying to use AWS Lambda feature server while Feast is in a development mode. " f"Feast will use a docker image version {version} derived from Feast SDK " @@ -347,8 +349,6 @@ def _get_docker_image_version() -> str: "> git fetch --all --tags\n" "> pip install -e sdk/python" ) - else: - version = version.replace(".", "_") return version diff --git a/sdk/python/feast/infra/feature_servers/aws_lambda/Dockerfile b/sdk/python/feast/infra/feature_servers/aws_lambda/Dockerfile index 4d46abd3db2..5b685dbcf61 100644 --- a/sdk/python/feast/infra/feature_servers/aws_lambda/Dockerfile +++ b/sdk/python/feast/infra/feature_servers/aws_lambda/Dockerfile @@ -6,6 +6,7 @@ COPY sdk/python/feast/infra/feature_servers/aws_lambda/app.py ${LAMBDA_TASK_ROOT # Copy necessary parts of the Feast codebase COPY sdk/python sdk/python COPY protos protos +COPY go go COPY README.md README.md # Install Feast for AWS with Lambda dependencies diff --git a/sdk/python/feast/infra/local.py b/sdk/python/feast/infra/local.py index c5a15c8a91b..7249d247a22 100644 --- a/sdk/python/feast/infra/local.py +++ b/sdk/python/feast/infra/local.py @@ -63,4 +63,5 @@ def _write_registry(self, registry_proto: RegistryProto): registry_proto.last_updated.FromDatetime(datetime.utcnow()) file_dir = self._filepath.parent file_dir.mkdir(exist_ok=True) - self._filepath.write_bytes(registry_proto.SerializeToString()) + with open(self._filepath, mode="wb", buffering=0) as f: + f.write(registry_proto.SerializeToString()) diff --git a/sdk/python/feast/infra/offline_stores/bigquery.py b/sdk/python/feast/infra/offline_stores/bigquery.py index 44e62d6ad1a..1e27fc326ba 100644 --- a/sdk/python/feast/infra/offline_stores/bigquery.py +++ b/sdk/python/feast/infra/offline_stores/bigquery.py @@ -56,7 +56,7 @@ class BigQueryOfflineStoreConfig(FeastConfigBaseModel): - """ Offline store config for GCP BigQuery """ + """Offline store config for GCP BigQuery""" type: Literal["bigquery"] = "bigquery" """ Offline store type selector""" @@ -338,12 +338,14 @@ def to_bigquery( def _to_arrow_internal(self) -> pyarrow.Table: with self._query_generator() as query: - return self._execute_query(query).to_arrow() + q = self._execute_query(query=query) + assert q + return q.to_arrow() @log_exceptions_and_usage def _execute_query( self, query, job_config=None, timeout: int = 1800 - ) -> bigquery.job.query.QueryJob: + ) -> Optional[bigquery.job.query.QueryJob]: bq_job = self.client.query(query, job_config=job_config) if job_config and job_config.dry_run: @@ -359,7 +361,7 @@ def persist(self, storage: SavedDatasetStorage): assert isinstance(storage, SavedDatasetBigQueryStorage) self.to_bigquery( - bigquery.QueryJobConfig(destination=storage.bigquery_options.table_ref) + bigquery.QueryJobConfig(destination=storage.bigquery_options.table) ) @property @@ -426,7 +428,7 @@ def _get_table_reference_for_new_entity( dataset.location = dataset_location if dataset_location else "US" try: - client.get_dataset(dataset) + client.get_dataset(dataset.reference) except NotFound: # Only create the dataset if it does not exist client.create_dataset(dataset, exists_ok=True) diff --git a/sdk/python/feast/infra/offline_stores/bigquery_source.py b/sdk/python/feast/infra/offline_stores/bigquery_source.py index 6c5be2b5f4c..31b0ed617e9 100644 --- a/sdk/python/feast/infra/offline_stores/bigquery_source.py +++ b/sdk/python/feast/infra/offline_stores/bigquery_source.py @@ -3,7 +3,7 @@ from feast import type_map from feast.data_source import DataSource -from feast.errors import DataSourceNoNameException, DataSourceNotFoundException +from feast.errors import DataSourceNotFoundException from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.SavedDataset_pb2 import ( SavedDatasetStorage as SavedDatasetStorageProto, @@ -16,61 +16,75 @@ class BigQuerySource(DataSource): def __init__( self, - name: Optional[str] = None, event_timestamp_column: Optional[str] = "", table: Optional[str] = None, - table_ref: Optional[str] = None, created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, - date_partition_column: Optional[str] = "", + date_partition_column: Optional[str] = None, query: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = None, ): """Create a BigQuerySource from an existing table or query. - Args: - name (optional): Name for the source. Defaults to the table_ref if not specified. - table (optional): The BigQuery table where features can be found. - table_ref (optional): (Deprecated) The BigQuery table where features can be found. - event_timestamp_column: Event timestamp column used for point in time joins of feature values. - created_timestamp_column (optional): Timestamp column when row was created, used for deduplicating rows. - field_mapping: A dictionary mapping of column names in this data source to feature names in a feature table - or view. Only used for feature columns, not entities or timestamp columns. - date_partition_column (optional): Timestamp column used for partitioning. - query (optional): SQL query to execute to generate data for this data source. - - Example: - >>> from feast import BigQuerySource - >>> my_bigquery_source = BigQuerySource(table="gcp_project:bq_dataset.bq_table") - """ - if table is None and table_ref is None and query is None: - raise ValueError('No "table" argument provided.') - if not table and table_ref: + Args: + table (optional): The BigQuery table where features can be found. + event_timestamp_column: (Deprecated) Event timestamp column used for point in time joins of feature values. + created_timestamp_column (optional): Timestamp column when row was created, used for deduplicating rows. + field_mapping: A dictionary mapping of column names in this data source to feature names in a feature table + or view. Only used for feature columns, not entities or timestamp columns. + date_partition_column (deprecated): Timestamp column used for partitioning. + query (optional): SQL query to execute to generate data for this data source. + name (optional): Name for the source. Defaults to the table if not specified. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the bigquery source, typically the email of the primary + maintainer. + timestamp_field (optional): Event timestamp field used for point in time + joins of feature values. + Example: + >>> from feast import BigQuerySource + >>> my_bigquery_source = BigQuerySource(table="gcp_project:bq_dataset.bq_table") + """ + if table is None and query is None: + raise ValueError('No "table" or "query" argument provided.') + + self.bigquery_options = BigQueryOptions(table=table, query=query) + + if date_partition_column: warnings.warn( ( - "The argument 'table_ref' is being deprecated. Please use 'table' " - "instead. Feast 0.20 and onwards will not support the argument 'table_ref'." + "The argument 'date_partition_column' is not supported for BigQuery sources. " + "It will be removed in Feast 0.21+" ), DeprecationWarning, ) - table = table_ref - self.bigquery_options = BigQueryOptions(table_ref=table, query=query) - # If no name, use the table_ref as the default name + # If no name, use the table as the default name _name = name if not _name: if table: _name = table - elif table_ref: - _name = table_ref else: - raise DataSourceNoNameException() + warnings.warn( + ( + f"Starting in Feast 0.21, Feast will require either a name for a data source (if using query) or `table`: {self.query}" + ), + DeprecationWarning, + ) super().__init__( - _name if _name else "", - event_timestamp_column, - created_timestamp_column, - field_mapping, - date_partition_column, + name=_name if _name else "", + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + description=description, + tags=tags, + owner=owner, + timestamp_field=timestamp_field, ) # Note: Python requires redefining hash in child classes that override __eq__ @@ -85,16 +99,19 @@ def __eq__(self, other): return ( self.name == other.name - and self.bigquery_options.table_ref == other.bigquery_options.table_ref + and self.bigquery_options.table == other.bigquery_options.table and self.bigquery_options.query == other.bigquery_options.query - and self.event_timestamp_column == other.event_timestamp_column + and self.timestamp_field == other.timestamp_field and self.created_timestamp_column == other.created_timestamp_column and self.field_mapping == other.field_mapping + and self.description == other.description + and self.tags == other.tags + and self.owner == other.owner ) @property - def table_ref(self): - return self.bigquery_options.table_ref + def table(self): + return self.bigquery_options.table @property def query(self): @@ -108,11 +125,13 @@ def from_proto(data_source: DataSourceProto): return BigQuerySource( name=data_source.name, field_mapping=dict(data_source.field_mapping), - table_ref=data_source.bigquery_options.table_ref, - event_timestamp_column=data_source.event_timestamp_column, + table=data_source.bigquery_options.table, + timestamp_field=data_source.timestamp_field, created_timestamp_column=data_source.created_timestamp_column, - date_partition_column=data_source.date_partition_column, query=data_source.bigquery_options.query, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, ) def to_proto(self) -> DataSourceProto: @@ -121,11 +140,13 @@ def to_proto(self) -> DataSourceProto: type=DataSourceProto.BATCH_BIGQUERY, field_mapping=self.field_mapping, bigquery_options=self.bigquery_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column - data_source_proto.date_partition_column = self.date_partition_column return data_source_proto @@ -136,14 +157,14 @@ def validate(self, config: RepoConfig): client = bigquery.Client() try: - client.get_table(self.table_ref) + client.get_table(self.table) except NotFound: - raise DataSourceNotFoundException(self.table_ref) + raise DataSourceNotFoundException(self.table) def get_table_query_string(self) -> str: """Returns a string that can directly be used to reference this table in SQL""" - if self.table_ref: - return f"`{self.table_ref}`" + if self.table: + return f"`{self.table}`" else: return f"({self.query})" @@ -157,8 +178,8 @@ def get_table_column_names_and_types( from google.cloud import bigquery client = bigquery.Client() - if self.table_ref is not None: - schema = client.get_table(self.table_ref).schema + if self.table is not None: + schema = client.get_table(self.table).schema if not isinstance(schema[0], bigquery.schema.SchemaField): raise TypeError("Could not parse BigQuery table schema.") else: @@ -182,9 +203,9 @@ class BigQueryOptions: """ def __init__( - self, table_ref: Optional[str], query: Optional[str], + self, table: Optional[str], query: Optional[str], ): - self._table_ref = table_ref + self._table = table self._query = query @property @@ -202,18 +223,18 @@ def query(self, query): self._query = query @property - def table_ref(self): + def table(self): """ Returns the table ref of this BQ table """ - return self._table_ref + return self._table - @table_ref.setter - def table_ref(self, table_ref): + @table.setter + def table(self, table): """ Sets the table ref of this BQ table """ - self._table_ref = table_ref + self._table = table @classmethod def from_proto(cls, bigquery_options_proto: DataSourceProto.BigQueryOptions): @@ -228,8 +249,7 @@ def from_proto(cls, bigquery_options_proto: DataSourceProto.BigQueryOptions): """ bigquery_options = cls( - table_ref=bigquery_options_proto.table_ref, - query=bigquery_options_proto.query, + table=bigquery_options_proto.table, query=bigquery_options_proto.query, ) return bigquery_options @@ -243,7 +263,7 @@ def to_proto(self) -> DataSourceProto.BigQueryOptions: """ bigquery_options_proto = DataSourceProto.BigQueryOptions( - table_ref=self.table_ref, query=self.query, + table=self.table, query=self.query, ) return bigquery_options_proto @@ -254,15 +274,13 @@ class SavedDatasetBigQueryStorage(SavedDatasetStorage): bigquery_options: BigQueryOptions - def __init__(self, table_ref: str): - self.bigquery_options = BigQueryOptions(table_ref=table_ref, query=None) + def __init__(self, table: str): + self.bigquery_options = BigQueryOptions(table=table, query=None) @staticmethod def from_proto(storage_proto: SavedDatasetStorageProto) -> SavedDatasetStorage: return SavedDatasetBigQueryStorage( - table_ref=BigQueryOptions.from_proto( - storage_proto.bigquery_storage - ).table_ref + table=BigQueryOptions.from_proto(storage_proto.bigquery_storage).table ) def to_proto(self) -> SavedDatasetStorageProto: @@ -271,4 +289,4 @@ def to_proto(self) -> SavedDatasetStorageProto: ) def to_data_source(self) -> DataSource: - return BigQuerySource(table_ref=self.bigquery_options.table_ref) + return BigQuerySource(table=self.bigquery_options.table) diff --git a/sdk/python/feast/protos/feast/core/__init__.py b/sdk/python/feast/infra/offline_stores/contrib/__init__.py similarity index 100% rename from sdk/python/feast/protos/feast/core/__init__.py rename to sdk/python/feast/infra/offline_stores/contrib/__init__.py diff --git a/sdk/python/feast/infra/offline_stores/contrib/contrib_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/contrib_repo_configuration.py new file mode 100644 index 00000000000..370ed0f47cb --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/contrib_repo_configuration.py @@ -0,0 +1,14 @@ +from tests.integration.feature_repos.integration_test_repo_config import ( + IntegrationTestRepoConfig, +) +from tests.integration.feature_repos.universal.data_sources.spark_data_source_creator import ( + SparkDataSourceCreator, +) +from tests.integration.feature_repos.universal.data_sources.trino import ( + TrinoSourceCreator, +) + +FULL_REPO_CONFIGS = [ + IntegrationTestRepoConfig(offline_store_creator=SparkDataSourceCreator), + IntegrationTestRepoConfig(offline_store_creator=TrinoSourceCreator), +] diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py index 95e306aa605..1b977ba622f 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py +++ b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py @@ -18,6 +18,7 @@ from feast.feature_view import DUMMY_ENTITY_ID, DUMMY_ENTITY_VAL from feast.infra.offline_stores import offline_utils from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SavedDatasetSparkStorage, SparkSource, ) from feast.infra.offline_stores.offline_store import ( @@ -29,6 +30,7 @@ from feast.repo_config import FeastConfigBaseModel, RepoConfig from feast.saved_dataset import SavedDatasetStorage from feast.type_map import spark_schema_to_np_dtypes +from feast.usage import log_exceptions_and_usage class SparkOfflineStoreConfig(FeastConfigBaseModel): @@ -42,6 +44,7 @@ class SparkOfflineStoreConfig(FeastConfigBaseModel): class SparkOfflineStore(OfflineStore): @staticmethod + @log_exceptions_and_usage(offline_store="spark") def pull_latest_from_table_or_query( config: RepoConfig, data_source: DataSource, @@ -102,6 +105,7 @@ def pull_latest_from_table_or_query( ) @staticmethod + @log_exceptions_and_usage(offline_store="spark") def get_historical_features( config: RepoConfig, feature_views: List[FeatureView], @@ -122,10 +126,8 @@ def get_historical_features( ) tmp_entity_df_table_name = offline_utils.get_temp_entity_table_name() - entity_schema = _upload_entity_df_and_get_entity_schema( - spark_session=spark_session, - table_name=tmp_entity_df_table_name, - entity_df=entity_df, + entity_schema = _get_entity_schema( + spark_session=spark_session, entity_df=entity_df, ) event_timestamp_col = offline_utils.infer_event_timestamp_from_entity_df( entity_schema=entity_schema, @@ -133,6 +135,12 @@ def get_historical_features( entity_df_event_timestamp_range = _get_entity_df_event_timestamp_range( entity_df, event_timestamp_col, spark_session, ) + _upload_entity_df( + spark_session=spark_session, + table_name=tmp_entity_df_table_name, + entity_df=entity_df, + event_timestamp_col=event_timestamp_col, + ) expected_join_keys = offline_utils.get_expected_join_keys( project=project, feature_views=feature_views, registry=registry @@ -176,6 +184,7 @@ def get_historical_features( ) @staticmethod + @log_exceptions_and_usage(offline_store="spark") def pull_all_from_table_or_query( config: RepoConfig, data_source: DataSource, @@ -186,9 +195,9 @@ def pull_all_from_table_or_query( end_date: datetime, ) -> RetrievalJob: """ - Note that join_key_columns, feature_name_columns, event_timestamp_column, and created_timestamp_column - have all already been mapped to column names of the source table and those column names are the values passed - into this function. + Note that join_key_columns, feature_name_columns, event_timestamp_column, and + created_timestamp_column have all already been mapped to column names of the + source table and those column names are the values passed into this function. """ assert isinstance(data_source, SparkSource) warnings.warn( @@ -196,26 +205,24 @@ def pull_all_from_table_or_query( "This API is unstable and it could and most probably will be changed in the future.", RuntimeWarning, ) - from_expression = data_source.get_table_query_string() - field_string = ( - '"' - + '", "'.join( - join_key_columns + feature_name_columns + [event_timestamp_column] - ) - + '"' + spark_session = get_spark_session_or_start_new_with_repoconfig( + store_config=config.offline_store + ) + + fields = ", ".join( + join_key_columns + feature_name_columns + [event_timestamp_column] ) + from_expression = data_source.get_table_query_string() start_date = start_date.astimezone(tz=utc) end_date = end_date.astimezone(tz=utc) query = f""" - SELECT {field_string} + SELECT {fields} FROM {from_expression} - WHERE "{event_timestamp_column}" BETWEEN TIMESTAMP '{start_date}' AND TIMESTAMP '{end_date}' + WHERE {event_timestamp_column} BETWEEN TIMESTAMP '{start_date}' AND TIMESTAMP '{end_date}' """ - spark_session = get_spark_session_or_start_new_with_repoconfig( - store_config=config.offline_store - ) + return SparkRetrievalJob( spark_session=spark_session, query=query, full_feature_names=False ) @@ -246,9 +253,7 @@ def on_demand_feature_views(self) -> Optional[List[OnDemandFeatureView]]: return self._on_demand_feature_views def to_spark_df(self) -> pyspark.sql.DataFrame: - statements = self.query.split( - "---EOS---" - ) # TODO can do better than this dirty split + statements = self.query.split("---EOS---") *_, last = map(self.spark_session.sql, statements) return last @@ -264,8 +269,13 @@ def _to_arrow_internal(self) -> pyarrow.Table: def persist(self, storage: SavedDatasetStorage): """ Run the retrieval and persist the results in the same offline store used for read. + Please note the persisting is done only within the scope of the spark session. """ - pass + assert isinstance(storage, SavedDatasetSparkStorage) + table_name = storage.spark_options.table + if not table_name: + raise ValueError("Cannot persist, table_name is not defined") + self.to_spark_df().createOrReplaceTempView(table_name) @property def metadata(self) -> Optional[RetrievalMetadata]: @@ -325,27 +335,42 @@ def _get_entity_df_event_timestamp_range( return entity_df_event_timestamp_range -def _upload_entity_df_and_get_entity_schema( - spark_session: SparkSession, - table_name: str, - entity_df: Union[pandas.DataFrame, str], +def _get_entity_schema( + spark_session: SparkSession, entity_df: Union[pandas.DataFrame, str] ) -> Dict[str, np.dtype]: if isinstance(entity_df, pd.DataFrame): - spark_session.createDataFrame(entity_df).createOrReplaceTempView(table_name) return dict(zip(entity_df.columns, entity_df.dtypes)) elif isinstance(entity_df, str): - spark_session.sql(entity_df).createOrReplaceTempView(table_name) - limited_entity_df = spark_session.table(table_name) + entity_spark_df = spark_session.sql(entity_df) return dict( zip( - limited_entity_df.columns, - spark_schema_to_np_dtypes(limited_entity_df.dtypes), + entity_spark_df.columns, + spark_schema_to_np_dtypes(entity_spark_df.dtypes), ) ) else: raise InvalidEntityType(type(entity_df)) +def _upload_entity_df( + spark_session: SparkSession, + table_name: str, + entity_df: Union[pandas.DataFrame, str], + event_timestamp_col: str, +) -> None: + if isinstance(entity_df, pd.DataFrame): + entity_df[event_timestamp_col] = pd.to_datetime( + entity_df[event_timestamp_col], utc=True + ) + spark_session.createDataFrame(entity_df).createOrReplaceTempView(table_name) + return + elif isinstance(entity_df, str): + spark_session.sql(entity_df).createOrReplaceTempView(table_name) + return + else: + raise InvalidEntityType(type(entity_df)) + + def _format_datetime(t: datetime) -> str: # Since Hive does not support timezone, need to transform to utc. if t.tzinfo: @@ -354,7 +379,8 @@ def _format_datetime(t: datetime) -> str: return dt -MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN = """/* +MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN = """ +/* Compute a deterministic hash for the `left_table_query_string` that will be used throughout all the logic as the field to GROUP BY the data */ @@ -371,152 +397,153 @@ def _format_datetime(t: datetime) -> str: {% endfor %} FROM {{ left_table_query_string }} ); + ---EOS--- --- Start create temporary table *__base + {% for featureview in featureviews %} -CREATE OR REPLACE TEMPORARY VIEW {{ featureview.name }}__base AS -WITH {{ featureview.name }}__entity_dataframe AS ( - SELECT - {{ featureview.entities | join(', ')}}, - entity_timestamp, - {{featureview.name}}__entity_row_unique_id - FROM entity_dataframe - GROUP BY {{ featureview.entities | join(', ')}}, entity_timestamp, {{featureview.name}}__entity_row_unique_id -), -/* - This query template performs the point-in-time correctness join for a single feature set table - to the provided entity table. - 1. We first join the current feature_view to the entity dataframe that has been passed. - This JOIN has the following logic: - - For each row of the entity dataframe, only keep the rows where the `event_timestamp_column` - is less than the one provided in the entity dataframe - - If there a TTL for the current feature_view, also keep the rows where the `event_timestamp_column` - is higher the the one provided minus the TTL - - For each row, Join on the entity key and retrieve the `entity_row_unique_id` that has been - computed previously - The output of this CTE will contain all the necessary information and already filtered out most - of the data that is not relevant. -*/ -{{ featureview.name }}__subquery AS ( - SELECT - {{ featureview.event_timestamp_column }} as event_timestamp, - {{ featureview.created_timestamp_column ~ ' as created_timestamp,' if featureview.created_timestamp_column else '' }} - {{ featureview.entity_selections | join(', ')}}, - {% for feature in featureview.features %} - {{ feature }} as {% if full_feature_names %}{{ featureview.name }}__{{feature}}{% else %}{{ feature }}{% endif %}{% if loop.last %}{% else %}, {% endif %} - {% endfor %} - FROM {{ featureview.table_subquery }} AS subquery - INNER JOIN ( - SELECT MAX(entity_timestamp) as max_entity_timestamp_ - {% if featureview.ttl == 0 %}{% else %} - ,(MIN(entity_timestamp) - interval '{{ featureview.ttl }}' second) as min_entity_timestamp_ - {% endif %} + +CREATE OR REPLACE TEMPORARY VIEW {{ featureview.name }}__cleaned AS ( + + WITH {{ featureview.name }}__entity_dataframe AS ( + SELECT + {{ featureview.entities | join(', ')}}{% if featureview.entities %},{% else %}{% endif %} + entity_timestamp, + {{featureview.name}}__entity_row_unique_id FROM entity_dataframe - ) AS temp - ON ( - {{ featureview.event_timestamp_column }} <= max_entity_timestamp_ + GROUP BY + {{ featureview.entities | join(', ')}}{% if featureview.entities %},{% else %}{% endif %} + entity_timestamp, + {{featureview.name}}__entity_row_unique_id + ), + + /* + This query template performs the point-in-time correctness join for a single feature set table + to the provided entity table. + + 1. We first join the current feature_view to the entity dataframe that has been passed. + This JOIN has the following logic: + - For each row of the entity dataframe, only keep the rows where the `event_timestamp_column` + is less than the one provided in the entity dataframe + - If there a TTL for the current feature_view, also keep the rows where the `event_timestamp_column` + is higher the the one provided minus the TTL + - For each row, Join on the entity key and retrieve the `entity_row_unique_id` that has been + computed previously + + The output of this CTE will contain all the necessary information and already filtered out most + of the data that is not relevant. + */ + + {{ featureview.name }}__subquery AS ( + SELECT + {{ featureview.event_timestamp_column }} as event_timestamp, + {{ featureview.created_timestamp_column ~ ' as created_timestamp,' if featureview.created_timestamp_column else '' }} + {{ featureview.entity_selections | join(', ')}}{% if featureview.entity_selections %},{% else %}{% endif %} + {% for feature in featureview.features %} + {{ feature }} as {% if full_feature_names %}{{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %}{{ featureview.field_mapping.get(feature, feature) }}{% endif %}{% if loop.last %}{% else %}, {% endif %} + {% endfor %} + FROM {{ featureview.table_subquery }} + WHERE {{ featureview.event_timestamp_column }} <= '{{ featureview.max_event_timestamp }}' {% if featureview.ttl == 0 %}{% else %} - AND {{ featureview.event_timestamp_column }} >= min_entity_timestamp_ - {% endif %} - ) -) -SELECT - subquery.*, - entity_dataframe.entity_timestamp, - entity_dataframe.{{featureview.name}}__entity_row_unique_id -FROM {{ featureview.name }}__subquery AS subquery -INNER JOIN ( - SELECT * - {% if featureview.ttl == 0 %}{% else %} - , (entity_timestamp - interval '{{ featureview.ttl }}' second) as ttl_entity_timestamp - {% endif %} - FROM {{ featureview.name }}__entity_dataframe -) AS entity_dataframe -ON ( - subquery.event_timestamp <= entity_dataframe.entity_timestamp - {% if featureview.ttl == 0 %}{% else %} - AND subquery.event_timestamp >= entity_dataframe.ttl_entity_timestamp - {% endif %} - {% for entity in featureview.entities %} - AND subquery.{{ entity }} = entity_dataframe.{{ entity }} - {% endfor %} -); ----EOS--- -{% endfor %} --- End create temporary table *__base -{% for featureview in featureviews %} -{% if loop.first %}WITH{% endif %} -/* - 2. If the `created_timestamp_column` has been set, we need to - deduplicate the data first. This is done by calculating the - `MAX(created_at_timestamp)` for each event_timestamp. - We then join the data on the next CTE -*/ -{% if featureview.created_timestamp_column %} -{{ featureview.name }}__dedup AS ( - SELECT - {{featureview.name}}__entity_row_unique_id, - event_timestamp, - MAX(created_timestamp) as created_timestamp - FROM {{ featureview.name }}__base - GROUP BY {{featureview.name}}__entity_row_unique_id, event_timestamp -), -{% endif %} -/* - 3. The data has been filtered during the first CTE "*__base" - Thus we only need to compute the latest timestamp of each feature. -*/ -{{ featureview.name }}__latest AS ( - SELECT - base.{{featureview.name}}__entity_row_unique_id, - MAX(base.event_timestamp) AS event_timestamp - {% if featureview.created_timestamp_column %} - ,MAX(base.created_timestamp) AS created_timestamp + AND {{ featureview.event_timestamp_column }} >= '{{ featureview.min_event_timestamp }}' {% endif %} - FROM {{ featureview.name }}__base AS base + ), + + {{ featureview.name }}__base AS ( + SELECT + subquery.*, + entity_dataframe.entity_timestamp, + entity_dataframe.{{featureview.name}}__entity_row_unique_id + FROM {{ featureview.name }}__subquery AS subquery + INNER JOIN {{ featureview.name }}__entity_dataframe AS entity_dataframe + ON TRUE + AND subquery.event_timestamp <= entity_dataframe.entity_timestamp + + {% if featureview.ttl == 0 %}{% else %} + AND subquery.event_timestamp >= entity_dataframe.entity_timestamp - {{ featureview.ttl }} * interval '1' second + {% endif %} + + {% for entity in featureview.entities %} + AND subquery.{{ entity }} = entity_dataframe.{{ entity }} + {% endfor %} + ), + + /* + 2. If the `created_timestamp_column` has been set, we need to + deduplicate the data first. This is done by calculating the + `MAX(created_at_timestamp)` for each event_timestamp. + We then join the data on the next CTE + */ {% if featureview.created_timestamp_column %} - INNER JOIN {{ featureview.name }}__dedup AS dedup - ON ( - dedup.{{featureview.name}}__entity_row_unique_id=base.{{featureview.name}}__entity_row_unique_id - AND dedup.event_timestamp=base.event_timestamp - AND dedup.created_timestamp=base.created_timestamp - ) + {{ featureview.name }}__dedup AS ( + SELECT + {{featureview.name}}__entity_row_unique_id, + event_timestamp, + MAX(created_timestamp) as created_timestamp + FROM {{ featureview.name }}__base + GROUP BY {{featureview.name}}__entity_row_unique_id, event_timestamp + ), {% endif %} - GROUP BY base.{{featureview.name}}__entity_row_unique_id -), -/* - 4. Once we know the latest value of each feature for a given timestamp, - we can join again the data back to the original "base" dataset -*/ -{{ featureview.name }}__cleaned AS ( + + /* + 3. The data has been filtered during the first CTE "*__base" + Thus we only need to compute the latest timestamp of each feature. + */ + {{ featureview.name }}__latest AS ( + SELECT + event_timestamp, + {% if featureview.created_timestamp_column %}created_timestamp,{% endif %} + {{featureview.name}}__entity_row_unique_id + FROM + ( + SELECT *, + ROW_NUMBER() OVER( + PARTITION BY {{featureview.name}}__entity_row_unique_id + ORDER BY event_timestamp DESC{% if featureview.created_timestamp_column %},created_timestamp DESC{% endif %} + ) AS row_number + FROM {{ featureview.name }}__base + {% if featureview.created_timestamp_column %} + INNER JOIN {{ featureview.name }}__dedup + USING ({{featureview.name}}__entity_row_unique_id, event_timestamp, created_timestamp) + {% endif %} + ) + WHERE row_number = 1 + ) + + /* + 4. Once we know the latest value of each feature for a given timestamp, + we can join again the data back to the original "base" dataset + */ SELECT base.* - FROM {{ featureview.name }}__base AS base - INNER JOIN {{ featureview.name }}__latest AS latest - ON ( - base.{{featureview.name}}__entity_row_unique_id=latest.{{featureview.name}}__entity_row_unique_id - AND base.event_timestamp=latest.event_timestamp + FROM {{ featureview.name }}__base as base + INNER JOIN {{ featureview.name }}__latest + USING( + {{featureview.name}}__entity_row_unique_id, + event_timestamp {% if featureview.created_timestamp_column %} - AND base.created_timestamp=latest.created_timestamp + ,created_timestamp {% endif %} ) -){% if loop.last %}{% else %}, {% endif %} +) + +---EOS--- + {% endfor %} + /* Joins the outputs of multiple time travel joins to a single table. The entity_dataframe dataset being our source of truth here. */ -SELECT `(entity_timestamp|{% for featureview in featureviews %}{{featureview.name}}__entity_row_unique_id{% if loop.last %}{% else %}|{% endif %}{% endfor %})?+.+` + +SELECT {{ final_output_feature_names | join(', ')}} FROM entity_dataframe {% for featureview in featureviews %} LEFT JOIN ( SELECT {{featureview.name}}__entity_row_unique_id {% for feature in featureview.features %} - ,{% if full_feature_names %}{{ featureview.name }}__{{feature}}{% else %}{{ feature }}{% endif %} + ,{% if full_feature_names %}{{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %}{{ featureview.field_mapping.get(feature, feature) }}{% endif %} {% endfor %} FROM {{ featureview.name }}__cleaned -) AS {{ featureview.name }}__joined -ON ( - {{ featureview.name }}__joined.{{featureview.name}}__entity_row_unique_id=entity_dataframe.{{featureview.name}}__entity_row_unique_id -) -{% endfor %}""" +) USING ({{featureview.name}}__entity_row_unique_id) +{% endfor %} +""" diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark_source.py b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark_source.py index 3ffdf6eda0c..65997040cc0 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark_source.py @@ -1,5 +1,4 @@ import logging -import pickle import traceback import warnings from enum import Enum @@ -40,6 +39,10 @@ def __init__( created_timestamp_column: Optional[str] = None, field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = None, + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = None, ): # If no name, use the table_ref as the default name _name = name @@ -48,36 +51,31 @@ def __init__( _name = table else: raise DataSourceNoNameException() + + if date_partition_column: + warnings.warn( + ( + "The argument 'date_partition_column' is not supported for Spark sources." + "It will be removed in Feast 0.21+" + ), + DeprecationWarning, + ) + super().__init__( - _name, - event_timestamp_column, - created_timestamp_column, - field_mapping, - date_partition_column, + name=_name, + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + description=description, + tags=tags, + owner=owner, + timestamp_field=timestamp_field, ) warnings.warn( "The spark data source API is an experimental feature in alpha development. " "This API is unstable and it could and most probably will be changed in the future.", RuntimeWarning, ) - self.allowed_formats = [format.value for format in SparkSourceFormat] - - # Check that only one of the ways to load a spark dataframe can be used. - if sum([(arg is not None) for arg in [table, query, path]]) != 1: - raise ValueError( - "Exactly one of params(table, query, path) must be specified." - ) - - if path is not None: - if file_format is None: - raise ValueError( - "If 'path' is specified, then 'file_format' is required." - ) - if file_format not in self.allowed_formats: - raise ValueError( - f"'file_format' should be one of {self.allowed_formats}" - ) - self.spark_options = SparkOptions( table=table, query=query, path=path, file_format=file_format, ) @@ -112,9 +110,9 @@ def file_format(self): @staticmethod def from_proto(data_source: DataSourceProto) -> Any: - assert data_source.HasField("custom_options") + assert data_source.HasField("spark_options") + spark_options = SparkOptions.from_proto(data_source.spark_options) - spark_options = SparkOptions.from_proto(data_source.custom_options) return SparkSource( name=data_source.name, field_mapping=dict(data_source.field_mapping), @@ -122,22 +120,27 @@ def from_proto(data_source: DataSourceProto) -> Any: query=spark_options.query, path=spark_options.path, file_format=spark_options.file_format, - event_timestamp_column=data_source.event_timestamp_column, + timestamp_field=data_source.timestamp_field, created_timestamp_column=data_source.created_timestamp_column, - date_partition_column=data_source.date_partition_column, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, ) def to_proto(self) -> DataSourceProto: data_source_proto = DataSourceProto( name=self.name, - type=DataSourceProto.CUSTOM_SOURCE, + type=DataSourceProto.BATCH_SPARK, + data_source_class_type="feast.infra.offline_stores.contrib.spark_offline_store.spark_source.SparkSource", field_mapping=self.field_mapping, - custom_options=self.spark_options.to_proto(), + spark_options=self.spark_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column - data_source_proto.date_partition_column = self.date_partition_column return data_source_proto @@ -189,20 +192,70 @@ def get_table_query_string(self) -> str: class SparkOptions: + allowed_formats = [format.value for format in SparkSourceFormat] + def __init__( self, - table: Optional[str] = None, - query: Optional[str] = None, - path: Optional[str] = None, - file_format: Optional[str] = None, + table: Optional[str], + query: Optional[str], + path: Optional[str], + file_format: Optional[str], ): - self.table = table - self.query = query - self.path = path - self.file_format = file_format + # Check that only one of the ways to load a spark dataframe can be used. We have + # to treat empty string and null the same due to proto (de)serialization. + if sum([(not (not arg)) for arg in [table, query, path]]) != 1: + raise ValueError( + "Exactly one of params(table, query, path) must be specified." + ) + if path: + if not file_format: + raise ValueError( + "If 'path' is specified, then 'file_format' is required." + ) + if file_format not in self.allowed_formats: + raise ValueError( + f"'file_format' should be one of {self.allowed_formats}" + ) + + self._table = table + self._query = query + self._path = path + self._file_format = file_format + + @property + def table(self): + return self._table + + @table.setter + def table(self, table): + self._table = table + + @property + def query(self): + return self._query + + @query.setter + def query(self, query): + self._query = query + + @property + def path(self): + return self._path + + @path.setter + def path(self, path): + self._path = path + + @property + def file_format(self): + return self._file_format + + @file_format.setter + def file_format(self, file_format): + self._file_format = file_format @classmethod - def from_proto(cls, spark_options_proto: DataSourceProto.CustomSourceOptions): + def from_proto(cls, spark_options_proto: DataSourceProto.SparkOptions): """ Creates a SparkOptions from a protobuf representation of a spark option args: @@ -210,25 +263,26 @@ def from_proto(cls, spark_options_proto: DataSourceProto.CustomSourceOptions): Returns: Returns a SparkOptions object based on the spark_options protobuf """ - spark_configuration = pickle.loads(spark_options_proto.configuration) - spark_options = cls( - table=spark_configuration.table, - query=spark_configuration.query, - path=spark_configuration.path, - file_format=spark_configuration.file_format, + table=spark_options_proto.table, + query=spark_options_proto.query, + path=spark_options_proto.path, + file_format=spark_options_proto.file_format, ) + return spark_options - def to_proto(self) -> DataSourceProto.CustomSourceOptions: + def to_proto(self) -> DataSourceProto.SparkOptions: """ Converts an SparkOptionsProto object to its protobuf representation. Returns: SparkOptionsProto protobuf """ - - spark_options_proto = DataSourceProto.CustomSourceOptions( - configuration=pickle.dumps(self), + spark_options_proto = DataSourceProto.SparkOptions( + table=self.table, + query=self.query, + path=self.path, + file_format=self.file_format, ) return spark_options_proto @@ -239,16 +293,34 @@ class SavedDatasetSparkStorage(SavedDatasetStorage): spark_options: SparkOptions - def __init__(self, table_ref: Optional[str] = None, query: Optional[str] = None): - self.spark_options = SparkOptions(table=table_ref, query=query) + def __init__( + self, + table: Optional[str] = None, + query: Optional[str] = None, + path: Optional[str] = None, + file_format: Optional[str] = None, + ): + self.spark_options = SparkOptions( + table=table, query=query, path=path, file_format=file_format, + ) @staticmethod def from_proto(storage_proto: SavedDatasetStorageProto) -> SavedDatasetStorage: - # TODO: implementation is not correct. Needs fix and update to protos. - return SavedDatasetSparkStorage(table_ref="", query=None) + spark_options = SparkOptions.from_proto(storage_proto.spark_storage) + return SavedDatasetSparkStorage( + table=spark_options.table, + query=spark_options.query, + path=spark_options.path, + file_format=spark_options.file_format, + ) def to_proto(self) -> SavedDatasetStorageProto: - return SavedDatasetStorageProto() + return SavedDatasetStorageProto(spark_storage=self.spark_options.to_proto()) def to_data_source(self) -> DataSource: - return SparkSource(table=self.spark_options.table) + return SparkSource( + table=self.spark_options.table, + query=self.spark_options.query, + path=self.spark_options.path, + file_format=self.spark_options.file_format, + ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/README.md b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/README.md new file mode 100644 index 00000000000..23fc2092da0 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/README.md @@ -0,0 +1,30 @@ +# Trino offline store +This is a walkthrough to talk about how we can test the trino plugin locally + +## Start Trino in a docker container +```sh +make start-trino-locally +``` + +Normally this should start a docker container named `trino` listening on the port 8080. +You can see the docker command executed by looking at the `Makefile` at the root. + +You can look at the queries being executed during the tests with the [local cluster UI](http://0.0.0.0:8080/ui/#) running. +This can be helpful to debug the Trino plugin while executing tests. + +## Run the universal suites locally +```sh +make test-trino-plugin-locally +``` + +## Kill the local Trino container +```sh +make kill-trino-locally +``` + +You can always look at the running containers and kill the ones you don't need anymore +```sh +docker ps +docker stop {NAME/SHA OF THE CONTAINER} +``` +feast.sdk.python.feast.infra.offline_stores.contrib.trino_offline_store \ No newline at end of file diff --git a/sdk/python/feast/protos/feast/serving/__init__.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/__init__.py similarity index 100% rename from sdk/python/feast/protos/feast/serving/__init__.py rename to sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/__init__.py diff --git a/sdk/python/feast/protos/feast/storage/__init__.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/connectors/__init__.py similarity index 100% rename from sdk/python/feast/protos/feast/storage/__init__.py rename to sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/connectors/__init__.py diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/connectors/upload.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/connectors/upload.py new file mode 100644 index 00000000000..5967b7a8634 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/connectors/upload.py @@ -0,0 +1,194 @@ +""" +Connectors can be found in the following doc https://trino.io/docs/current/connector.html + +For the hive connector, all file formats are here +https://trino.io/docs/current/connector/hive.html#supported-file-types + +Example yaml config +```yaml +offline_store: + type: trino + host: localhost + port: 8080 + catalog: hive + dataset: ci + connector: + type: hive + file_format: parquet +``` +""" +from datetime import datetime +from typing import Any, Dict, Iterator, Optional, Set + +import numpy as np +import pandas as pd +import pyarrow +from pytz import utc + +from feast.infra.offline_stores.contrib.trino_offline_store.trino_queries import Trino +from feast.infra.offline_stores.contrib.trino_offline_store.trino_type_map import ( + pa_to_trino_value_type, +) + +CONNECTORS_DONT_SUPPORT_CREATE_TABLE: Set[str] = { + "druid", + "elasticsearch", + "googlesheets", + "jmx", + "kafka", + "kinesis", + "localfile", + "pinot", + "postgresql", + "prometheus", + "redis", + "thrift", + "tpcds", + "tpch", +} +CONNECTORS_WITHOUT_WITH_STATEMENTS: Set[str] = { + "bigquery", + "cassandra", + "memory", + "mongodb", + "mysql", + "oracle", + "redshift", + "memsql", +} + +CREATE_SCHEMA_QUERY_TEMPLATE = """ +CREATE TABLE IF NOT EXISTS {table} ( + {schema} +) +{with_statement} +""" + +INSERT_ROWS_QUERY_TEMPLATE = """ +INSERT INTO {table} ({columns}) +VALUES {values} +""" + + +def pyarrow_schema_from_dataframe(df: pd.DataFrame) -> Dict[str, Any]: + pyarrow_schema = pyarrow.Table.from_pandas(df).schema + trino_schema: Dict[str, Any] = {} + for field in pyarrow_schema: + try: + trino_type = pa_to_trino_value_type(str(field.type)) + except KeyError: + raise ValueError( + f"Not supported type '{field.type}' in entity_df for '{field.name}'." + ) + trino_schema[field.name] = trino_type + return trino_schema + + +def trino_table_schema_from_dataframe(df: pd.DataFrame) -> str: + return ",".join( + [ + f"{field_name} {field_type}" + for field_name, field_type in pyarrow_schema_from_dataframe(df=df).items() + ] + ) + + +def pandas_dataframe_fix_batches( + df: pd.DataFrame, batch_size: int +) -> Iterator[pd.DataFrame]: + for pos in range(0, len(df), batch_size): + yield df[pos : pos + batch_size] + + +def format_pandas_row(df: pd.DataFrame) -> str: + pyarrow_schema = pyarrow_schema_from_dataframe(df=df) + + def _is_nan(value: Any) -> bool: + if value is None: + return True + + try: + return np.isnan(value) + except TypeError: + return False + + def _format_value(row: pd.Series, schema: Dict[str, Any]) -> str: + formated_values = [] + for row_name, row_value in row.iteritems(): + if schema[row_name].startswith("timestamp"): + if isinstance(row_value, datetime): + row_value = format_datetime(row_value) + formated_values.append(f"TIMESTAMP '{row_value}'") + elif isinstance(row_value, list): + formated_values.append(f"ARRAY{row_value}") + elif isinstance(row_value, np.ndarray): + formated_values.append(f"ARRAY{row_value.tolist()}") + elif isinstance(row_value, tuple): + formated_values.append(f"ARRAY{list(row_value)}") + elif isinstance(row_value, str): + formated_values.append(f"'{row_value}'") + elif _is_nan(row_value): + formated_values.append("NULL") + else: + formated_values.append(f"{row_value}") + + return f"({','.join(formated_values)})" + + results = df.apply(_format_value, args=(pyarrow_schema,), axis=1).tolist() + return ",".join(results) + + +def format_datetime(t: datetime) -> str: + if t.tzinfo: + t = t.astimezone(tz=utc) + return t.strftime("%Y-%m-%d %H:%M:%S.%f") + + +def upload_pandas_dataframe_to_trino( + client: Trino, + df: pd.DataFrame, + table: str, + connector_args: Optional[Dict[str, str]] = None, + batch_size: int = 1000000, # 1 million rows by default +) -> None: + connector_args = connector_args or {} + connector_name = connector_args["type"] + + if connector_name in CONNECTORS_DONT_SUPPORT_CREATE_TABLE: + raise ValueError( + f"The connector '{connector_name}' is not supported because it does not support CREATE TABLE operations" + ) + elif connector_name in CONNECTORS_WITHOUT_WITH_STATEMENTS: + with_statement = "" + elif connector_name in {"hive", "iceberg"}: + if "file_format" not in connector_args.keys(): + raise ValueError( + f"The connector {connector_name} needs the argument 'file_format' in order to create tables with Trino" + ) + with_statement = f"WITH (format = '{connector_args['file_format']}')" + elif connector_name in {"kudu", "phoenix", "sqlserver"}: + raise ValueError( + f"The connector {connector_name} is not yet supported. PRs welcome :)" + ) + else: + raise ValueError( + f"The connector {connector_name} is not part of the connectors listed in the Trino website: https://trino.io/docs/current/connector.html" + ) + + client.execute_query( + CREATE_SCHEMA_QUERY_TEMPLATE.format( + table=table, + schema=trino_table_schema_from_dataframe(df=df), + with_statement=with_statement, + ) + ) + + # Upload batchs of 1M rows at a time + for batch_df in pandas_dataframe_fix_batches(df=df, batch_size=batch_size): + client.execute_query( + INSERT_ROWS_QUERY_TEMPLATE.format( + table=table, + columns=",".join(batch_df.columns), + values=format_pandas_row(batch_df), + ) + ) diff --git a/sdk/python/feast/protos/feast/types/__init__.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/__init__.py similarity index 100% rename from sdk/python/feast/protos/feast/types/__init__.py rename to sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/__init__.py diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/manual_tests.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/manual_tests.py new file mode 100644 index 00000000000..5228ed84a9d --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/manual_tests.py @@ -0,0 +1,12 @@ +from tests.integration.feature_repos.integration_test_repo_config import ( + IntegrationTestRepoConfig, +) +from tests.integration.feature_repos.universal.data_sources.trino import ( + TrinoSourceCreator, +) + +FULL_REPO_CONFIGS = [ + IntegrationTestRepoConfig( + provider="local", offline_store_creator=TrinoSourceCreator, + ), +] diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/properties/memory.properties b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/properties/memory.properties new file mode 100644 index 00000000000..6a291def3c3 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/properties/memory.properties @@ -0,0 +1,2 @@ +connector.name=memory +memory.max-data-per-node=128MB \ No newline at end of file diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py new file mode 100644 index 00000000000..442bdf66569 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py @@ -0,0 +1,573 @@ +import uuid +from datetime import date, datetime +from typing import Any, Dict, List, Optional, Tuple, Union + +import numpy as np +import pandas as pd +import pyarrow +from pydantic import StrictStr +from trino.auth import Authentication + +from feast.data_source import DataSource +from feast.errors import InvalidEntityType +from feast.feature_view import DUMMY_ENTITY_ID, DUMMY_ENTITY_VAL, FeatureView +from feast.infra.offline_stores import offline_utils +from feast.infra.offline_stores.contrib.trino_offline_store.connectors.upload import ( + upload_pandas_dataframe_to_trino, +) +from feast.infra.offline_stores.contrib.trino_offline_store.trino_queries import Trino +from feast.infra.offline_stores.contrib.trino_offline_store.trino_source import ( + SavedDatasetTrinoStorage, + TrinoSource, +) +from feast.infra.offline_stores.offline_store import ( + OfflineStore, + RetrievalJob, + RetrievalMetadata, +) +from feast.on_demand_feature_view import OnDemandFeatureView +from feast.registry import Registry +from feast.repo_config import FeastConfigBaseModel, RepoConfig +from feast.saved_dataset import SavedDatasetStorage +from feast.usage import log_exceptions_and_usage + + +class TrinoOfflineStoreConfig(FeastConfigBaseModel): + """Online store config for Trino""" + + type: StrictStr = "trino" + """ Offline store type selector """ + + host: StrictStr + """ Host of the Trino cluster """ + + port: int + """ Port of the Trino cluster """ + + catalog: StrictStr + """ Catalog of the Trino cluster """ + + connector: Dict[str, str] + """ + Trino connector to use as well as potential extra parameters. + Needs to contain at least the path, for example + {"type": "bigquery"} + or + {"type": "hive", "file_format": "parquet"} + """ + + dataset: StrictStr = "feast" + """ (optional) Trino Dataset name for temporary tables """ + + +class TrinoRetrievalJob(RetrievalJob): + def __init__( + self, + query: str, + client: Trino, + config: RepoConfig, + full_feature_names: bool, + on_demand_feature_views: Optional[List[OnDemandFeatureView]] = None, + metadata: Optional[RetrievalMetadata] = None, + ): + self._query = query + self._client = client + self._config = config + self._full_feature_names = full_feature_names + self._on_demand_feature_views = on_demand_feature_views + self._metadata = metadata + + @property + def full_feature_names(self) -> bool: + return self._full_feature_names + + @property + def on_demand_feature_views(self) -> Optional[List[OnDemandFeatureView]]: + return self._on_demand_feature_views + + def _to_df_internal(self) -> pd.DataFrame: + """Return dataset as Pandas DataFrame synchronously including on demand transforms""" + results = self._client.execute_query(query_text=self._query) + self.pyarrow_schema = results.pyarrow_schema + return results.to_dataframe() + + def _to_arrow_internal(self) -> pyarrow.Table: + """Return payrrow dataset as synchronously including on demand transforms""" + return pyarrow.Table.from_pandas( + self._to_df_internal(), schema=self.pyarrow_schema + ) + + def to_sql(self) -> str: + """Returns the SQL query that will be executed in Trino to build the historical feature table""" + return self._query + + def to_trino( + self, + destination_table: Optional[str] = None, + timeout: int = 1800, + retry_cadence: int = 10, + ) -> Optional[str]: + """ + Triggers the execution of a historical feature retrieval query and exports the results to a Trino table. + Runs for a maximum amount of time specified by the timeout parameter (defaulting to 30 minutes). + Args: + timeout: An optional number of seconds for setting the time limit of the QueryJob. + retry_cadence: An optional number of seconds for setting how long the job should checked for completion. + Returns: + Returns the destination table name. + """ + if not destination_table: + today = date.today().strftime("%Y%m%d") + rand_id = str(uuid.uuid4())[:7] + destination_table = f"{self._client.catalog}.{self._config.offline_store.dataset}.historical_{today}_{rand_id}" + + # TODO: Implement the timeout logic + query = f"CREATE TABLE {destination_table} AS ({self._query})" + self._client.execute_query(query_text=query) + return destination_table + + def persist(self, storage: SavedDatasetStorage): + """ + Run the retrieval and persist the results in the same offline store used for read. + """ + if not isinstance(storage, SavedDatasetTrinoStorage): + raise ValueError( + f"The storage object is not a `SavedDatasetTrinoStorage` but is instead a {type(storage)}" + ) + self.to_trino(destination_table=storage.trino_options.table) + + @property + def metadata(self) -> Optional[RetrievalMetadata]: + """ + Return metadata information about retrieval. + Should be available even before materializing the dataset itself. + """ + return self._metadata + + +class TrinoOfflineStore(OfflineStore): + @staticmethod + @log_exceptions_and_usage(offline_store="trino") + def pull_latest_from_table_or_query( + config: RepoConfig, + data_source: DataSource, + join_key_columns: List[str], + feature_name_columns: List[str], + event_timestamp_column: str, + created_timestamp_column: Optional[str], + start_date: datetime, + end_date: datetime, + user: str = "user", + auth: Optional[Authentication] = None, + http_scheme: Optional[str] = None, + ) -> TrinoRetrievalJob: + if not isinstance(data_source, TrinoSource): + raise ValueError( + f"The data_source object is not a TrinoSource but is instead '{type(data_source)}'" + ) + if not isinstance(config.offline_store, TrinoOfflineStoreConfig): + raise ValueError( + f"The config.offline_store object is not a TrinoOfflineStoreConfig but is instead '{type(config.offline_store)}'" + ) + + from_expression = data_source.get_table_query_string() + + partition_by_join_key_string = ", ".join(join_key_columns) + if partition_by_join_key_string != "": + partition_by_join_key_string = ( + "PARTITION BY " + partition_by_join_key_string + ) + timestamps = [event_timestamp_column] + if created_timestamp_column: + timestamps.append(created_timestamp_column) + timestamp_desc_string = " DESC, ".join(timestamps) + " DESC" + field_string = ", ".join(join_key_columns + feature_name_columns + timestamps) + + client = _get_trino_client( + config=config, user=user, auth=auth, http_scheme=http_scheme + ) + + query = f""" + SELECT + {field_string} + {f", {repr(DUMMY_ENTITY_VAL)} AS {DUMMY_ENTITY_ID}" if not join_key_columns else ""} + FROM ( + SELECT {field_string}, + ROW_NUMBER() OVER({partition_by_join_key_string} ORDER BY {timestamp_desc_string}) AS _feast_row + FROM {from_expression} + WHERE {event_timestamp_column} BETWEEN TIMESTAMP '{start_date}' AND TIMESTAMP '{end_date}' + ) + WHERE _feast_row = 1 + """ + + # When materializing a single feature view, we don't need full feature names. On demand transforms aren't materialized + return TrinoRetrievalJob( + query=query, client=client, config=config, full_feature_names=False, + ) + + @staticmethod + @log_exceptions_and_usage(offline_store="trino") + def get_historical_features( + config: RepoConfig, + feature_views: List[FeatureView], + feature_refs: List[str], + entity_df: Union[pd.DataFrame, str], + registry: Registry, + project: str, + full_feature_names: bool = False, + user: str = "user", + auth: Optional[Authentication] = None, + http_scheme: Optional[str] = None, + ) -> TrinoRetrievalJob: + if not isinstance(config.offline_store, TrinoOfflineStoreConfig): + raise ValueError( + f"This function should be used with a TrinoOfflineStoreConfig object. Instead we have config.offline_store being '{type(config.offline_store)}'" + ) + + client = _get_trino_client( + config=config, user=user, auth=auth, http_scheme=http_scheme + ) + + table_reference = _get_table_reference_for_new_entity( + catalog=config.offline_store.catalog, + dataset_name=config.offline_store.dataset, + ) + + entity_schema = _upload_entity_df_and_get_entity_schema( + client=client, + table_name=table_reference, + entity_df=entity_df, + connector=config.offline_store.connector, + ) + + entity_df_event_timestamp_col = offline_utils.infer_event_timestamp_from_entity_df( + entity_schema=entity_schema + ) + + entity_df_event_timestamp_range = _get_entity_df_event_timestamp_range( + entity_df=entity_df, + entity_df_event_timestamp_col=entity_df_event_timestamp_col, + client=client, + ) + + expected_join_keys = offline_utils.get_expected_join_keys( + project=project, feature_views=feature_views, registry=registry + ) + + offline_utils.assert_expected_columns_in_entity_df( + entity_schema=entity_schema, + join_keys=expected_join_keys, + entity_df_event_timestamp_col=entity_df_event_timestamp_col, + ) + + # Build a query context containing all information required to template the Trino SQL query + query_context = offline_utils.get_feature_view_query_context( + feature_refs=feature_refs, + feature_views=feature_views, + registry=registry, + project=project, + entity_df_timestamp_range=entity_df_event_timestamp_range, + ) + + # Generate the Trino SQL query from the query context + query = offline_utils.build_point_in_time_query( + query_context, + left_table_query_string=table_reference, + entity_df_event_timestamp_col=entity_df_event_timestamp_col, + entity_df_columns=entity_schema.keys(), + query_template=MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN, + full_feature_names=full_feature_names, + ) + + return TrinoRetrievalJob( + query=query, + client=client, + config=config, + full_feature_names=full_feature_names, + on_demand_feature_views=OnDemandFeatureView.get_requested_odfvs( + feature_refs, project, registry + ), + metadata=RetrievalMetadata( + features=feature_refs, + keys=list(set(entity_schema.keys()) - {entity_df_event_timestamp_col}), + min_event_timestamp=entity_df_event_timestamp_range[0], + max_event_timestamp=entity_df_event_timestamp_range[1], + ), + ) + + @staticmethod + @log_exceptions_and_usage(offline_store="trino") + def pull_all_from_table_or_query( + config: RepoConfig, + data_source: DataSource, + join_key_columns: List[str], + feature_name_columns: List[str], + event_timestamp_column: str, + start_date: datetime, + end_date: datetime, + user: str = "user", + auth: Optional[Authentication] = None, + http_scheme: Optional[str] = None, + ) -> RetrievalJob: + if not isinstance(data_source, TrinoSource): + raise ValueError( + f"The data_source object is not a TrinoSource object but is instead a {type(data_source)}" + ) + from_expression = data_source.get_table_query_string() + + client = _get_trino_client( + config=config, user=user, auth=auth, http_scheme=http_scheme + ) + field_string = ", ".join( + join_key_columns + feature_name_columns + [event_timestamp_column] + ) + query = f""" + SELECT {field_string} + FROM {from_expression} + WHERE {event_timestamp_column} BETWEEN TIMESTAMP '{start_date}' AND TIMESTAMP '{end_date}' + """ + return TrinoRetrievalJob( + query=query, client=client, config=config, full_feature_names=False, + ) + + +def _get_table_reference_for_new_entity(catalog: str, dataset_name: str,) -> str: + """Gets the table_id for the new entity to be uploaded.""" + table_name = offline_utils.get_temp_entity_table_name() + return f"{catalog}.{dataset_name}.{table_name}" + + +def _upload_entity_df_and_get_entity_schema( + client: Trino, + table_name: str, + entity_df: Union[pd.DataFrame, str], + connector: Dict[str, str], +) -> Dict[str, np.dtype]: + """Uploads a Pandas entity dataframe into a Trino table and returns the resulting table""" + if type(entity_df) is str: + client.execute_query(f"CREATE TABLE {table_name} AS ({entity_df})") + + results = client.execute_query(f"SELECT * FROM {table_name} LIMIT 1") + + limited_entity_df = pd.DataFrame( + data=results.data, columns=results.columns_names + ) + for col_name, col_type in results.schema.items(): + if col_type == "timestamp": + limited_entity_df[col_name] = pd.to_datetime( + limited_entity_df[col_name] + ) + entity_schema = dict(zip(limited_entity_df.columns, limited_entity_df.dtypes)) + + return entity_schema + elif isinstance(entity_df, pd.DataFrame): + upload_pandas_dataframe_to_trino( + client=client, df=entity_df, table=table_name, connector_args=connector + ) + entity_schema = dict(zip(entity_df.columns, entity_df.dtypes)) + return entity_schema + else: + raise InvalidEntityType(type(entity_df)) + + # TODO: Ensure that the table expires after some time + + +def _get_trino_client( + config: RepoConfig, user: str, auth: Optional[Any], http_scheme: Optional[str] +) -> Trino: + client = Trino( + user=user, + catalog=config.offline_store.catalog, + host=config.offline_store.host, + port=config.offline_store.port, + auth=auth, + http_scheme=http_scheme, + ) + return client + + +def _get_entity_df_event_timestamp_range( + entity_df: Union[pd.DataFrame, str], + entity_df_event_timestamp_col: str, + client: Trino, +) -> Tuple[datetime, datetime]: + if type(entity_df) is str: + results = client.execute_query( + f"SELECT MIN({entity_df_event_timestamp_col}) AS min, MAX({entity_df_event_timestamp_col}) AS max " + f"FROM ({entity_df})" + ) + + entity_df_event_timestamp_range = ( + pd.to_datetime(results.data[0][0]).to_pydatetime(), + pd.to_datetime(results.data[0][1]).to_pydatetime(), + ) + elif isinstance(entity_df, pd.DataFrame): + entity_df_event_timestamp = entity_df.loc[ + :, entity_df_event_timestamp_col + ].infer_objects() + if pd.api.types.is_string_dtype(entity_df_event_timestamp): + entity_df_event_timestamp = pd.to_datetime( + entity_df_event_timestamp, utc=True + ) + entity_df_event_timestamp_range = ( + entity_df_event_timestamp.min().to_pydatetime(), + entity_df_event_timestamp.max().to_pydatetime(), + ) + else: + raise InvalidEntityType(type(entity_df)) + + return entity_df_event_timestamp_range + + +MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN = """ +/* + Compute a deterministic hash for the `left_table_query_string` that will be used throughout + all the logic as the field to GROUP BY the data +*/ +WITH entity_dataframe AS ( + SELECT *, + {{entity_df_event_timestamp_col}} AS entity_timestamp + {% for featureview in featureviews %} + {% if featureview.entities %} + ,CONCAT( + {% for entity in featureview.entities %} + CAST({{entity}} AS VARCHAR), + {% endfor %} + CAST({{entity_df_event_timestamp_col}} AS VARCHAR) + ) AS {{featureview.name}}__entity_row_unique_id + {% else %} + ,CAST({{entity_df_event_timestamp_col}} AS VARCHAR) AS {{featureview.name}}__entity_row_unique_id + {% endif %} + {% endfor %} + FROM {{ left_table_query_string }} +), +{% for featureview in featureviews %} +{{ featureview.name }}__entity_dataframe AS ( + SELECT + {{ featureview.entities | join(', ')}}{% if featureview.entities %},{% else %}{% endif %} + entity_timestamp, + {{featureview.name}}__entity_row_unique_id + FROM entity_dataframe + GROUP BY + {{ featureview.entities | join(', ')}}{% if featureview.entities %},{% else %}{% endif %} + entity_timestamp, + {{featureview.name}}__entity_row_unique_id +), +/* + This query template performs the point-in-time correctness join for a single feature set table + to the provided entity table. + 1. We first join the current feature_view to the entity dataframe that has been passed. + This JOIN has the following logic: + - For each row of the entity dataframe, only keep the rows where the `event_timestamp_column` + is less than the one provided in the entity dataframe + - If there a TTL for the current feature_view, also keep the rows where the `event_timestamp_column` + is higher the the one provided minus the TTL + - For each row, Join on the entity key and retrieve the `entity_row_unique_id` that has been + computed previously + The output of this CTE will contain all the necessary information and already filtered out most + of the data that is not relevant. +*/ +{{ featureview.name }}__subquery AS ( + SELECT + {{ featureview.event_timestamp_column }} as event_timestamp, + {{ featureview.created_timestamp_column ~ ' as created_timestamp,' if featureview.created_timestamp_column else '' }} + {{ featureview.entity_selections | join(', ')}}{% if featureview.entity_selections %},{% else %}{% endif %} + {% for feature in featureview.features %} + {{ feature }} as {% if full_feature_names %}{{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %}{{ featureview.field_mapping.get(feature, feature) }}{% endif %}{% if loop.last %}{% else %}, {% endif %} + {% endfor %} + FROM {{ featureview.table_subquery }} + WHERE {{ featureview.event_timestamp_column }} <= from_iso8601_timestamp('{{ featureview.max_event_timestamp }}') + {% if featureview.ttl == 0 %}{% else %} + AND {{ featureview.event_timestamp_column }} >= from_iso8601_timestamp('{{ featureview.min_event_timestamp }}') + {% endif %} +), +{{ featureview.name }}__base AS ( + SELECT + subquery.*, + entity_dataframe.entity_timestamp, + entity_dataframe.{{featureview.name}}__entity_row_unique_id + FROM {{ featureview.name }}__subquery AS subquery + INNER JOIN {{ featureview.name }}__entity_dataframe AS entity_dataframe + ON TRUE + AND subquery.event_timestamp <= entity_dataframe.entity_timestamp + {% if featureview.ttl == 0 %}{% else %} + AND subquery.event_timestamp >= entity_dataframe.entity_timestamp - interval '{{ featureview.ttl }}' second + {% endif %} + {% for entity in featureview.entities %} + AND subquery.{{ entity }} = entity_dataframe.{{ entity }} + {% endfor %} +), +/* + 2. If the `created_timestamp_column` has been set, we need to + deduplicate the data first. This is done by calculating the + `MAX(created_at_timestamp)` for each event_timestamp. + We then join the data on the next CTE +*/ +{% if featureview.created_timestamp_column %} +{{ featureview.name }}__dedup AS ( + SELECT + {{featureview.name}}__entity_row_unique_id, + event_timestamp, + MAX(created_timestamp) as created_timestamp + FROM {{ featureview.name }}__base + GROUP BY {{featureview.name}}__entity_row_unique_id, event_timestamp +), +{% endif %} +/* + 3. The data has been filtered during the first CTE "*__base" + Thus we only need to compute the latest timestamp of each feature. +*/ +{{ featureview.name }}__latest AS ( + SELECT + event_timestamp, + {% if featureview.created_timestamp_column %}created_timestamp,{% endif %} + {{featureview.name}}__entity_row_unique_id + FROM + ( + SELECT *, + ROW_NUMBER() OVER( + PARTITION BY {{featureview.name}}__entity_row_unique_id + ORDER BY event_timestamp DESC{% if featureview.created_timestamp_column %},created_timestamp DESC{% endif %} + ) AS row_number + FROM {{ featureview.name }}__base + {% if featureview.created_timestamp_column %} + INNER JOIN {{ featureview.name }}__dedup + USING ({{featureview.name}}__entity_row_unique_id, event_timestamp, created_timestamp) + {% endif %} + ) + WHERE row_number = 1 +), +/* + 4. Once we know the latest value of each feature for a given timestamp, + we can join again the data back to the original "base" dataset +*/ +{{ featureview.name }}__cleaned AS ( + SELECT base.*, {{featureview.name}}__entity_row_unique_id + FROM {{ featureview.name }}__base as base + INNER JOIN {{ featureview.name }}__latest + USING( + {{featureview.name}}__entity_row_unique_id, + event_timestamp + {% if featureview.created_timestamp_column %} + ,created_timestamp + {% endif %} + ) +){% if loop.last %}{% else %}, {% endif %} +{% endfor %} +/* + Joins the outputs of multiple time travel joins to a single table. + The entity_dataframe dataset being our source of truth here. + */ +SELECT {{ final_output_feature_names | join(', ')}} +FROM entity_dataframe +{% for featureview in featureviews %} +LEFT JOIN ( + SELECT + {{featureview.name}}__entity_row_unique_id + {% for feature in featureview.features %} + ,{% if full_feature_names %}{{ featureview.name }}__{{featureview.field_mapping.get(feature, feature)}}{% else %}{{ featureview.field_mapping.get(feature, feature) }}{% endif %} + {% endfor %} + FROM {{ featureview.name }}__cleaned +) USING ({{featureview.name}}__entity_row_unique_id) +{% endfor %} +""" diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_queries.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_queries.py new file mode 100644 index 00000000000..1d4b5881240 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_queries.py @@ -0,0 +1,151 @@ +from __future__ import annotations + +import datetime +import os +import signal +from dataclasses import dataclass +from enum import Enum +from typing import Any, Dict, List, Optional + +import numpy as np +import pandas as pd +import pyarrow as pa +import trino +from trino.dbapi import Cursor +from trino.exceptions import TrinoQueryError + +from feast.infra.offline_stores.contrib.trino_offline_store.trino_type_map import ( + trino_to_pa_value_type, +) + + +class QueryStatus(Enum): + PENDING = 0 + RUNNING = 1 + ERROR = 2 + COMPLETED = 3 + CANCELLED = 4 + + +class Trino: + def __init__( + self, + host: Optional[str] = None, + port: Optional[int] = None, + user: Optional[str] = None, + catalog: Optional[str] = None, + auth: Optional[Any] = None, + http_scheme: Optional[str] = None, + ): + self.host = host or os.getenv("TRINO_HOST") + self.port = port or os.getenv("TRINO_PORT") + self.user = user or os.getenv("TRINO_USER") + self.catalog = catalog or os.getenv("TRINO_CATALOG") + self.auth = auth or os.getenv("TRINO_AUTH") + self.http_scheme = http_scheme or os.getenv("TRINO_HTTP_SCHEME") + self._cursor: Optional[Cursor] = None + + if self.host is None: + raise ValueError("TRINO_HOST must be set if not passed in") + if self.port is None: + raise ValueError("TRINO_PORT must be set if not passed in") + if self.user is None: + raise ValueError("TRINO_USER must be set if not passed in") + if self.catalog is None: + raise ValueError("TRINO_CATALOG must be set if not passed in") + + def _get_cursor(self) -> Cursor: + if self._cursor is None: + self._cursor = trino.dbapi.connect( + host=self.host, + port=self.port, + user=self.user, + catalog=self.catalog, + auth=self.auth, + http_scheme=self.http_scheme, + ).cursor() + + return self._cursor + + def create_query(self, query_text: str) -> Query: + """ + Create a Query object without executing it. + """ + return Query(query_text=query_text, cursor=self._get_cursor()) + + def execute_query(self, query_text: str) -> Results: + """ + Create a Query object and execute it. + """ + query = Query(query_text=query_text, cursor=self._get_cursor()) + return query.execute() + + +class Query(object): + def __init__(self, query_text: str, cursor: Cursor): + self.query_text = query_text + self.status = QueryStatus.PENDING + self._cursor = cursor + + signal.signal(signal.SIGINT, self.cancel) + signal.signal(signal.SIGTERM, self.cancel) + + def execute(self) -> Results: + try: + self.status = QueryStatus.RUNNING + start_time = datetime.datetime.utcnow() + + self._cursor.execute(operation=self.query_text) + rows = self._cursor.fetchall() + + end_time = datetime.datetime.utcnow() + self.execution_time = end_time - start_time + self.status = QueryStatus.COMPLETED + + return Results(data=rows, columns=self._cursor._query.columns) + except TrinoQueryError as error: + self.status = QueryStatus.ERROR + raise error + finally: + self.close() + + def close(self): + self._cursor.close() + + def cancel(self, *args): + if self.status != QueryStatus.COMPLETED: + self._cursor.cancel() + self.status = QueryStatus.CANCELLED + self.close() + + +@dataclass +class Results: + """Class for keeping track of the results of a Trino query""" + + data: List[List[Any]] + columns: List[Dict] + + @property + def columns_names(self) -> List[str]: + return [column["name"] for column in self.columns] + + @property + def schema(self) -> Dict[str, str]: + return {column["name"]: column["type"] for column in self.columns} + + @property + def pyarrow_schema(self) -> pa.Schema: + return pa.schema( + [ + pa.field(column["name"], trino_to_pa_value_type(column["type"])) + for column in self.columns + ] + ) + + def to_dataframe(self) -> pd.DataFrame: + df = pd.DataFrame(data=self.data, columns=self.columns_names) + for col_name, col_type in self.schema.items(): + if col_type.startswith("timestamp"): + df[col_name] = pd.to_datetime(df[col_name]) + return df.fillna(np.nan) diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_source.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_source.py new file mode 100644 index 00000000000..7d6280746ec --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_source.py @@ -0,0 +1,242 @@ +from typing import Callable, Dict, Iterable, Optional, Tuple + +from feast import ValueType +from feast.data_source import DataSource +from feast.infra.offline_stores.contrib.trino_offline_store.trino_queries import Trino +from feast.infra.offline_stores.contrib.trino_offline_store.trino_type_map import ( + trino_to_feast_value_type, +) +from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto +from feast.protos.feast.core.SavedDataset_pb2 import ( + SavedDatasetStorage as SavedDatasetStorageProto, +) +from feast.repo_config import RepoConfig +from feast.saved_dataset import SavedDatasetStorage + + +class TrinoOptions: + """ + DataSource Trino options used to source features from Trino query + """ + + def __init__(self, table: Optional[str], query: Optional[str]): + self._table = table + self._query = query + + @property + def query(self): + """ + Returns the Trino SQL query referenced by this source + """ + return self._query + + @query.setter + def query(self, query): + """ + Sets the Trino SQL query referenced by this source + """ + self._query = query + + @property + def table(self): + """ + Returns the table ref of this Trino table + """ + return self._table + + @table.setter + def table(self, table): + """ + Sets the table ref of this Trino table + """ + self._table = table + + @classmethod + def from_proto(cls, trino_options_proto: DataSourceProto.TrinoOptions): + """ + Creates a TrinoOptions from a protobuf representation of a Trino option + Args: + trino_options_proto: A protobuf representation of a DataSource + Returns: + Returns a TrinoOptions object based on the trino_options protobuf + """ + trino_options = cls( + table=trino_options_proto.table, query=trino_options_proto.query, + ) + + return trino_options + + def to_proto(self) -> DataSourceProto.TrinoOptions: + """ + Converts an TrinoOptionsProto object to its protobuf representation. + Returns: + TrinoOptionsProto protobuf + """ + + trino_options_proto = DataSourceProto.TrinoOptions( + table=self.table, query=self.query, + ) + + return trino_options_proto + + +class TrinoSource(DataSource): + def __init__( + self, + *, + event_timestamp_column: Optional[str] = "", + table: Optional[str] = None, + created_timestamp_column: Optional[str] = "", + field_mapping: Optional[Dict[str, str]] = None, + date_partition_column: Optional[str] = None, + query: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = None, + ): + super().__init__( + name=name if name else "", + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + description=description, + tags=tags, + owner=owner, + timestamp_field=timestamp_field, + ) + + self._trino_options = TrinoOptions(table=table, query=query) + + def __hash__(self): + return super().__hash__() + + def __eq__(self, other): + if not isinstance(other, TrinoSource): + raise TypeError( + "Comparisons should only involve TrinoSource class objects." + ) + + return ( + self.name == other.name + and self.trino_options.table == other.trino_options.table + and self.trino_options.query == other.trino_options.query + and self.timestamp_field == other.timestamp_field + and self.created_timestamp_column == other.created_timestamp_column + and self.field_mapping == other.field_mapping + and self.description == other.description + and self.tags == other.tags + and self.owner == other.owner + ) + + @property + def table(self): + return self._trino_options.table + + @property + def query(self): + return self._trino_options.query + + @property + def trino_options(self): + """ + Returns the Trino options of this data source + """ + return self._trino_options + + @trino_options.setter + def trino_options(self, trino_options): + """ + Sets the Trino options of this data source + """ + self._trino_options = trino_options + + @staticmethod + def from_proto(data_source: DataSourceProto): + + assert data_source.HasField("trino_options") + + return TrinoSource( + name=data_source.name, + field_mapping=dict(data_source.field_mapping), + table=data_source.trino_options.table, + query=data_source.trino_options.query, + timestamp_field=data_source.timestamp_field, + created_timestamp_column=data_source.created_timestamp_column, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, + ) + + def to_proto(self) -> DataSourceProto: + data_source_proto = DataSourceProto( + name=self.name, + type=DataSourceProto.BATCH_TRINO, + field_mapping=self.field_mapping, + trino_options=self.trino_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, + ) + + data_source_proto.timestamp_field = self.timestamp_field + data_source_proto.created_timestamp_column = self.created_timestamp_column + data_source_proto.date_partition_column = self.date_partition_column + + return data_source_proto + + def validate(self, config: RepoConfig): + self.get_table_column_names_and_types(config) + + def get_table_query_string(self) -> str: + """Returns a string that can directly be used to reference this table in SQL""" + return self.table or self.query + + @staticmethod + def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: + return trino_to_feast_value_type + + def get_table_column_names_and_types( + self, config: RepoConfig + ) -> Iterable[Tuple[str, str]]: + client = Trino( + user="user", + catalog=config.offline_store.catalog, + host=config.offline_store.host, + port=config.offline_store.port, + ) + if self.table is not None: + table_schema = client.execute_query( + f"SELECT * FROM {self.table} LIMIT 1" + ).schema + else: + table_schema = client.execute_query( + f"SELECT * FROM ({self.query}) LIMIT 1" + ).schema + + return [ + (field_name, field_type) for field_name, field_type in table_schema.items() + ] + + +class SavedDatasetTrinoStorage(SavedDatasetStorage): + _proto_attr_name = "trino_storage" + + trino_options: TrinoOptions + + def __init__(self, table: Optional[str] = None, query: Optional[str] = None): + self.trino_options = TrinoOptions(table=table, query=query) + + @staticmethod + def from_proto(storage_proto: SavedDatasetStorageProto) -> SavedDatasetStorage: + # TODO: implementation is not correct. Needs fix and update to protos. + return SavedDatasetTrinoStorage( + table=TrinoOptions.from_proto(storage_proto.trino_storage).table + ) + + def to_proto(self) -> SavedDatasetStorageProto: + return SavedDatasetStorageProto(trino_storage=self.trino_options.to_proto()) + + def to_data_source(self) -> DataSource: + return TrinoSource(table=self.trino_options.table) diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_type_map.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_type_map.py new file mode 100644 index 00000000000..79066bbfa4d --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_type_map.py @@ -0,0 +1,111 @@ +from typing import Dict + +import pyarrow as pa +import regex as re + +from feast import ValueType + + +def trino_to_feast_value_type(trino_type_as_str: str) -> ValueType: + type_map: Dict[str, ValueType] = { + "tinyint": ValueType.INT32, + "smallint": ValueType.INT32, + "int": ValueType.INT32, + "integer": ValueType.INT32, + "bigint": ValueType.INT64, + "double": ValueType.DOUBLE, + "decimal": ValueType.FLOAT, + "timestamp": ValueType.UNIX_TIMESTAMP, + "char": ValueType.STRING, + "varchar": ValueType.STRING, + "boolean": ValueType.BOOL, + } + return type_map[trino_type_as_str.lower()] + + +def pa_to_trino_value_type(pa_type_as_str: str) -> str: + # PyArrow types: https://arrow.apache.org/docs/python/api/datatypes.html + # Trino type: https://trino.io/docs/current/language/types.html + pa_type_as_str = pa_type_as_str.lower() + trino_type = "{}" + if pa_type_as_str.startswith("list"): + trino_type = "array<{}>" + pa_type_as_str = re.search(r"^list$", pa_type_as_str).group(1) + + if pa_type_as_str.startswith("date"): + return trino_type.format("date") + + if pa_type_as_str.startswith("timestamp"): + if "tz=" in pa_type_as_str: + return trino_type.format("timestamp with time zone") + else: + return trino_type.format("timestamp") + + if pa_type_as_str.startswith("decimal"): + return trino_type.format(pa_type_as_str) + + type_map = { + "null": "null", + "bool": "boolean", + "int8": "tinyint", + "int16": "smallint", + "int32": "int", + "int64": "bigint", + "uint8": "smallint", + "uint16": "int", + "uint32": "bigint", + "uint64": "bigint", + "float": "double", + "double": "double", + "binary": "binary", + "string": "varchar", + } + return trino_type.format(type_map[pa_type_as_str]) + + +_TRINO_TO_PA_TYPE_MAP = { + "null": pa.null(), + "boolean": pa.bool_(), + "date": pa.date32(), + "tinyint": pa.int8(), + "smallint": pa.int16(), + "integer": pa.int32(), + "bigint": pa.int64(), + "double": pa.float64(), + "binary": pa.binary(), + "char": pa.string(), +} + + +def trino_to_pa_value_type(trino_type_as_str: str) -> pa.DataType: + trino_type_as_str = trino_type_as_str.lower() + + _is_list: bool = False + if trino_type_as_str.startswith("array"): + _is_list = True + trino_type_as_str = re.search(r"^array\((\w+)\)$", trino_type_as_str).group(1) + + if trino_type_as_str.startswith("decimal"): + search_precision = re.search( + r"^decimal\((\d+)(?>,\s?\d+)?\)$", trino_type_as_str + ) + if search_precision: + precision = int(search_precision.group(1)) + if precision > 32: + pa_type = pa.float64() + else: + pa_type = pa.float32() + + elif trino_type_as_str.startswith("timestamp"): + pa_type = pa.timestamp("us") + + elif trino_type_as_str.startswith("varchar"): + pa_type = pa.string() + + else: + pa_type = _TRINO_TO_PA_TYPE_MAP[trino_type_as_str] + + if _is_list: + return pa.list_(pa_type) + else: + return pa_type diff --git a/sdk/python/feast/infra/offline_stores/file.py b/sdk/python/feast/infra/offline_stores/file.py index c71f0c3ff74..cb6e874f8a9 100644 --- a/sdk/python/feast/infra/offline_stores/file.py +++ b/sdk/python/feast/infra/offline_stores/file.py @@ -31,7 +31,7 @@ class FileOfflineStoreConfig(FeastConfigBaseModel): - """ Offline store config for local (file-based) store """ + """Offline store config for local (file-based) store""" type: Literal["file"] = "file" """ Offline store type selector""" @@ -77,9 +77,8 @@ def _to_arrow_internal(self): def persist(self, storage: SavedDatasetStorage): assert isinstance(storage, SavedDatasetFileStorage) - filesystem, path = FileSource.create_filesystem_and_path( - storage.file_options.file_url, storage.file_options.s3_endpoint_override, + storage.file_options.uri, storage.file_options.s3_endpoint_override, ) if path.endswith(".parquet"): @@ -187,9 +186,7 @@ def evaluate_historical_retrieval(): # Load feature view data from sources and join them incrementally for feature_view, features in feature_views_to_features.items(): - event_timestamp_column = ( - feature_view.batch_source.event_timestamp_column - ) + event_timestamp_column = feature_view.batch_source.timestamp_field created_timestamp_column = ( feature_view.batch_source.created_timestamp_column ) diff --git a/sdk/python/feast/infra/offline_stores/file_source.py b/sdk/python/feast/infra/offline_stores/file_source.py index 59e703dd6fb..3df0db69b1c 100644 --- a/sdk/python/feast/infra/offline_stores/file_source.py +++ b/sdk/python/feast/infra/offline_stores/file_source.py @@ -1,3 +1,4 @@ +import warnings from typing import Callable, Dict, Iterable, Optional, Tuple from pyarrow._fs import FileSystem @@ -20,32 +21,42 @@ class FileSource(DataSource): def __init__( self, path: str, - name: Optional[str] = "", event_timestamp_column: Optional[str] = "", file_format: Optional[FileFormat] = None, created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, date_partition_column: Optional[str] = "", s3_endpoint_override: Optional[str] = None, + name: Optional[str] = "", + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = "", ): """Create a FileSource from a file containing feature data. Only Parquet format supported. Args: - name (optional): Name for the file source. Defaults to the path. path: File path to file containing feature data. Must contain an event_timestamp column, entity columns and feature columns. - event_timestamp_column: Event timestamp column used for point in time joins of feature values. + event_timestamp_column(optional): (Deprecated) Event timestamp column used for point in time joins of feature values. created_timestamp_column (optional): Timestamp column when row was created, used for deduplicating rows. file_format (optional): Explicitly set the file format. Allows Feast to bypass inferring the file format. field_mapping: A dictionary mapping of column names in this data source to feature names in a feature table or view. Only used for feature columns, not entities or timestamp columns. date_partition_column (optional): Timestamp column used for partitioning. s3_endpoint_override (optional): Overrides AWS S3 enpoint with custom S3 storage + name (optional): Name for the file source. Defaults to the path. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the file source, typically the email of the primary + maintainer. + timestamp_field (optional): Event timestamp foe;d used for point in time + joins of feature values. Examples: >>> from feast import FileSource - >>> file_source = FileSource(path="my_features.parquet", event_timestamp_column="event_timestamp") + >>> file_source = FileSource(path="my_features.parquet", timestamp_field="event_timestamp") """ if path is None: raise ValueError( @@ -53,16 +64,28 @@ def __init__( ) self.file_options = FileOptions( file_format=file_format, - file_url=path, + uri=path, s3_endpoint_override=s3_endpoint_override, ) + if date_partition_column: + warnings.warn( + ( + "The argument 'date_partition_column' is not supported for File sources." + "It will be removed in Feast 0.21+" + ), + DeprecationWarning, + ) + super().__init__( - name if name else path, - event_timestamp_column, - created_timestamp_column, - field_mapping, - date_partition_column, + name=name if name else path, + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + description=description, + tags=tags, + owner=owner, + timestamp_field=timestamp_field, ) # Note: Python requires redefining hash in child classes that override __eq__ @@ -75,13 +98,15 @@ def __eq__(self, other): return ( self.name == other.name - and self.file_options.file_url == other.file_options.file_url and self.file_options.file_format == other.file_options.file_format - and self.event_timestamp_column == other.event_timestamp_column + and self.timestamp_field == other.timestamp_field and self.created_timestamp_column == other.created_timestamp_column and self.field_mapping == other.field_mapping and self.file_options.s3_endpoint_override == other.file_options.s3_endpoint_override + and self.description == other.description + and self.tags == other.tags + and self.owner == other.owner ) @property @@ -89,7 +114,7 @@ def path(self): """ Returns the path of this file data source. """ - return self.file_options.file_url + return self.file_options.uri @staticmethod def from_proto(data_source: DataSourceProto): @@ -97,11 +122,13 @@ def from_proto(data_source: DataSourceProto): name=data_source.name, field_mapping=dict(data_source.field_mapping), file_format=FileFormat.from_proto(data_source.file_options.file_format), - path=data_source.file_options.file_url, - event_timestamp_column=data_source.event_timestamp_column, + path=data_source.file_options.uri, + timestamp_field=data_source.timestamp_field, created_timestamp_column=data_source.created_timestamp_column, - date_partition_column=data_source.date_partition_column, s3_endpoint_override=data_source.file_options.s3_endpoint_override, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, ) def to_proto(self) -> DataSourceProto: @@ -110,11 +137,13 @@ def to_proto(self) -> DataSourceProto: type=DataSourceProto.BATCH_FILE, field_mapping=self.field_mapping, file_options=self.file_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column - data_source_proto.date_partition_column = self.date_partition_column return data_source_proto @@ -161,19 +190,20 @@ class FileOptions: def __init__( self, file_format: Optional[FileFormat], - file_url: Optional[str], s3_endpoint_override: Optional[str], + uri: Optional[str], ): """ FileOptions initialization method Args: file_format (FileFormat, optional): file source format eg. parquet - file_url (str, optional): file source url eg. s3:// or local file - s3_endpoint_override (str, optional): custom s3 endpoint (used only with s3 file_url) + s3_endpoint_override (str, optional): custom s3 endpoint (used only with s3 uri) + uri (str, optional): file source url eg. s3:// or local file + """ self._file_format = file_format - self._file_url = file_url + self._uri = uri self._s3_endpoint_override = s3_endpoint_override @property @@ -191,18 +221,18 @@ def file_format(self, file_format): self._file_format = file_format @property - def file_url(self): + def uri(self): """ Returns the file url of this file """ - return self._file_url + return self._uri - @file_url.setter - def file_url(self, file_url): + @uri.setter + def uri(self, uri): """ Sets the file url of this file """ - self._file_url = file_url + self._uri = uri @property def s3_endpoint_override(self): @@ -231,7 +261,7 @@ def from_proto(cls, file_options_proto: DataSourceProto.FileOptions): """ file_options = cls( file_format=FileFormat.from_proto(file_options_proto.file_format), - file_url=file_options_proto.file_url, + uri=file_options_proto.uri, s3_endpoint_override=file_options_proto.s3_endpoint_override, ) return file_options @@ -243,12 +273,11 @@ def to_proto(self) -> DataSourceProto.FileOptions: Returns: FileOptionsProto protobuf """ - file_options_proto = DataSourceProto.FileOptions( file_format=( None if self.file_format is None else self.file_format.to_proto() ), - file_url=self.file_url, + uri=self.uri, s3_endpoint_override=self.s3_endpoint_override, ) @@ -267,16 +296,16 @@ def __init__( s3_endpoint_override: Optional[str] = None, ): self.file_options = FileOptions( - file_url=path, file_format=file_format, s3_endpoint_override=s3_endpoint_override, + uri=path, ) @staticmethod def from_proto(storage_proto: SavedDatasetStorageProto) -> SavedDatasetStorage: file_options = FileOptions.from_proto(storage_proto.file_storage) return SavedDatasetFileStorage( - path=file_options.file_url, + path=file_options.uri, file_format=file_options.file_format, s3_endpoint_override=file_options.s3_endpoint_override, ) @@ -286,7 +315,7 @@ def to_proto(self) -> SavedDatasetStorageProto: def to_data_source(self) -> DataSource: return FileSource( - path=self.file_options.file_url, + path=self.file_options.uri, file_format=self.file_options.file_format, s3_endpoint_override=self.file_options.s3_endpoint_override, ) diff --git a/sdk/python/feast/infra/offline_stores/offline_store.py b/sdk/python/feast/infra/offline_stores/offline_store.py index a3065a31c0e..e5937712f69 100644 --- a/sdk/python/feast/infra/offline_stores/offline_store.py +++ b/sdk/python/feast/infra/offline_stores/offline_store.py @@ -179,9 +179,24 @@ def pull_latest_from_table_or_query( end_date: datetime, ) -> RetrievalJob: """ + This method pulls data from the offline store, and the FeatureStore class is used to write + this data into the online store. This method is invoked when running materialization (using + the `feast materialize` or `feast materialize-incremental` commands, or the corresponding + FeatureStore.materialize() method. This method pulls data from the offline store, and the FeatureStore + class is used to write this data into the online store. + Note that join_key_columns, feature_name_columns, event_timestamp_column, and created_timestamp_column have all already been mapped to column names of the source table and those column names are the values passed into this function. + + Args: + config: Repo configuration object + data_source: Data source to pull all of the columns from + join_key_columns: Columns of the join keys + feature_name_columns: Columns of the feature names needed + event_timestamp_column: Timestamp column + start_date: Starting date of query + end_date: Ending date of query """ pass @@ -210,8 +225,19 @@ def pull_all_from_table_or_query( end_date: datetime, ) -> RetrievalJob: """ + Returns a Retrieval Job for all join key columns, feature name columns, and the event timestamp columns that occur between the start_date and end_date. + Note that join_key_columns, feature_name_columns, event_timestamp_column, and created_timestamp_column have all already been mapped to column names of the source table and those column names are the values passed into this function. + + Args: + config: Repo configuration object + data_source: Data source to pull all of the columns from + join_key_columns: Columns of the join keys + feature_name_columns: Columns of the feature names needed + event_timestamp_column: Timestamp column + start_date: Starting date of query + end_date: Ending date of query """ pass diff --git a/sdk/python/feast/infra/offline_stores/offline_utils.py b/sdk/python/feast/infra/offline_stores/offline_utils.py index eaf4925266d..c62d0223a03 100644 --- a/sdk/python/feast/infra/offline_stores/offline_utils.py +++ b/sdk/python/feast/infra/offline_stores/offline_utils.py @@ -101,8 +101,10 @@ def get_feature_view_query_context( project: str, entity_df_timestamp_range: Tuple[datetime, datetime], ) -> List[FeatureViewQueryContext]: - """Build a query context containing all information required to template a BigQuery and Redshift point-in-time SQL query""" - + """ + Build a query context containing all information required to template a BigQuery and + Redshift point-in-time SQL query + """ ( feature_views_to_feature_map, on_demand_feature_views_to_features, @@ -112,11 +114,7 @@ def get_feature_view_query_context( query_context = [] for feature_view, features in feature_views_to_feature_map.items(): - join_keys = [] - entity_selections = [] - reverse_field_mapping = { - v: k for k, v in feature_view.input.field_mapping.items() - } + join_keys, entity_selections = [], [] for entity_name in feature_view.entities: entity = registry.get_entity(entity_name, project) join_key = feature_view.projection.join_key_map.get( @@ -130,38 +128,42 @@ def get_feature_view_query_context( else: ttl_seconds = 0 - event_timestamp_column = feature_view.input.event_timestamp_column - created_timestamp_column = feature_view.input.created_timestamp_column + reverse_field_mapping = { + v: k for k, v in feature_view.batch_source.field_mapping.items() + } + features = [reverse_field_mapping.get(feature, feature) for feature in features] + timestamp_field = reverse_field_mapping.get( + feature_view.batch_source.timestamp_field, + feature_view.batch_source.timestamp_field, + ) + created_timestamp_column = reverse_field_mapping.get( + feature_view.batch_source.created_timestamp_column, + feature_view.batch_source.created_timestamp_column, + ) + max_event_timestamp = to_naive_utc(entity_df_timestamp_range[1]).isoformat() min_event_timestamp = None if feature_view.ttl: min_event_timestamp = to_naive_utc( entity_df_timestamp_range[0] - feature_view.ttl ).isoformat() - max_event_timestamp = to_naive_utc(entity_df_timestamp_range[1]).isoformat() - context = FeatureViewQueryContext( name=feature_view.projection.name_to_use(), ttl=ttl_seconds, entities=join_keys, - features=[ - reverse_field_mapping.get(feature, feature) for feature in features - ], - field_mapping=feature_view.input.field_mapping, - event_timestamp_column=reverse_field_mapping.get( - event_timestamp_column, event_timestamp_column - ), - created_timestamp_column=reverse_field_mapping.get( - created_timestamp_column, created_timestamp_column - ), + features=features, + field_mapping=feature_view.batch_source.field_mapping, + event_timestamp_column=timestamp_field, + created_timestamp_column=created_timestamp_column, # TODO: Make created column optional and not hardcoded - table_subquery=feature_view.input.get_table_query_string(), + table_subquery=feature_view.batch_source.get_table_query_string(), entity_selections=entity_selections, min_event_timestamp=min_event_timestamp, max_event_timestamp=max_event_timestamp, ) query_context.append(context) + return query_context diff --git a/sdk/python/feast/infra/offline_stores/redshift.py b/sdk/python/feast/infra/offline_stores/redshift.py index 3efd45bc741..e67cf13f5c4 100644 --- a/sdk/python/feast/infra/offline_stores/redshift.py +++ b/sdk/python/feast/infra/offline_stores/redshift.py @@ -39,7 +39,7 @@ class RedshiftOfflineStoreConfig(FeastConfigBaseModel): - """ Offline store config for AWS Redshift """ + """Offline store config for AWS Redshift""" type: Literal["redshift"] = "redshift" """ Offline store type selector""" @@ -341,7 +341,7 @@ def _to_arrow_internal(self) -> pa.Table: @log_exceptions_and_usage def to_s3(self) -> str: - """ Export dataset to S3 in Parquet format and return path """ + """Export dataset to S3 in Parquet format and return path""" if self.on_demand_feature_views: transformed_df = self.to_df() aws_utils.upload_df_to_s3(self._s3_resource, self._s3_path, transformed_df) @@ -361,7 +361,7 @@ def to_s3(self) -> str: @log_exceptions_and_usage def to_redshift(self, table_name: str) -> None: - """ Save dataset as a new Redshift table """ + """Save dataset as a new Redshift table""" if self.on_demand_feature_views: transformed_df = self.to_df() aws_utils.upload_df_to_redshift( diff --git a/sdk/python/feast/infra/offline_stores/redshift_source.py b/sdk/python/feast/infra/offline_stores/redshift_source.py index 19b88544a0e..f099e307cc8 100644 --- a/sdk/python/feast/infra/offline_stores/redshift_source.py +++ b/sdk/python/feast/infra/offline_stores/redshift_source.py @@ -1,12 +1,9 @@ +import warnings from typing import Callable, Dict, Iterable, Optional, Tuple from feast import type_map from feast.data_source import DataSource -from feast.errors import ( - DataSourceNoNameException, - DataSourceNotFoundException, - RedshiftCredentialsError, -) +from feast.errors import DataSourceNotFoundException, RedshiftCredentialsError from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.SavedDataset_pb2 import ( SavedDatasetStorage as SavedDatasetStorageProto, @@ -19,21 +16,25 @@ class RedshiftSource(DataSource): def __init__( self, - name: Optional[str] = None, event_timestamp_column: Optional[str] = "", table: Optional[str] = None, schema: Optional[str] = None, created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, - date_partition_column: Optional[str] = "", + date_partition_column: Optional[str] = None, query: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + database: Optional[str] = "", + timestamp_field: Optional[str] = "", ): """ Creates a RedshiftSource object. Args: - name (optional): Name for the source. Defaults to the table_ref if not specified. - event_timestamp_column (optional): Event timestamp column used for point in + event_timestamp_column (optional): (Deprecated) Event timestamp column used for point in time joins of feature values. table (optional): Redshift table where the features are stored. schema (optional): Redshift schema in which the table is located. @@ -41,9 +42,23 @@ def __init__( row was created, used for deduplicating rows. field_mapping (optional): A dictionary mapping of column names in this data source to column names in a feature table or view. - date_partition_column (optional): Timestamp column used for partitioning. + date_partition_column (deprecated): Timestamp column used for partitioning. query (optional): The query to be executed to obtain the features. + name (optional): Name for the source. Defaults to the table_ref if not specified. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the redshift source, typically the email of the primary + maintainer. + database (optional): The Redshift database name. + timestamp_field (optional): Event timestamp field used for point in time + joins of feature values. """ + # The default Redshift schema is named "public". + _schema = "public" if table and not schema else schema + self.redshift_options = RedshiftOptions( + table=table, schema=_schema, query=query, database=database + ) + if table is None and query is None: raise ValueError('No "table" argument provided.') _name = name @@ -51,22 +66,31 @@ def __init__( if table: _name = table else: - raise DataSourceNoNameException() + warnings.warn( + ( + f"Starting in Feast 0.21, Feast will require either a name for a data source (if using query) " + f"or `table`: {self.query}" + ), + DeprecationWarning, + ) + if date_partition_column: + warnings.warn( + ( + "The argument 'date_partition_column' is not supported for Redshift sources." + "It will be removed in Feast 0.21+" + ), + DeprecationWarning, + ) - # TODO(adchia): figure out what to do if user uses the query to start super().__init__( - _name, - event_timestamp_column, - created_timestamp_column, - field_mapping, - date_partition_column, - ) - - # The default Redshift schema is named "public". - _schema = "public" if table and not schema else schema - - self.redshift_options = RedshiftOptions( - table=table, schema=_schema, query=query + name=_name if _name else "", + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + description=description, + tags=tags, + owner=owner, + timestamp_field=timestamp_field, ) @staticmethod @@ -84,12 +108,19 @@ def from_proto(data_source: DataSourceProto): field_mapping=dict(data_source.field_mapping), table=data_source.redshift_options.table, schema=data_source.redshift_options.schema, - event_timestamp_column=data_source.event_timestamp_column, + timestamp_field=data_source.timestamp_field, created_timestamp_column=data_source.created_timestamp_column, - date_partition_column=data_source.date_partition_column, query=data_source.redshift_options.query, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, + database=data_source.redshift_options.database, ) + # Note: Python requires redefining hash in child classes that override __eq__ + def __hash__(self): + return super().__hash__() + def __eq__(self, other): if not isinstance(other, RedshiftSource): raise TypeError( @@ -101,9 +132,13 @@ def __eq__(self, other): and self.redshift_options.table == other.redshift_options.table and self.redshift_options.schema == other.redshift_options.schema and self.redshift_options.query == other.redshift_options.query - and self.event_timestamp_column == other.event_timestamp_column + and self.redshift_options.database == other.redshift_options.database + and self.timestamp_field == other.timestamp_field and self.created_timestamp_column == other.created_timestamp_column and self.field_mapping == other.field_mapping + and self.description == other.description + and self.tags == other.tags + and self.owner == other.owner ) @property @@ -118,9 +153,14 @@ def schema(self): @property def query(self): - """Returns the Redshift options of this Redshift source.""" + """Returns the Redshift query of this Redshift source.""" return self.redshift_options.query + @property + def database(self): + """Returns the Redshift database of this Redshift source.""" + return self.redshift_options.database + def to_proto(self) -> DataSourceProto: """ Converts a RedshiftSource object to its protobuf representation. @@ -132,11 +172,13 @@ def to_proto(self) -> DataSourceProto: type=DataSourceProto.BATCH_REDSHIFT, field_mapping=self.field_mapping, redshift_options=self.redshift_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column - data_source_proto.date_partition_column = self.date_partition_column return data_source_proto @@ -173,12 +215,15 @@ def get_table_column_names_and_types( assert isinstance(config.offline_store, RedshiftOfflineStoreConfig) client = aws_utils.get_redshift_data_client(config.offline_store.region) - if self.table is not None: try: table = client.describe_table( ClusterIdentifier=config.offline_store.cluster_id, - Database=config.offline_store.database, + Database=( + self.database + if self.database + else config.offline_store.database + ), DbUser=config.offline_store.user, Table=self.table, Schema=self.schema, @@ -197,7 +242,7 @@ def get_table_column_names_and_types( statement_id = aws_utils.execute_redshift_statement( client, config.offline_store.cluster_id, - config.offline_store.database, + self.database if self.database else config.offline_store.database, config.offline_store.user, f"SELECT * FROM ({self.query}) LIMIT 1", ) @@ -214,11 +259,16 @@ class RedshiftOptions: """ def __init__( - self, table: Optional[str], schema: Optional[str], query: Optional[str] + self, + table: Optional[str], + schema: Optional[str], + query: Optional[str], + database: Optional[str], ): self._table = table self._schema = schema self._query = query + self._database = database @property def query(self): @@ -250,6 +300,16 @@ def schema(self, schema): """Sets the schema of this Redshift table.""" self._schema = schema + @property + def database(self): + """Returns the schema name of this Redshift table.""" + return self._database + + @database.setter + def database(self, database): + """Sets the database name of this Redshift table.""" + self._database = database + @classmethod def from_proto(cls, redshift_options_proto: DataSourceProto.RedshiftOptions): """ @@ -265,6 +325,7 @@ def from_proto(cls, redshift_options_proto: DataSourceProto.RedshiftOptions): table=redshift_options_proto.table, schema=redshift_options_proto.schema, query=redshift_options_proto.query, + database=redshift_options_proto.database, ) return redshift_options @@ -277,7 +338,10 @@ def to_proto(self) -> DataSourceProto.RedshiftOptions: A RedshiftOptionsProto protobuf. """ redshift_options_proto = DataSourceProto.RedshiftOptions( - table=self.table, schema=self.schema, query=self.query, + table=self.table, + schema=self.schema, + query=self.query, + database=self.database, ) return redshift_options_proto @@ -290,7 +354,7 @@ class SavedDatasetRedshiftStorage(SavedDatasetStorage): def __init__(self, table_ref: str): self.redshift_options = RedshiftOptions( - table=table_ref, schema=None, query=None + table=table_ref, schema=None, query=None, database=None ) @staticmethod diff --git a/sdk/python/feast/infra/offline_stores/snowflake.py b/sdk/python/feast/infra/offline_stores/snowflake.py index ee8cd71ce05..c88e1b1844c 100644 --- a/sdk/python/feast/infra/offline_stores/snowflake.py +++ b/sdk/python/feast/infra/offline_stores/snowflake.py @@ -54,7 +54,7 @@ class SnowflakeOfflineStoreConfig(FeastConfigBaseModel): - """ Offline store config for Snowflake """ + """Offline store config for Snowflake""" type: Literal["snowflake.offline"] = "snowflake.offline" """ Offline store type selector""" @@ -82,7 +82,7 @@ class SnowflakeOfflineStoreConfig(FeastConfigBaseModel): database: Optional[str] = None """ Snowflake database name """ - schema_: Optional[str] = Field("PUBLIC", alias="schema") + schema_: Optional[str] = Field(None, alias="schema") """ Snowflake schema name """ class Config: @@ -128,6 +128,9 @@ def pull_latest_from_table_or_query( + '"' ) + if data_source.snowflake_options.warehouse: + config.offline_store.warehouse = data_source.snowflake_options.warehouse + snowflake_conn = get_snowflake_conn(config.offline_store) query = f""" @@ -173,6 +176,9 @@ def pull_all_from_table_or_query( + '"' ) + if data_source.snowflake_options.warehouse: + config.offline_store.warehouse = data_source.snowflake_options.warehouse + snowflake_conn = get_snowflake_conn(config.offline_store) start_date = start_date.astimezone(tz=utc) @@ -336,7 +342,7 @@ def _to_arrow_internal(self) -> pa.Table: ) def to_snowflake(self, table_name: str) -> None: - """ Save dataset as a new Snowflake table """ + """Save dataset as a new Snowflake table""" if self.on_demand_feature_views is not None: transformed_df = self.to_df() diff --git a/sdk/python/feast/infra/offline_stores/snowflake_source.py b/sdk/python/feast/infra/offline_stores/snowflake_source.py index ff36f1a66a0..1d24cba44ae 100644 --- a/sdk/python/feast/infra/offline_stores/snowflake_source.py +++ b/sdk/python/feast/infra/offline_stores/snowflake_source.py @@ -1,8 +1,8 @@ +import warnings from typing import Callable, Dict, Iterable, Optional, Tuple from feast import type_map from feast.data_source import DataSource -from feast.errors import DataSourceNoNameException from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.SavedDataset_pb2 import ( SavedDatasetStorage as SavedDatasetStorageProto, @@ -15,36 +15,55 @@ class SnowflakeSource(DataSource): def __init__( self, - name: Optional[str] = None, database: Optional[str] = None, + warehouse: Optional[str] = None, schema: Optional[str] = None, table: Optional[str] = None, query: Optional[str] = None, event_timestamp_column: Optional[str] = "", + date_partition_column: Optional[str] = None, created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, - date_partition_column: Optional[str] = "", + name: Optional[str] = None, + description: Optional[str] = "", + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = "", + timestamp_field: Optional[str] = "", ): """ Creates a SnowflakeSource object. Args: - name (optional): Name for the source. Defaults to the table if not specified. database (optional): Snowflake database where the features are stored. + warehouse (optional): Snowflake warehouse where the database is stored. schema (optional): Snowflake schema in which the table is located. table (optional): Snowflake table where the features are stored. - event_timestamp_column (optional): Event timestamp column used for point in + event_timestamp_column (optional): (Deprecated) Event timestamp column used for point in time joins of feature values. query (optional): The query to be executed to obtain the features. created_timestamp_column (optional): Timestamp column indicating when the row was created, used for deduplicating rows. field_mapping (optional): A dictionary mapping of column names in this data source to column names in a feature table or view. - date_partition_column (optional): Timestamp column used for partitioning. - + date_partition_column (deprecated): Timestamp column used for partitioning. + name (optional): Name for the source. Defaults to the table if not specified. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the snowflake source, typically the email of the primary + maintainer. """ if table is None and query is None: raise ValueError('No "table" argument provided.') + # The default Snowflake schema is named "PUBLIC". + _schema = "PUBLIC" if (database and table and not schema) else schema + + self.snowflake_options = SnowflakeOptions( + database=database, + schema=_schema, + table=table, + query=query, + warehouse=warehouse, + ) # If no name, use the table as the default name _name = name @@ -52,21 +71,32 @@ def __init__( if table: _name = table else: - raise DataSourceNoNameException() + warnings.warn( + ( + f"Starting in Feast 0.21, Feast will require either a name for a data source (if using query) " + f"or `table`: {self.query}" + ), + DeprecationWarning, + ) + + if date_partition_column: + warnings.warn( + ( + "The argument 'date_partition_column' is not supported for Snowflake sources." + "It will be removed in Feast 0.21+" + ), + DeprecationWarning, + ) super().__init__( - _name, - event_timestamp_column, - created_timestamp_column, - field_mapping, - date_partition_column, - ) - - # The default Snowflake schema is named "PUBLIC". - _schema = "PUBLIC" if (database and table and not schema) else schema - - self.snowflake_options = SnowflakeOptions( - database=database, schema=_schema, table=table, query=query + name=_name if _name else "", + event_timestamp_column=event_timestamp_column, + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + description=description, + tags=tags, + owner=owner, + timestamp_field=timestamp_field, ) @staticmethod @@ -85,12 +115,19 @@ def from_proto(data_source: DataSourceProto): database=data_source.snowflake_options.database, schema=data_source.snowflake_options.schema, table=data_source.snowflake_options.table, - event_timestamp_column=data_source.event_timestamp_column, + warehouse=data_source.snowflake_options.warehouse, + timestamp_field=data_source.timestamp_field, created_timestamp_column=data_source.created_timestamp_column, - date_partition_column=data_source.date_partition_column, query=data_source.snowflake_options.query, + description=data_source.description, + tags=dict(data_source.tags), + owner=data_source.owner, ) + # Note: Python requires redefining hash in child classes that override __eq__ + def __hash__(self): + return super().__hash__() + def __eq__(self, other): if not isinstance(other, SnowflakeSource): raise TypeError( @@ -103,9 +140,13 @@ def __eq__(self, other): and self.snowflake_options.schema == other.snowflake_options.schema and self.snowflake_options.table == other.snowflake_options.table and self.snowflake_options.query == other.snowflake_options.query - and self.event_timestamp_column == other.event_timestamp_column + and self.snowflake_options.warehouse == other.snowflake_options.warehouse + and self.timestamp_field == other.timestamp_field and self.created_timestamp_column == other.created_timestamp_column and self.field_mapping == other.field_mapping + and self.description == other.description + and self.tags == other.tags + and self.owner == other.owner ) @property @@ -128,6 +169,11 @@ def query(self): """Returns the snowflake options of this snowflake source.""" return self.snowflake_options.query + @property + def warehouse(self): + """Returns the warehouse of this snowflake source.""" + return self.snowflake_options.warehouse + def to_proto(self) -> DataSourceProto: """ Converts a SnowflakeSource object to its protobuf representation. @@ -139,11 +185,13 @@ def to_proto(self) -> DataSourceProto: type=DataSourceProto.BATCH_SNOWFLAKE, field_mapping=self.field_mapping, snowflake_options=self.snowflake_options.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) - data_source_proto.event_timestamp_column = self.event_timestamp_column + data_source_proto.timestamp_field = self.timestamp_field data_source_proto.created_timestamp_column = self.created_timestamp_column - data_source_proto.date_partition_column = self.date_partition_column return data_source_proto @@ -212,11 +260,13 @@ def __init__( schema: Optional[str], table: Optional[str], query: Optional[str], + warehouse: Optional[str], ): self._database = database self._schema = schema self._table = table self._query = query + self._warehouse = warehouse @property def query(self): @@ -258,6 +308,16 @@ def table(self, table): """Sets the table ref of this snowflake table.""" self._table = table + @property + def warehouse(self): + """Returns the warehouse name of this snowflake table.""" + return self._warehouse + + @warehouse.setter + def warehouse(self, warehouse): + """Sets the warehouse name of this snowflake table.""" + self._warehouse = warehouse + @classmethod def from_proto(cls, snowflake_options_proto: DataSourceProto.SnowflakeOptions): """ @@ -274,6 +334,7 @@ def from_proto(cls, snowflake_options_proto: DataSourceProto.SnowflakeOptions): schema=snowflake_options_proto.schema, table=snowflake_options_proto.table, query=snowflake_options_proto.query, + warehouse=snowflake_options_proto.warehouse, ) return snowflake_options @@ -290,6 +351,7 @@ def to_proto(self) -> DataSourceProto.SnowflakeOptions: schema=self.schema, table=self.table, query=self.query, + warehouse=self.warehouse, ) return snowflake_options_proto @@ -302,7 +364,7 @@ class SavedDatasetSnowflakeStorage(SavedDatasetStorage): def __init__(self, table_ref: str): self.snowflake_options = SnowflakeOptions( - database=None, schema=None, table=table_ref, query=None + database=None, schema=None, table=table_ref, query=None, warehouse=None ) @staticmethod diff --git a/sdk/python/feast/infra/online_stores/datastore.py b/sdk/python/feast/infra/online_stores/datastore.py index a29a8393e2e..e975ce138ca 100644 --- a/sdk/python/feast/infra/online_stores/datastore.py +++ b/sdk/python/feast/infra/online_stores/datastore.py @@ -55,7 +55,7 @@ class DatastoreOnlineStoreConfig(FeastConfigBaseModel): - """ Online store config for GCP Datastore """ + """Online store config for GCP Datastore""" type: Literal["datastore"] = "datastore" """ Online store type selector""" @@ -159,11 +159,13 @@ def online_write_batch( write_batch_size = online_config.write_batch_size feast_project = config.project - pool = ThreadPool(processes=write_concurrency) - pool.map( - lambda b: self._write_minibatch(client, feast_project, table, b, progress), - self._to_minibatches(data, batch_size=write_batch_size), - ) + with ThreadPool(processes=write_concurrency) as pool: + pool.map( + lambda b: self._write_minibatch( + client, feast_project, table, b, progress + ), + self._to_minibatches(data, batch_size=write_batch_size), + ) @staticmethod def _to_minibatches(data: ProtoBatch, batch_size) -> Iterator[ProtoBatch]: diff --git a/sdk/python/feast/infra/online_stores/dynamodb.py b/sdk/python/feast/infra/online_stores/dynamodb.py index 66c32c1fb8b..01562ad900c 100644 --- a/sdk/python/feast/infra/online_stores/dynamodb.py +++ b/sdk/python/feast/infra/online_stores/dynamodb.py @@ -11,12 +11,13 @@ # 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. +import itertools import logging from datetime import datetime from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple from pydantic import StrictStr -from pydantic.typing import Literal +from pydantic.typing import Literal, Union from feast import Entity, FeatureView, utils from feast.infra.infra_object import DYNAMODB_INFRA_OBJECT_CLASS_TYPE, InfraObject @@ -49,8 +50,20 @@ class DynamoDBOnlineStoreConfig(FeastConfigBaseModel): type: Literal["dynamodb"] = "dynamodb" """Online store type selector""" + batch_size: int = 40 + """Number of items to retrieve in a DynamoDB BatchGetItem call.""" + + endpoint_url: Union[str, None] = None + """DynamoDB local development endpoint Url, i.e. http://localhost:8000""" + region: StrictStr - """ AWS Region Name """ + """AWS Region Name""" + + sort_response: bool = True + """Whether or not to sort BatchGetItem response.""" + + table_name_template: StrictStr = "{project}.{table_name}" + """DynamoDB table name template""" class DynamoDBOnlineStore(OnlineStore): @@ -85,13 +98,17 @@ def update( """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) - dynamodb_client = self._get_dynamodb_client(online_config.region) - dynamodb_resource = self._get_dynamodb_resource(online_config.region) + dynamodb_client = self._get_dynamodb_client( + online_config.region, online_config.endpoint_url + ) + dynamodb_resource = self._get_dynamodb_resource( + online_config.region, online_config.endpoint_url + ) for table_instance in tables_to_keep: try: dynamodb_resource.create_table( - TableName=_get_table_name(config, table_instance), + TableName=_get_table_name(online_config, config, table_instance), KeySchema=[{"AttributeName": "entity_id", "KeyType": "HASH"}], AttributeDefinitions=[ {"AttributeName": "entity_id", "AttributeType": "S"} @@ -107,12 +124,13 @@ def update( for table_instance in tables_to_keep: dynamodb_client.get_waiter("table_exists").wait( - TableName=_get_table_name(config, table_instance) + TableName=_get_table_name(online_config, config, table_instance) ) for table_to_delete in tables_to_delete: _delete_table_idempotent( - dynamodb_resource, _get_table_name(config, table_to_delete) + dynamodb_resource, + _get_table_name(online_config, config, table_to_delete), ) def teardown( @@ -130,10 +148,14 @@ def teardown( """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) - dynamodb_resource = self._get_dynamodb_resource(online_config.region) + dynamodb_resource = self._get_dynamodb_resource( + online_config.region, online_config.endpoint_url + ) for table in tables: - _delete_table_idempotent(dynamodb_resource, _get_table_name(config, table)) + _delete_table_idempotent( + dynamodb_resource, _get_table_name(online_config, config, table) + ) @log_exceptions_and_usage(online_store="dynamodb") def online_write_batch( @@ -162,24 +184,14 @@ def online_write_batch( """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) - dynamodb_resource = self._get_dynamodb_resource(online_config.region) + dynamodb_resource = self._get_dynamodb_resource( + online_config.region, online_config.endpoint_url + ) - table_instance = dynamodb_resource.Table(_get_table_name(config, table)) - with table_instance.batch_writer() as batch: - for entity_key, features, timestamp, created_ts in data: - entity_id = compute_entity_id(entity_key) - batch.put_item( - Item={ - "entity_id": entity_id, # PartitionKey - "event_ts": str(utils.make_tzaware(timestamp)), - "values": { - k: v.SerializeToString() - for k, v in features.items() # Serialized Features - }, - } - ) - if progress: - progress(1) + table_instance = dynamodb_resource.Table( + _get_table_name(online_config, config, table) + ) + self._write_batch_non_duplicates(table_instance, data, progress) @log_exceptions_and_usage(online_store="dynamodb") def online_read( @@ -202,48 +214,120 @@ def online_read( """ online_config = config.online_store assert isinstance(online_config, DynamoDBOnlineStoreConfig) - dynamodb_resource = self._get_dynamodb_resource(online_config.region) + dynamodb_resource = self._get_dynamodb_resource( + online_config.region, online_config.endpoint_url + ) + table_instance = dynamodb_resource.Table( + _get_table_name(online_config, config, table) + ) result: List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]] = [] - for entity_key in entity_keys: - table_instance = dynamodb_resource.Table(_get_table_name(config, table)) - entity_id = compute_entity_id(entity_key) + entity_ids = [compute_entity_id(entity_key) for entity_key in entity_keys] + batch_size = online_config.batch_size + sort_response = online_config.sort_response + entity_ids_iter = iter(entity_ids) + while True: + batch = list(itertools.islice(entity_ids_iter, batch_size)) + # No more items to insert + if len(batch) == 0: + break + batch_entity_ids = { + table_instance.name: { + "Keys": [{"entity_id": entity_id} for entity_id in batch] + } + } with tracing_span(name="remote_call"): - response = table_instance.get_item(Key={"entity_id": entity_id}) - value = response.get("Item") - - if value is not None: - res = {} - for feature_name, value_bin in value["values"].items(): - val = ValueProto() - val.ParseFromString(value_bin.value) - res[feature_name] = val - result.append((datetime.fromisoformat(value["event_ts"]), res)) + response = dynamodb_resource.batch_get_item( + RequestItems=batch_entity_ids + ) + response = response.get("Responses") + table_responses = response.get(table_instance.name) + if table_responses: + if sort_response: + table_responses = self._sort_dynamodb_response( + table_responses, entity_ids + ) + for tbl_res in table_responses: + res = {} + for feature_name, value_bin in tbl_res["values"].items(): + val = ValueProto() + val.ParseFromString(value_bin.value) + res[feature_name] = val + result.append((datetime.fromisoformat(tbl_res["event_ts"]), res)) else: - result.append((None, None)) + batch_size_nones = ((None, None),) * len(batch) + result.extend(batch_size_nones) return result - def _get_dynamodb_client(self, region: str): + def _get_dynamodb_client(self, region: str, endpoint_url: Optional[str] = None): if self._dynamodb_client is None: - self._dynamodb_client = _initialize_dynamodb_client(region) + self._dynamodb_client = _initialize_dynamodb_client(region, endpoint_url) return self._dynamodb_client - def _get_dynamodb_resource(self, region: str): + def _get_dynamodb_resource(self, region: str, endpoint_url: Optional[str] = None): if self._dynamodb_resource is None: - self._dynamodb_resource = _initialize_dynamodb_resource(region) + self._dynamodb_resource = _initialize_dynamodb_resource( + region, endpoint_url + ) return self._dynamodb_resource + def _sort_dynamodb_response(self, responses: list, order: list): + """DynamoDB Batch Get Item doesn't return items in a particular order.""" + # Assign an index to order + order_with_index = {value: idx for idx, value in enumerate(order)} + # Sort table responses by index + table_responses_ordered = [ + (order_with_index[tbl_res["entity_id"]], tbl_res) for tbl_res in responses + ] + table_responses_ordered = sorted( + table_responses_ordered, key=lambda tup: tup[0] + ) + _, table_responses_ordered = zip(*table_responses_ordered) + return table_responses_ordered + + @log_exceptions_and_usage(online_store="dynamodb") + def _write_batch_non_duplicates( + self, + table_instance, + data: List[ + Tuple[EntityKeyProto, Dict[str, ValueProto], datetime, Optional[datetime]] + ], + progress: Optional[Callable[[int], Any]], + ): + """Deduplicate write batch request items on ``entity_id`` primary key.""" + with table_instance.batch_writer(overwrite_by_pkeys=["entity_id"]) as batch: + for entity_key, features, timestamp, created_ts in data: + entity_id = compute_entity_id(entity_key) + batch.put_item( + Item={ + "entity_id": entity_id, # PartitionKey + "event_ts": str(utils.make_tzaware(timestamp)), + "values": { + k: v.SerializeToString() + for k, v in features.items() # Serialized Features + }, + } + ) + if progress: + progress(1) + -def _initialize_dynamodb_client(region: str): - return boto3.client("dynamodb", region_name=region) +def _initialize_dynamodb_client(region: str, endpoint_url: Optional[str] = None): + return boto3.client("dynamodb", region_name=region, endpoint_url=endpoint_url) -def _initialize_dynamodb_resource(region: str): - return boto3.resource("dynamodb", region_name=region) +def _initialize_dynamodb_resource(region: str, endpoint_url: Optional[str] = None): + return boto3.resource("dynamodb", region_name=region, endpoint_url=endpoint_url) -def _get_table_name(config: RepoConfig, table: FeatureView) -> str: - return f"{config.project}.{table.name}" +# TODO(achals): This form of user-facing templating is experimental. +# Please refer to https://github.com/feast-dev/feast/issues/2438 before building on top of it, +def _get_table_name( + online_config: DynamoDBOnlineStoreConfig, config: RepoConfig, table: FeatureView +) -> str: + return online_config.table_name_template.format( + project=config.project, table_name=table.name + ) def _delete_table_idempotent( @@ -270,13 +354,20 @@ class DynamoDBTable(InfraObject): Attributes: name: The name of the table. region: The region of the table. + endpoint_url: Local DynamoDB Endpoint Url. + _dynamodb_client: Boto3 DynamoDB client. + _dynamodb_resource: Boto3 DynamoDB resource. """ region: str + endpoint_url = None + _dynamodb_client = None + _dynamodb_resource = None - def __init__(self, name: str, region: str): + def __init__(self, name: str, region: str, endpoint_url: Optional[str] = None): super().__init__(name) self.region = region + self.endpoint_url = endpoint_url def to_infra_object_proto(self) -> InfraObjectProto: dynamodb_table_proto = self.to_proto() @@ -305,8 +396,8 @@ def from_proto(dynamodb_table_proto: DynamoDBTableProto) -> Any: ) def update(self): - dynamodb_client = _initialize_dynamodb_client(region=self.region) - dynamodb_resource = _initialize_dynamodb_resource(region=self.region) + dynamodb_client = self._get_dynamodb_client(self.region, self.endpoint_url) + dynamodb_resource = self._get_dynamodb_resource(self.region, self.endpoint_url) try: dynamodb_resource.create_table( @@ -327,5 +418,17 @@ def update(self): dynamodb_client.get_waiter("table_exists").wait(TableName=f"{self.name}") def teardown(self): - dynamodb_resource = _initialize_dynamodb_resource(region=self.region) + dynamodb_resource = self._get_dynamodb_resource(self.region, self.endpoint_url) _delete_table_idempotent(dynamodb_resource, self.name) + + def _get_dynamodb_client(self, region: str, endpoint_url: Optional[str] = None): + if self._dynamodb_client is None: + self._dynamodb_client = _initialize_dynamodb_client(region, endpoint_url) + return self._dynamodb_client + + def _get_dynamodb_resource(self, region: str, endpoint_url: Optional[str] = None): + if self._dynamodb_resource is None: + self._dynamodb_resource = _initialize_dynamodb_resource( + region, endpoint_url + ) + return self._dynamodb_resource diff --git a/sdk/python/feast/infra/online_stores/sqlite.py b/sdk/python/feast/infra/online_stores/sqlite.py index e65aab4e7be..710f4c386a6 100644 --- a/sdk/python/feast/infra/online_stores/sqlite.py +++ b/sdk/python/feast/infra/online_stores/sqlite.py @@ -37,7 +37,7 @@ class SqliteOnlineStoreConfig(FeastConfigBaseModel): - """ Online store config for local (SQLite-based) store """ + """Online store config for local (SQLite-based) store""" type: Literal[ "sqlite", "feast.infra.online_stores.sqlite.SqliteOnlineStore" diff --git a/sdk/python/feast/infra/provider.py b/sdk/python/feast/infra/provider.py index b3f10292423..b379193ba38 100644 --- a/sdk/python/feast/infra/provider.py +++ b/sdk/python/feast/infra/provider.py @@ -183,7 +183,7 @@ def retrieve_saved_dataset( Returns: RetrievalJob object, which is lazy wrapper for actual query performed under the hood. - """ + """ ... def get_feature_server_endpoint(self) -> Optional[str]: @@ -258,7 +258,7 @@ def _get_column_names( the query to the offline store. """ # if we have mapped fields, use the original field names in the call to the offline store - event_timestamp_column = feature_view.batch_source.event_timestamp_column + event_timestamp_column = feature_view.batch_source.timestamp_field feature_names = [feature.name for feature in feature_view.features] created_timestamp_column = feature_view.batch_source.created_timestamp_column join_keys = [ @@ -290,9 +290,13 @@ def _get_column_names( # We need to exclude join keys and timestamp columns from the list of features, after they are mapped to # their final column names via the `field_mapping` field of the source. - _feature_names = set(feature_names) - set(join_keys) - _feature_names = _feature_names - {event_timestamp_column, created_timestamp_column} - feature_names = list(_feature_names) + feature_names = [ + name + for name in feature_names + if name not in join_keys + and name != event_timestamp_column + and name != created_timestamp_column + ] return ( join_keys, feature_names, @@ -348,9 +352,9 @@ def _convert_arrow_to_proto( if isinstance(table, pyarrow.Table): table = table.to_batches()[0] - columns = [(f.name, f.dtype) for f in feature_view.features] + list( - join_keys.items() - ) + columns = [ + (field.name, field.dtype.to_value_type()) for field in feature_view.schema + ] + list(join_keys.items()) proto_values_by_column = { column: python_values_to_proto_values( @@ -378,7 +382,7 @@ def _convert_arrow_to_proto( event_timestamps = [ _coerce_datetime(val) for val in pandas.to_datetime( - table.column(feature_view.batch_source.event_timestamp_column).to_numpy( + table.column(feature_view.batch_source.timestamp_field).to_numpy( zero_copy_only=False ) ) diff --git a/sdk/python/feast/infra/utils/aws_utils.py b/sdk/python/feast/infra/utils/aws_utils.py index e7f628795d8..fe5eed774ec 100644 --- a/sdk/python/feast/infra/utils/aws_utils.py +++ b/sdk/python/feast/infra/utils/aws_utils.py @@ -151,7 +151,7 @@ def execute_redshift_statement( def get_redshift_statement_result(redshift_data_client, statement_id: str) -> dict: - """ Get the Redshift statement result """ + """Get the Redshift statement result""" return redshift_data_client.get_statement_result(Id=statement_id) @@ -306,7 +306,7 @@ def temporarily_upload_df_to_redshift( def download_s3_directory(s3_resource, bucket: str, key: str, local_dir: str): - """ Download the S3 directory to a local disk """ + """Download the S3 directory to a local disk""" bucket_obj = s3_resource.Bucket(bucket) if key != "" and not key.endswith("/"): key = key + "/" @@ -318,7 +318,7 @@ def download_s3_directory(s3_resource, bucket: str, key: str, local_dir: str): def delete_s3_directory(s3_resource, bucket: str, key: str): - """ Delete S3 directory recursively """ + """Delete S3 directory recursively""" bucket_obj = s3_resource.Bucket(bucket) if key != "" and not key.endswith("/"): key = key + "/" @@ -365,7 +365,7 @@ def unload_redshift_query_to_pa( iam_role: str, query: str, ) -> pa.Table: - """ Unload Redshift Query results to S3 and get the results in PyArrow Table format """ + """Unload Redshift Query results to S3 and get the results in PyArrow Table format""" bucket, key = get_bucket_and_key(s3_path) execute_redshift_query_and_unload_to_s3( @@ -388,7 +388,7 @@ def unload_redshift_query_to_df( iam_role: str, query: str, ) -> pd.DataFrame: - """ Unload Redshift Query results to S3 and get the results in Pandas DataFrame format """ + """Unload Redshift Query results to S3 and get the results in Pandas DataFrame format""" table = unload_redshift_query_to_pa( redshift_data_client, cluster_id, diff --git a/sdk/python/feast/infra/utils/snowflake_utils.py b/sdk/python/feast/infra/utils/snowflake_utils.py index 065a4bad467..a467a9de421 100644 --- a/sdk/python/feast/infra/utils/snowflake_utils.py +++ b/sdk/python/feast/infra/utils/snowflake_utils.py @@ -4,9 +4,11 @@ import string from logging import getLogger from tempfile import TemporaryDirectory -from typing import Dict, Iterator, List, Optional, Tuple, cast +from typing import Any, Dict, Iterator, List, Optional, Tuple, cast import pandas as pd +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization from tenacity import ( retry, retry_if_exception_type, @@ -40,26 +42,38 @@ def execute_snowflake_statement(conn: SnowflakeConnection, query) -> SnowflakeCu def get_snowflake_conn(config, autocommit=True) -> SnowflakeConnection: - if config.type == "snowflake.offline": - config_header = "connections.feast_offline_store" + assert config.type == "snowflake.offline" + config_header = "connections.feast_offline_store" config_dict = dict(config) # read config file config_reader = configparser.ConfigParser() config_reader.read([config_dict["config_path"]]) + kwargs: Dict[str, Any] = {} if config_reader.has_section(config_header): kwargs = dict(config_reader[config_header]) - else: - kwargs = {} + + if "schema" in kwargs: + kwargs["schema_"] = kwargs.pop("schema") kwargs.update((k, v) for k, v in config_dict.items() if v is not None) - [ - kwargs.update({k: '"' + v + '"'}) - for k, v in kwargs.items() - if k in ["role", "warehouse", "database", "schema_"] - ] - kwargs["schema"] = kwargs.pop("schema_") + + for k, v in kwargs.items(): + if k in ["role", "warehouse", "database", "schema_"]: + kwargs[k] = f'"{v}"' + + if "schema_" in kwargs: + kwargs["schema"] = kwargs.pop("schema_") + else: + kwargs["schema"] = '"PUBLIC"' + + # https://docs.snowflake.com/en/user-guide/python-connector-example.html#using-key-pair-authentication-key-pair-rotation + # https://docs.snowflake.com/en/user-guide/key-pair-auth.html#configuring-key-pair-authentication + if "private_key" in kwargs: + kwargs["private_key"] = parse_private_key_path( + kwargs["private_key"], kwargs["private_key_passphrase"] + ) try: conn = snowflake.connector.connect( @@ -282,3 +296,21 @@ def chunk_helper(lst: pd.DataFrame, n: int) -> Iterator[Tuple[int, pd.DataFrame] """Helper generator to chunk a sequence efficiently with current index like if enumerate was called on sequence.""" for i in range(0, len(lst), n): yield int(i / n), lst[i : i + n] + + +def parse_private_key_path(key_path: str, private_key_passphrase: str) -> bytes: + + with open(key_path, "rb") as key: + p_key = serialization.load_pem_private_key( + key.read(), + password=private_key_passphrase.encode(), + backend=default_backend(), + ) + + pkb = p_key.private_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption(), + ) + + return pkb diff --git a/sdk/python/feast/on_demand_feature_view.py b/sdk/python/feast/on_demand_feature_view.py index 04b7f33cc66..790891b0781 100644 --- a/sdk/python/feast/on_demand_feature_view.py +++ b/sdk/python/feast/on_demand_feature_view.py @@ -1,24 +1,26 @@ import copy import functools +import warnings from types import MethodType -from typing import Dict, List, Type, Union +from typing import Dict, List, Optional, Type, Union import dill import pandas as pd from feast.base_feature_view import BaseFeatureView -from feast.data_source import RequestDataSource +from feast.data_source import RequestSource from feast.errors import RegistryInferenceFailure, SpecifiedFeaturesNotPresentError from feast.feature import Feature from feast.feature_view import FeatureView from feast.feature_view_projection import FeatureViewProjection +from feast.field import Field, from_value_type from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( OnDemandFeatureView as OnDemandFeatureViewProto, ) from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( OnDemandFeatureViewMeta, OnDemandFeatureViewSpec, - OnDemandInput, + OnDemandSource, ) from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( UserDefinedFunction as UserDefinedFunctionProto, @@ -30,47 +32,187 @@ from feast.usage import log_exceptions from feast.value_type import ValueType +warnings.simplefilter("once", DeprecationWarning) + class OnDemandFeatureView(BaseFeatureView): """ - [Experimental] An OnDemandFeatureView defines on demand transformations on existing feature view values and request - data. - - Args: - name: Name of the group of features. - features: Output schema of transformation with feature names - inputs: The input feature views passed into the transform. - udf: User defined transformation function that takes as input pandas dataframes + [Experimental] An OnDemandFeatureView defines a logical group of features that are + generated by applying a transformation on a set of input sources, such as feature + views and request data sources. + + Attributes: + name: The unique name of the on demand feature view. + features: The list of features in the output of the on demand feature view. + source_feature_view_projections: A map from input source names to actual input + sources with type FeatureViewProjection. + source_request_sources: A map from input source names to the actual input + sources with type RequestSource. + udf: The user defined transformation function, which must take pandas dataframes + as inputs. + description: A human-readable description. + tags: A dictionary of key-value pairs to store arbitrary metadata. + owner: The owner of the on demand feature view, typically the email of the primary + maintainer. """ # TODO(adchia): remove inputs from proto and declaration - input_feature_view_projections: Dict[str, FeatureViewProjection] - input_request_data_sources: Dict[str, RequestDataSource] + name: str + features: List[Field] + source_feature_view_projections: Dict[str, FeatureViewProjection] + source_request_sources: Dict[str, RequestSource] udf: MethodType + description: str + tags: Dict[str, str] + owner: str @log_exceptions def __init__( self, - name: str, - features: List[Feature], - inputs: Dict[str, Union[FeatureView, FeatureViewProjection, RequestDataSource]], - udf: MethodType, + *args, + name: Optional[str] = None, + features: Optional[List[Feature]] = None, + sources: Optional[ + Dict[str, Union[FeatureView, FeatureViewProjection, RequestSource]] + ] = None, + udf: Optional[MethodType] = None, + inputs: Optional[ + Dict[str, Union[FeatureView, FeatureViewProjection, RequestSource]] + ] = None, + schema: Optional[List[Field]] = None, + description: str = "", + tags: Optional[Dict[str, str]] = None, + owner: str = "", ): """ Creates an OnDemandFeatureView object. + + Args: + name: The unique name of the on demand feature view. + features (deprecated): The list of features in the output of the on demand + feature view, after the transformation has been applied. + sources (optional): A map from input source names to the actual input sources, + which may be feature views, feature view projections, or request data sources. + These sources serve as inputs to the udf, which will refer to them by name. + udf (optional): The user defined transformation function, which must take pandas + dataframes as inputs. + inputs (optional): A map from input source names to the actual input sources, + which may be feature views, feature view projections, or request data sources. + These sources serve as inputs to the udf, which will refer to them by name. + schema (optional): The list of features in the output of the on demand feature + view, after the transformation has been applied. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the on demand feature view, typically the email + of the primary maintainer. """ - super().__init__(name, features) - self.input_feature_view_projections: Dict[str, FeatureViewProjection] = {} - self.input_request_data_sources: Dict[str, RequestDataSource] = {} - for input_ref, odfv_input in inputs.items(): - if isinstance(odfv_input, RequestDataSource): - self.input_request_data_sources[input_ref] = odfv_input - elif isinstance(odfv_input, FeatureViewProjection): - self.input_feature_view_projections[input_ref] = odfv_input + positional_attributes = ["name", "features", "inputs", "udf"] + + _name = name + + _schema = schema or [] + if len(_schema) == 0 and features is not None: + _schema = [Field.from_feature(feature) for feature in features] + if features is not None: + warnings.warn( + ( + "The `features` parameter is being deprecated in favor of the `schema` parameter. " + "Please switch from using `features` to `schema`. This will also requiring switching " + "feature definitions from using `Feature` to `Field`. Feast 0.21 and onwards will not " + "support the `features` parameter." + ), + DeprecationWarning, + ) + + _sources = sources or inputs + if inputs and sources: + raise ValueError("At most one of `sources` or `inputs` can be specified.") + elif inputs: + warnings.warn( + ( + "The `inputs` parameter is being deprecated. Please use `sources` instead. " + "Feast 0.21 and onwards will not support the `inputs` parameter." + ), + DeprecationWarning, + ) + + _udf = udf + + if args: + warnings.warn( + ( + "On demand feature view parameters should be specified as keyword arguments " + "instead of positional arguments. Feast 0.23 and onwards will not support " + "positional arguments in on demand feature view definitions." + ), + DeprecationWarning, + ) + if len(args) > len(positional_attributes): + raise ValueError( + f"Only {', '.join(positional_attributes)} are allowed as positional args " + f"when defining feature views, for backwards compatibility." + ) + if len(args) >= 1: + _name = args[0] + if len(args) >= 2: + _schema = args[1] + # Convert Features to Fields. + if len(_schema) > 0 and isinstance(_schema[0], Feature): + _schema = [Field.from_feature(feature) for feature in _schema] + warnings.warn( + ( + "The `features` parameter is being deprecated in favor of the `schema` parameter. " + "Please switch from using `features` to `schema`. This will also requiring switching " + "feature definitions from using `Feature` to `Field`. Feast 0.21 and onwards will not " + "support the `features` parameter." + ), + DeprecationWarning, + ) + if len(args) >= 3: + _sources = args[2] + warnings.warn( + ( + "The `inputs` parameter is being deprecated. Please use `sources` instead. " + "Feast 0.21 and onwards will not support the `inputs` parameter." + ), + DeprecationWarning, + ) + if len(args) >= 4: + _udf = args[3] + + if not _name: + raise ValueError( + "The name of the on demand feature view must be specified." + ) + + if not _sources: + raise ValueError("The `sources` parameter must be specified.") + + super().__init__( + name=_name, + features=_schema, + description=description, + tags=tags, + owner=owner, + ) + + assert _sources is not None + self.source_feature_view_projections: Dict[str, FeatureViewProjection] = {} + self.source_request_sources: Dict[str, RequestSource] = {} + for source_name, odfv_source in _sources.items(): + if isinstance(odfv_source, RequestSource): + self.source_request_sources[source_name] = odfv_source + elif isinstance(odfv_source, FeatureViewProjection): + self.source_feature_view_projections[source_name] = odfv_source else: - self.input_feature_view_projections[input_ref] = odfv_input.projection + self.source_feature_view_projections[ + source_name + ] = odfv_source.projection - self.udf = udf + if _udf is None: + raise ValueError("The `udf` parameter must be specified.") + assert _udf + self.udf = _udf @property def proto_class(self) -> Type[OnDemandFeatureViewProto]: @@ -79,11 +221,14 @@ def proto_class(self) -> Type[OnDemandFeatureViewProto]: def __copy__(self): fv = OnDemandFeatureView( name=self.name, - features=self.features, - inputs=dict( - **self.input_feature_view_projections, **self.input_request_data_sources + schema=self.features, + sources=dict( + **self.source_feature_view_projections, **self.source_request_sources, ), udf=self.udf, + description=self.description, + tags=self.tags, + owner=self.owner, ) fv.projection = copy.copy(self.projection) return fv @@ -93,17 +238,13 @@ def __eq__(self, other): return False if ( - not self.input_feature_view_projections - == other.input_feature_view_projections + not self.source_feature_view_projections + == other.source_feature_view_projections + or not self.source_request_sources == other.source_request_sources + or not self.udf.__code__.co_code == other.udf.__code__.co_code ): return False - if not self.input_request_data_sources == other.input_request_data_sources: - return False - - if not self.udf.__code__.co_code == other.udf.__code__.co_code: - return False - return True def __hash__(self): @@ -121,23 +262,26 @@ def to_proto(self) -> OnDemandFeatureViewProto: meta.created_timestamp.FromDatetime(self.created_timestamp) if self.last_updated_timestamp: meta.last_updated_timestamp.FromDatetime(self.last_updated_timestamp) - inputs = {} - for input_ref, fv_projection in self.input_feature_view_projections.items(): - inputs[input_ref] = OnDemandInput( + sources = {} + for source_name, fv_projection in self.source_feature_view_projections.items(): + sources[source_name] = OnDemandSource( feature_view_projection=fv_projection.to_proto() ) - for input_ref, request_data_source in self.input_request_data_sources.items(): - inputs[input_ref] = OnDemandInput( - request_data_source=request_data_source.to_proto() + for (source_name, request_sources,) in self.source_request_sources.items(): + sources[source_name] = OnDemandSource( + request_data_source=request_sources.to_proto() ) spec = OnDemandFeatureViewSpec( name=self.name, features=[feature.to_proto() for feature in self.features], - inputs=inputs, + sources=sources, user_defined_function=UserDefinedFunctionProto( name=self.udf.__name__, body=dill.dumps(self.udf, recurse=True), ), + description=self.description, + tags=self.tags, + owner=self.owner, ) return OnDemandFeatureViewProto(spec=spec, meta=meta) @@ -153,37 +297,39 @@ def from_proto(cls, on_demand_feature_view_proto: OnDemandFeatureViewProto): Returns: A OnDemandFeatureView object based on the on-demand feature view protobuf. """ - inputs = {} + sources = {} for ( - input_name, - on_demand_input, - ) in on_demand_feature_view_proto.spec.inputs.items(): - if on_demand_input.WhichOneof("input") == "feature_view": - inputs[input_name] = FeatureView.from_proto( - on_demand_input.feature_view + source_name, + on_demand_source, + ) in on_demand_feature_view_proto.spec.sources.items(): + if on_demand_source.WhichOneof("source") == "feature_view": + sources[source_name] = FeatureView.from_proto( + on_demand_source.feature_view ).projection - elif on_demand_input.WhichOneof("input") == "feature_view_projection": - inputs[input_name] = FeatureViewProjection.from_proto( - on_demand_input.feature_view_projection + elif on_demand_source.WhichOneof("source") == "feature_view_projection": + sources[source_name] = FeatureViewProjection.from_proto( + on_demand_source.feature_view_projection ) else: - inputs[input_name] = RequestDataSource.from_proto( - on_demand_input.request_data_source + sources[source_name] = RequestSource.from_proto( + on_demand_source.request_data_source ) on_demand_feature_view_obj = cls( name=on_demand_feature_view_proto.spec.name, - features=[ - Feature( + schema=[ + Field( name=feature.name, - dtype=ValueType(feature.value_type), - labels=dict(feature.labels), + dtype=from_value_type(ValueType(feature.value_type)), ) for feature in on_demand_feature_view_proto.spec.features ], - inputs=inputs, + sources=sources, udf=dill.loads( on_demand_feature_view_proto.spec.user_defined_function.body ), + description=on_demand_feature_view_proto.spec.description, + tags=dict(on_demand_feature_view_proto.spec.tags), + owner=on_demand_feature_view_proto.spec.owner, ) # FeatureViewProjections are not saved in the OnDemandFeatureView proto. @@ -205,8 +351,18 @@ def from_proto(cls, on_demand_feature_view_proto: OnDemandFeatureViewProto): def get_request_data_schema(self) -> Dict[str, ValueType]: schema: Dict[str, ValueType] = {} - for request_data_source in self.input_request_data_sources.values(): - schema.update(request_data_source.schema) + for request_source in self.source_request_sources.values(): + if isinstance(request_source.schema, List): + new_schema = {} + for field in request_source.schema: + new_schema[field.name] = field.dtype.to_value_type() + schema.update(new_schema) + elif isinstance(request_source.schema, Dict): + schema.update(request_source.schema) + else: + raise Exception( + f"Request source schema is not correct type: ${str(type(request_source.schema))}" + ) return schema def get_transformed_features_df( @@ -214,9 +370,9 @@ def get_transformed_features_df( ) -> pd.DataFrame: # Apply on demand transformations columns_to_cleanup = [] - for input_fv_projection in self.input_feature_view_projections.values(): - for feature in input_fv_projection.features: - full_feature_ref = f"{input_fv_projection.name}__{feature.name}" + for source_fv_projection in self.source_feature_view_projections.values(): + for feature in source_fv_projection.features: + full_feature_ref = f"{source_fv_projection.name}__{feature.name}" if full_feature_ref in df_with_features.keys(): # Make sure the partial feature name is always present df_with_features[feature.name] = df_with_features[full_feature_ref] @@ -255,23 +411,26 @@ def infer_features(self): RegistryInferenceFailure: The set of features could not be inferred. """ df = pd.DataFrame() - for feature_view_projection in self.input_feature_view_projections.values(): + for feature_view_projection in self.source_feature_view_projections.values(): for feature in feature_view_projection.features: - dtype = feast_value_type_to_pandas_type(feature.dtype) + dtype = feast_value_type_to_pandas_type(feature.dtype.to_value_type()) df[f"{feature_view_projection.name}__{feature.name}"] = pd.Series( dtype=dtype ) df[f"{feature.name}"] = pd.Series(dtype=dtype) - for request_data in self.input_request_data_sources.values(): - for feature_name, feature_type in request_data.schema.items(): - dtype = feast_value_type_to_pandas_type(feature_type) - df[f"{feature_name}"] = pd.Series(dtype=dtype) + for request_data in self.source_request_sources.values(): + for field in request_data.schema: + dtype = feast_value_type_to_pandas_type(field.dtype.to_value_type()) + df[f"{field.name}"] = pd.Series(dtype=dtype) output_df: pd.DataFrame = self.udf.__call__(df) inferred_features = [] for f, dt in zip(output_df.columns, output_df.dtypes): inferred_features.append( - Feature( - name=f, dtype=python_type_to_feast_value_type(f, type_name=str(dt)) + Field( + name=f, + dtype=from_value_type( + python_type_to_feast_value_type(f, type_name=str(dt)) + ), ) ) @@ -307,23 +466,115 @@ def get_requested_odfvs(feature_refs, project, registry): return requested_on_demand_feature_views +# TODO(felixwang9817): Force this decorator to accept kwargs and switch from +# `features` to `schema`. def on_demand_feature_view( - features: List[Feature], inputs: Dict[str, Union[FeatureView, RequestDataSource]] + *args, + features: Optional[List[Feature]] = None, + sources: Optional[Dict[str, Union[FeatureView, RequestSource]]] = None, + inputs: Optional[Dict[str, Union[FeatureView, RequestSource]]] = None, + schema: Optional[List[Field]] = None, + description: str = "", + tags: Optional[Dict[str, str]] = None, + owner: str = "", ): """ - Declare an on-demand feature view + Creates an OnDemandFeatureView object with the given user function as udf. - :param features: Output schema with feature names - :param inputs: The inputs passed into the transform. - :return: An On Demand Feature View. + Args: + features (deprecated): The list of features in the output of the on demand + feature view, after the transformation has been applied. + sources (optional): A map from input source names to the actual input sources, + which may be feature views, feature view projections, or request data sources. + These sources serve as inputs to the udf, which will refer to them by name. + inputs (optional): A map from input source names to the actual input sources, + which may be feature views, feature view projections, or request data sources. + These sources serve as inputs to the udf, which will refer to them by name. + schema (optional): The list of features in the output of the on demand feature + view, after the transformation has been applied. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the on demand feature view, typically the email + of the primary maintainer. """ + positional_attributes = ["features", "inputs"] + + _schema = schema or [] + if len(_schema) == 0 and features is not None: + _schema = [Field.from_feature(feature) for feature in features] + if features is not None: + warnings.warn( + ( + "The `features` parameter is being deprecated in favor of the `schema` parameter. " + "Please switch from using `features` to `schema`. This will also requiring switching " + "feature definitions from using `Feature` to `Field`. Feast 0.21 and onwards will not " + "support the `features` parameter." + ), + DeprecationWarning, + ) + + _sources = sources or inputs + if inputs and sources: + raise ValueError("At most one of `sources` or `inputs` can be specified.") + elif inputs: + warnings.warn( + ( + "The `inputs` parameter is being deprecated. Please use `sources` instead. " + "Feast 0.21 and onwards will not support the `inputs` parameter." + ), + DeprecationWarning, + ) + + if args: + warnings.warn( + ( + "On demand feature view parameters should be specified as keyword arguments " + "instead of positional arguments. Feast 0.23 and onwards will not support " + "positional arguments in on demand feature view definitions." + ), + DeprecationWarning, + ) + if len(args) > len(positional_attributes): + raise ValueError( + f"Only {', '.join(positional_attributes)} are allowed as positional args " + f"when defining feature views, for backwards compatibility." + ) + if len(args) >= 1: + _schema = args[0] + # Convert Features to Fields. + if len(_schema) > 0 and isinstance(_schema[0], Feature): + _schema = [Field.from_feature(feature) for feature in _schema] + warnings.warn( + ( + "The `features` parameter is being deprecated in favor of the `schema` parameter. " + "Please switch from using `features` to `schema`. This will also requiring switching " + "feature definitions from using `Feature` to `Field`. Feast 0.21 and onwards will not " + "support the `features` parameter." + ), + DeprecationWarning, + ) + if len(args) >= 2: + _sources = args[1] + warnings.warn( + ( + "The `inputs` parameter is being deprecated. Please use `sources` instead. " + "Feast 0.21 and onwards will not support the `inputs` parameter." + ), + DeprecationWarning, + ) + + if not _sources: + raise ValueError("The `sources` parameter must be specified.") def decorator(user_function): on_demand_feature_view_obj = OnDemandFeatureView( name=user_function.__name__, - inputs=inputs, - features=features, + sources=_sources, + schema=_schema, udf=user_function, + description=description, + tags=tags, + owner=owner, ) functools.update_wrapper( wrapper=on_demand_feature_view_obj, wrapped=user_function diff --git a/sdk/python/feast/online_response.py b/sdk/python/feast/online_response.py index f01bd510be9..48524359bf3 100644 --- a/sdk/python/feast/online_response.py +++ b/sdk/python/feast/online_response.py @@ -40,10 +40,8 @@ def __init__(self, online_response_proto: GetOnlineFeaturesResponse): for idx, val in enumerate(self.proto.metadata.feature_names.val): if val == DUMMY_ENTITY_ID: del self.proto.metadata.feature_names.val[idx] - for result in self.proto.results: - del result.values[idx] - del result.statuses[idx] - del result.event_timestamps[idx] + del self.proto.results[idx] + break def to_dict(self, include_event_timestamps: bool = False) -> Dict[str, Any]: @@ -55,21 +53,18 @@ def to_dict(self, include_event_timestamps: bool = False) -> Dict[str, Any]: """ response: Dict[str, List[Any]] = {} - for result in self.proto.results: - for idx, feature_ref in enumerate(self.proto.metadata.feature_names.val): - native_type_value = feast_value_type_to_python_type(result.values[idx]) - if feature_ref not in response: - response[feature_ref] = [native_type_value] - else: - response[feature_ref].append(native_type_value) - - if include_event_timestamps: - event_ts = result.event_timestamps[idx].seconds - timestamp_ref = feature_ref + TIMESTAMP_POSTFIX - if timestamp_ref not in response: - response[timestamp_ref] = [event_ts] - else: - response[timestamp_ref].append(event_ts) + for feature_ref, feature_vector in zip( + self.proto.metadata.feature_names.val, self.proto.results + ): + response[feature_ref] = [ + feast_value_type_to_python_type(v) for v in feature_vector.values + ] + + if include_event_timestamps: + timestamp_ref = feature_ref + TIMESTAMP_POSTFIX + response[timestamp_ref] = [ + ts.seconds for ts in feature_vector.event_timestamps + ] return response diff --git a/sdk/python/feast/proto_json.py b/sdk/python/feast/proto_json.py index 549d7b6d148..44e004cb036 100644 --- a/sdk/python/feast/proto_json.py +++ b/sdk/python/feast/proto_json.py @@ -15,6 +15,8 @@ JsonObject = Any +# TODO: These methods need to be updated when bumping the version of protobuf. +# https://github.com/feast-dev/feast/issues/2484 def _patch_proto_json_encoding( proto_type: Type[ProtoMessage], to_json_object: Callable[[_Printer, ProtoMessage], JsonObject], @@ -68,7 +70,7 @@ def to_json_object(printer: _Printer, message: ProtoMessage) -> JsonObject: return value def from_json_object( - parser: _Parser, value: JsonObject, message: ProtoMessage + parser: _Parser, value: JsonObject, message: ProtoMessage, ) -> None: if value is None: message.null_val = 0 @@ -140,7 +142,7 @@ def to_json_object(printer: _Printer, message: ProtoMessage) -> JsonObject: return [printer._MessageToJsonObject(item) for item in message.val] def from_json_object( - parser: _Parser, value: JsonObject, message: ProtoMessage + parser: _Parser, value: JsonObject, message: ProtoMessage, ) -> None: array = value if isinstance(value, list) else value["val"] for item in array: @@ -181,7 +183,7 @@ def to_json_object(printer: _Printer, message: ProtoMessage) -> JsonObject: return list(message.val) def from_json_object( - parser: _Parser, value: JsonObject, message: ProtoMessage + parser: _Parser, value: JsonObject, message: ProtoMessage, ) -> None: array = value if isinstance(value, list) else value["val"] message.val.extend(array) diff --git a/sdk/python/feast/py.typed b/sdk/python/feast/py.typed new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/feast/registry.py b/sdk/python/feast/registry.py index cb1261d8c93..da9c6c6b217 100644 --- a/sdk/python/feast/registry.py +++ b/sdk/python/feast/registry.py @@ -314,12 +314,17 @@ def apply_data_source( commit: Whether to immediately commit to the registry """ registry = self._prepare_registry_for_changes() - for idx, existing_data_source_proto in enumerate(registry.data_sources): if existing_data_source_proto.name == data_source.name: del registry.data_sources[idx] data_source_proto = data_source.to_proto() + data_source_proto.data_source_class_type = ( + f"{data_source.__class__.__module__}.{data_source.__class__.__name__}" + ) data_source_proto.project = project + data_source_proto.data_source_class_type = ( + f"{data_source.__class__.__module__}.{data_source.__class__.__name__}" + ) registry.data_sources.append(data_source_proto) if commit: self.commit() diff --git a/sdk/python/feast/repo_config.py b/sdk/python/feast/repo_config.py index 20edebf5c7c..c86a42a8bd8 100644 --- a/sdk/python/feast/repo_config.py +++ b/sdk/python/feast/repo_config.py @@ -1,3 +1,4 @@ +import logging import os from pathlib import Path from typing import Any @@ -23,6 +24,8 @@ from feast.importer import import_class from feast.usage import log_exceptions +_logger = logging.getLogger(__name__) + # These dict exists so that: # - existing values for the online store type in featurestore.yaml files continue to work in a backwards compatible way # - first party and third party implementations can use the same class loading code path. @@ -40,6 +43,7 @@ "redshift": "feast.infra.offline_stores.redshift.RedshiftOfflineStore", "snowflake.offline": "feast.infra.offline_stores.snowflake.SnowflakeOfflineStore", "spark": "feast.infra.offline_stores.contrib.spark_offline_store.spark.SparkOfflineStore", + "trino": "feast.infra.offline_stores.contrib.trino_offline_store.trino.TrinoOfflineStore", } FEATURE_SERVER_CONFIG_CLASS_FOR_TYPE = { @@ -54,7 +58,7 @@ class FeastBaseModel(BaseModel): - """ Feast Pydantic Configuration Class """ + """Feast Pydantic Configuration Class""" class Config: arbitrary_types_allowed = True @@ -62,7 +66,7 @@ class Config: class FeastConfigBaseModel(BaseModel): - """ Feast Pydantic Configuration Class """ + """Feast Pydantic Configuration Class""" class Config: arbitrary_types_allowed = True @@ -70,7 +74,7 @@ class Config: class RegistryConfig(FeastBaseModel): - """ Metadata Store Configuration. Configuration that relates to reading from and writing to the Feast registry.""" + """Metadata Store Configuration. Configuration that relates to reading from and writing to the Feast registry.""" registry_store_type: Optional[StrictStr] """ str: Provider name or a class name that implements RegistryStore. """ @@ -86,7 +90,7 @@ class RegistryConfig(FeastBaseModel): class RepoConfig(FeastBaseModel): - """ Repo config. Typically loaded from `feature_store.yaml` """ + """Repo config. Typically loaded from `feature_store.yaml`""" registry: Union[StrictStr, RegistryConfig] = "data/registry.db" """ str: Path to metadata store. Can be a local path, or remote object storage path, e.g. a GCS URI """ @@ -114,6 +118,8 @@ class RepoConfig(FeastBaseModel): repo_path: Optional[Path] = None + go_feature_retrieval: Optional[bool] = False + def __init__(self, **data: Any): super().__init__(**data) @@ -276,7 +282,11 @@ def _validate_flags(cls, v): for flag_name, val in v.items(): if flag_name not in flags.FLAG_NAMES: - raise ValueError(f"Flag name, {flag_name}, not valid.") + _logger.warn( + "Unrecognized flag: %s. This feature may be invalid, or may refer " + "to a previously experimental feature which has graduated to production.", + flag_name, + ) if type(val) is not bool: raise ValueError(f"Flag value, {val}, not valid.") diff --git a/sdk/python/feast/repo_operations.py b/sdk/python/feast/repo_operations.py index 4bee79bd60a..5e223aac8af 100644 --- a/sdk/python/feast/repo_operations.py +++ b/sdk/python/feast/repo_operations.py @@ -12,6 +12,7 @@ import click from click.exceptions import BadParameter +from feast import PushSource from feast.data_source import DataSource from feast.diff.registry_diff import extract_objects_for_keep_delete_update_add from feast.entity import Entity @@ -93,7 +94,7 @@ def get_repo_files(repo_root: Path) -> List[Path]: def parse_repo(repo_root: Path) -> RepoContents: - """ Collect feature table definitions from feature repo """ + """Collect feature table definitions from feature repo""" res = RepoContents( data_sources=set(), entities=set(), @@ -112,6 +113,8 @@ def parse_repo(repo_root: Path) -> RepoContents: res.data_sources.add(obj) if isinstance(obj, FeatureView): res.feature_views.add(obj) + if isinstance(obj.stream_source, PushSource): + res.data_sources.add(obj.stream_source.batch_source) elif isinstance(obj, Entity): res.entities.add(obj) elif isinstance(obj, FeatureService): @@ -185,10 +188,8 @@ def extract_objects_for_apply_delete(project, registry, repo): return ( all_to_apply, all_to_delete, - set( - objs_to_add[FeastObjectType.FEATURE_VIEW].union( - objs_to_update[FeastObjectType.FEATURE_VIEW] - ) + set(objs_to_add[FeastObjectType.FEATURE_VIEW]).union( + set(objs_to_update[FeastObjectType.FEATURE_VIEW]) ), objs_to_delete[FeastObjectType.FEATURE_VIEW], ) @@ -261,7 +262,7 @@ def teardown(repo_config: RepoConfig, repo_path: Path): @log_exceptions_and_usage def registry_dump(repo_config: RepoConfig, repo_path: Path): - """ For debugging only: output contents of the metadata registry """ + """For debugging only: output contents of the metadata registry""" registry_config = repo_config.get_registry_config() project = repo_config.project registry = Registry(registry_config=registry_config, repo_path=repo_path) diff --git a/sdk/python/feast/request_feature_view.py b/sdk/python/feast/request_feature_view.py index 5d716f2f8d2..7248ffe9890 100644 --- a/sdk/python/feast/request_feature_view.py +++ b/sdk/python/feast/request_feature_view.py @@ -1,10 +1,11 @@ import copy -from typing import Type +import warnings +from typing import Dict, List, Optional, Type from feast.base_feature_view import BaseFeatureView -from feast.data_source import RequestDataSource -from feast.feature import Feature +from feast.data_source import RequestSource from feast.feature_view_projection import FeatureViewProjection +from feast.field import Field from feast.protos.feast.core.RequestFeatureView_pb2 import ( RequestFeatureView as RequestFeatureViewProto, ) @@ -14,30 +15,70 @@ class RequestFeatureView(BaseFeatureView): """ - [Experimental] An RequestFeatureView defines a feature that is available from the inference request. - - Args: - name: Name of the group of features. - request_data_source: Request data source that specifies the schema and features + [Experimental] A RequestFeatureView defines a logical group of features that should + be available as an input to an on demand feature view at request time. + + Attributes: + name: The unique name of the request feature view. + request_source: The request source that specifies the schema and + features of the request feature view. + features: The list of features defined as part of this request feature view. + description: A human-readable description. + tags: A dictionary of key-value pairs to store arbitrary metadata. + owner: The owner of the request feature view, typically the email of the primary + maintainer. """ - request_data_source: RequestDataSource + name: str + request_source: RequestSource + features: List[Field] + description: str + tags: Dict[str, str] + owner: str @log_exceptions def __init__( - self, name: str, request_data_source: RequestDataSource, + self, + name: str, + request_data_source: RequestSource, + description: str = "", + tags: Optional[Dict[str, str]] = None, + owner: str = "", ): """ - Creates an RequestFeatureView object. + Creates a RequestFeatureView object. + + Args: + name: The unique name of the request feature view. + request_data_source: The request data source that specifies the schema and + features of the request feature view. + description (optional): A human-readable description. + tags (optional): A dictionary of key-value pairs to store arbitrary metadata. + owner (optional): The owner of the request feature view, typically the email + of the primary maintainer. """ + warnings.warn( + "Request feature view is deprecated. " + "Please use request data source instead", + DeprecationWarning, + ) + + if isinstance(request_data_source.schema, Dict): + new_features = [ + Field(name=name, dtype=dtype) + for name, dtype in request_data_source.schema.items() + ] + else: + new_features = request_data_source.schema + super().__init__( name=name, - features=[ - Feature(name=name, dtype=dtype) - for name, dtype in request_data_source.schema.items() - ], + features=new_features, + description=description, + tags=tags, + owner=owner, ) - self.request_data_source = request_data_source + self.request_source = request_data_source @property def proto_class(self) -> Type[RequestFeatureViewProto]: @@ -51,7 +92,11 @@ def to_proto(self) -> RequestFeatureViewProto: A RequestFeatureViewProto protobuf. """ spec = RequestFeatureViewSpec( - name=self.name, request_data_source=self.request_data_source.to_proto() + name=self.name, + request_data_source=self.request_source.to_proto(), + description=self.description, + tags=self.tags, + owner=self.owner, ) return RequestFeatureViewProto(spec=spec) @@ -70,9 +115,12 @@ def from_proto(cls, request_feature_view_proto: RequestFeatureViewProto): request_feature_view_obj = cls( name=request_feature_view_proto.spec.name, - request_data_source=RequestDataSource.from_proto( + request_data_source=RequestSource.from_proto( request_feature_view_proto.spec.request_data_source ), + description=request_feature_view_proto.spec.description, + tags=dict(request_feature_view_proto.spec.tags), + owner=request_feature_view_proto.spec.owner, ) # FeatureViewProjections are not saved in the RequestFeatureView proto. @@ -84,8 +132,6 @@ def from_proto(cls, request_feature_view_proto: RequestFeatureViewProto): return request_feature_view_obj def __copy__(self): - fv = RequestFeatureView( - name=self.name, request_data_source=self.request_data_source - ) + fv = RequestFeatureView(name=self.name, request_data_source=self.request_source) fv.projection = copy.copy(self.projection) return fv diff --git a/sdk/python/feast/templates/aws/bootstrap.py b/sdk/python/feast/templates/aws/bootstrap.py index 2b64a27e627..80c2480d254 100644 --- a/sdk/python/feast/templates/aws/bootstrap.py +++ b/sdk/python/feast/templates/aws/bootstrap.py @@ -53,14 +53,17 @@ def bootstrap(): repo_path = pathlib.Path(__file__).parent.absolute() config_file = repo_path / "feature_store.yaml" + driver_file = repo_path / "driver_repo.py" replace_str_in_file(config_file, "%AWS_REGION%", aws_region) replace_str_in_file(config_file, "%REDSHIFT_CLUSTER_ID%", cluster_id) replace_str_in_file(config_file, "%REDSHIFT_DATABASE%", database) + replace_str_in_file(driver_file, "%REDSHIFT_DATABASE%", database) replace_str_in_file(config_file, "%REDSHIFT_USER%", user) replace_str_in_file( - config_file, "%REDSHIFT_S3_STAGING_LOCATION%", s3_staging_location + driver_file, config_file, "%REDSHIFT_S3_STAGING_LOCATION%", s3_staging_location ) + replace_str_in_file(config_file,) replace_str_in_file(config_file, "%REDSHIFT_IAM_ROLE%", iam_role) diff --git a/sdk/python/feast/templates/aws/driver_repo.py b/sdk/python/feast/templates/aws/driver_repo.py index 10a0dbb638b..19ba44807b9 100644 --- a/sdk/python/feast/templates/aws/driver_repo.py +++ b/sdk/python/feast/templates/aws/driver_repo.py @@ -1,6 +1,7 @@ from datetime import timedelta -from feast import Entity, Feature, FeatureView, RedshiftSource, ValueType +from feast import Entity, FeatureView, Field, RedshiftSource, ValueType +from feast.types import Float32, Int64 # Define an entity for the driver. Entities can be thought of as primary keys used to # retrieve features. Entities are also used to join multiple tables/views during the @@ -23,10 +24,12 @@ table="feast_driver_hourly_stats", # The event timestamp is used for point-in-time joins and for ensuring only # features within the TTL are returned - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", # The (optional) created timestamp is used to ensure there are no duplicate # feature rows in the offline store or when building training datasets created_timestamp_column="created", + # Database to redshift source. + database="%REDSHIFT_DATABASE%", ) # Feature views are a grouping based on how features are stored in either the @@ -49,10 +52,10 @@ # The list of features defined below act as a schema to both define features # for both materialization of features into a store, and are used as references # during retrieval for building a training dataset or serving features - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], # Batch sources are used to find feature values. In the case of this feature # view we will query a source table on Redshift for driver statistics diff --git a/sdk/python/feast/templates/gcp/driver_repo.py b/sdk/python/feast/templates/gcp/driver_repo.py index 003cd9fa25f..e494e021f2f 100644 --- a/sdk/python/feast/templates/gcp/driver_repo.py +++ b/sdk/python/feast/templates/gcp/driver_repo.py @@ -1,6 +1,7 @@ from datetime import timedelta -from feast import BigQuerySource, Entity, Feature, FeatureView, ValueType +from feast import BigQuerySource, Entity, FeatureView, Field, ValueType +from feast.types import Float32, Int64 # Define an entity for the driver. Entities can be thought of as primary keys used to # retrieve features. Entities are also used to join multiple tables/views during the @@ -20,10 +21,10 @@ # datasets or materializing features into an online store. driver_stats_source = BigQuerySource( # The BigQuery table where features can be found - table_ref="feast-oss.demo_data.driver_hourly_stats_2", + table="feast-oss.demo_data.driver_hourly_stats_2", # The event timestamp is used for point-in-time joins and for ensuring only # features within the TTL are returned - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", # The (optional) created timestamp is used to ensure there are no duplicate # feature rows in the offline store or when building training datasets created_timestamp_column="created", @@ -49,10 +50,10 @@ # The list of features defined below act as a schema to both define features # for both materialization of features into a store, and are used as references # during retrieval for building a training dataset or serving features - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], # Batch sources are used to find feature values. In the case of this feature # view we will query a source table on BigQuery for driver statistics diff --git a/sdk/python/feast/templates/local/example.py b/sdk/python/feast/templates/local/example.py index 9ff4fe3055d..076a331f91a 100644 --- a/sdk/python/feast/templates/local/example.py +++ b/sdk/python/feast/templates/local/example.py @@ -1,15 +1,16 @@ # This is an example feature definition file -from google.protobuf.duration_pb2 import Duration +from datetime import timedelta -from feast import Entity, Feature, FeatureView, FileSource, ValueType +from feast import Entity, FeatureView, Field, FileSource, ValueType +from feast.types import Float32, Int64 # Read data from parquet files. Parquet is convenient for local development mode. For # production, you can use your favorite DWH, such as BigQuery. See Feast documentation # for more info. driver_hourly_stats = FileSource( path="%PARQUET_PATH%", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) @@ -23,11 +24,11 @@ driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", entities=["driver_id"], - ttl=Duration(seconds=86400 * 1), - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + ttl=timedelta(days=1), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], online=True, batch_source=driver_hourly_stats, diff --git a/sdk/python/feast/templates/snowflake/bootstrap.py b/sdk/python/feast/templates/snowflake/bootstrap.py index 3712651a5d9..194ba08c08b 100644 --- a/sdk/python/feast/templates/snowflake/bootstrap.py +++ b/sdk/python/feast/templates/snowflake/bootstrap.py @@ -68,7 +68,7 @@ def bootstrap(): repo_path = pathlib.Path(__file__).parent.absolute() config_file = repo_path / "feature_store.yaml" - + driver_file = repo_path / "driver_repo.py" replace_str_in_file( config_file, "SNOWFLAKE_DEPLOYMENT_URL", snowflake_deployment_url ) @@ -78,6 +78,8 @@ def bootstrap(): replace_str_in_file(config_file, "SNOWFLAKE_WAREHOUSE", snowflake_warehouse) replace_str_in_file(config_file, "SNOWFLAKE_DATABASE", snowflake_database) + replace_str_in_file(driver_file, "SNOWFLAKE_WAREHOUSE", snowflake_warehouse) + def replace_str_in_file(file_path, match_str, sub_str): with open(file_path, "r") as f: diff --git a/sdk/python/feast/templates/snowflake/driver_repo.py b/sdk/python/feast/templates/snowflake/driver_repo.py index a63c6cb5030..c14e4c38cc9 100644 --- a/sdk/python/feast/templates/snowflake/driver_repo.py +++ b/sdk/python/feast/templates/snowflake/driver_repo.py @@ -2,7 +2,8 @@ import yaml -from feast import Entity, Feature, FeatureView, SnowflakeSource, ValueType +from feast import Entity, FeatureView, Field, SnowflakeSource +from feast.types import Float32, Int64 # Define an entity for the driver. Entities can be thought of as primary keys used to # retrieve features. Entities are also used to join multiple tables/views during the @@ -24,9 +25,10 @@ # The Snowflake table where features can be found database=yaml.safe_load(open("feature_store.yaml"))["offline_store"]["database"], table=f"{project_name}_feast_driver_hourly_stats", + warehouse="SNOWFLAKE_WAREHOUSE", # The event timestamp is used for point-in-time joins and for ensuring only # features within the TTL are returned - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", # The (optional) created timestamp is used to ensure there are no duplicate # feature rows in the offline store or when building training datasets created_timestamp_column="created", @@ -52,10 +54,10 @@ # The list of features defined below act as a schema to both define features # for both materialization of features into a store, and are used as references # during retrieval for building a training dataset or serving features - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], # Batch sources are used to find feature values. In the case of this feature # view we will query a source table on Redshift for driver statistics diff --git a/sdk/python/feast/templates/spark/bootstrap.py b/sdk/python/feast/templates/spark/bootstrap.py index 155a86bf484..b57387d3d7d 100644 --- a/sdk/python/feast/templates/spark/bootstrap.py +++ b/sdk/python/feast/templates/spark/bootstrap.py @@ -1,48 +1,35 @@ -from datetime import datetime, timedelta -from pathlib import Path - -from pyspark.sql import SparkSession - -from feast.driver_test_data import ( - create_customer_daily_profile_df, - create_driver_hourly_stats_df, -) - -CURRENT_DIR = Path(__file__).parent -DRIVER_ENTITIES = [1001, 1002, 1003] -CUSTOMER_ENTITIES = [201, 202, 203] -START_DATE = datetime.strptime("2022-01-01", "%Y-%m-%d") -END_DATE = START_DATE + timedelta(days=7) - - def bootstrap(): # Bootstrap() will automatically be called from the init_repo() during `feast init` - generate_example_data( - spark_session=SparkSession.builder.getOrCreate(), base_dir=str(CURRENT_DIR), - ) - + import pathlib + from datetime import datetime, timedelta -def example_data_exists(base_dir: str) -> bool: - for path in [ - Path(base_dir) / "data" / "driver_hourly_stats", - Path(base_dir) / "data" / "customer_daily_profile", - ]: - if not path.exists(): - return False - return True + from feast.driver_test_data import ( + create_customer_daily_profile_df, + create_driver_hourly_stats_df, + ) + repo_path = pathlib.Path(__file__).parent.absolute() + data_path = repo_path / "data" + data_path.mkdir(exist_ok=True) -def generate_example_data(spark_session: SparkSession, base_dir: str) -> None: - spark_session.createDataFrame( - data=create_driver_hourly_stats_df(DRIVER_ENTITIES, START_DATE, END_DATE) - ).write.parquet( - path=str(Path(base_dir) / "data" / "driver_hourly_stats"), mode="overwrite", + driver_entities = [1001, 1002, 1003] + end_date = datetime.now().replace(microsecond=0, second=0, minute=0) + start_date = end_date - timedelta(days=15) + driver_stats_df = create_driver_hourly_stats_df( + driver_entities, start_date, end_date + ) + driver_stats_df.to_parquet( + path=str(data_path / "driver_hourly_stats.parquet"), + allow_truncated_timestamps=True, ) - spark_session.createDataFrame( - data=create_customer_daily_profile_df(CUSTOMER_ENTITIES, START_DATE, END_DATE) - ).write.parquet( - path=str(Path(base_dir) / "data" / "customer_daily_profile"), mode="overwrite", + customer_entities = [201, 202, 203] + customer_profile_df = create_customer_daily_profile_df( + customer_entities, start_date, end_date + ) + customer_profile_df.to_parquet( + path=str(data_path / "customer_daily_profile.parquet"), + allow_truncated_timestamps=True, ) diff --git a/sdk/python/feast/templates/spark/example.py b/sdk/python/feast/templates/spark/example.py index ddda73b7872..c8c1c1257eb 100644 --- a/sdk/python/feast/templates/spark/example.py +++ b/sdk/python/feast/templates/spark/example.py @@ -2,14 +2,14 @@ # This is an example feature definition file # # # # # # # # # # # # # # # # # # # # # # # # # +from datetime import timedelta from pathlib import Path -from google.protobuf.duration_pb2 import Duration - -from feast import Entity, Feature, FeatureView, ValueType +from feast import Entity, FeatureView, Field, ValueType from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( SparkSource, ) +from feast.types import Float32, Int64 # Constants related to the generated data sets CURRENT_DIR = Path(__file__).parent @@ -23,15 +23,17 @@ # Sources driver_hourly_stats = SparkSource( - path=f"{CURRENT_DIR}/data/driver_hourly_stats", + name="driver_hourly_stats", + path=f"{CURRENT_DIR}/data/driver_hourly_stats.parquet", file_format="parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) customer_daily_profile = SparkSource( - path=f"{CURRENT_DIR}/data/customer_daily_profile", + name="customer_daily_profile", + path=f"{CURRENT_DIR}/data/customer_daily_profile.parquet", file_format="parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) @@ -39,11 +41,11 @@ driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", entities=["driver_id"], - ttl=Duration(seconds=86400 * 7), # one week - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + ttl=timedelta(days=7), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], online=True, batch_source=driver_hourly_stats, @@ -52,11 +54,11 @@ customer_daily_profile_view = FeatureView( name="customer_daily_profile", entities=["customer_id"], - ttl=Duration(seconds=86400 * 7), # one week - features=[ - Feature(name="current_balance", dtype=ValueType.FLOAT), - Feature(name="avg_passenger_count", dtype=ValueType.FLOAT), - Feature(name="lifetime_trip_count", dtype=ValueType.INT64), + ttl=timedelta(days=7), + schema=[ + Field(name="current_balance", dtype=Float32), + Field(name="avg_passenger_count", dtype=Float32), + Field(name="lifetime_trip_count", dtype=Int64), ], online=True, batch_source=customer_daily_profile, diff --git a/sdk/python/feast/type_map.py b/sdk/python/feast/type_map.py index 713b952d092..9798faf508b 100644 --- a/sdk/python/feast/type_map.py +++ b/sdk/python/feast/type_map.py @@ -580,10 +580,10 @@ def pa_to_redshift_value_type(pa_type: pyarrow.DataType) -> str: def _non_empty_value(value: Any) -> bool: """ - Check that there's enough data we can use for type inference. - If primitive type - just checking that it's not None - If iterable - checking that there's some elements (len > 0) - String is special case: "" - empty string is considered non empty + Check that there's enough data we can use for type inference. + If primitive type - just checking that it's not None + If iterable - checking that there's some elements (len > 0) + String is special case: "" - empty string is considered non empty """ return value is not None and ( not isinstance(value, Sized) or len(value) > 0 or isinstance(value, str) diff --git a/sdk/python/feast/types.py b/sdk/python/feast/types.py new file mode 100644 index 00000000000..40c1d62e7d2 --- /dev/null +++ b/sdk/python/feast/types.py @@ -0,0 +1,194 @@ +# Copyright 2022 The Feast Authors +# +# 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 +# +# https://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. +from abc import ABC, abstractmethod +from enum import Enum +from typing import Dict, Union + +from feast.value_type import ValueType + +PRIMITIVE_FEAST_TYPES_TO_VALUE_TYPES = { + "INVALID": "UNKNOWN", + "BYTES": "BYTES", + "STRING": "STRING", + "INT32": "INT32", + "INT64": "INT64", + "FLOAT64": "DOUBLE", + "FLOAT32": "FLOAT", + "BOOL": "BOOL", + "UNIX_TIMESTAMP": "UNIX_TIMESTAMP", +} + + +class ComplexFeastType(ABC): + """ + A ComplexFeastType represents a structured type that is recognized by Feast. + """ + + def __init__(self): + """Creates a ComplexFeastType object.""" + pass + + @abstractmethod + def to_value_type(self) -> ValueType: + """ + Converts a ComplexFeastType object to the corresponding ValueType enum. + """ + raise NotImplementedError + + def __hash__(self): + return hash(self.to_value_type().value) + + def __eq__(self, other): + return self.to_value_type() == other.to_value_type() + + +class PrimitiveFeastType(Enum): + """ + A PrimitiveFeastType represents a primitive type in Feast. + + Note that these values must match the values in /feast/protos/types/Value.proto. + """ + + INVALID = 0 + BYTES = 1 + STRING = 2 + INT32 = 3 + INT64 = 4 + FLOAT64 = 5 + FLOAT32 = 6 + BOOL = 7 + UNIX_TIMESTAMP = 8 + + def to_value_type(self) -> ValueType: + """ + Converts a PrimitiveFeastType object to the corresponding ValueType enum. + """ + value_type_name = PRIMITIVE_FEAST_TYPES_TO_VALUE_TYPES[self.name] + return ValueType[value_type_name] + + def __str__(self): + return PRIMITIVE_FEAST_TYPES_TO_STRING[self.name] + + def __eq__(self, other): + if isinstance(other, PrimitiveFeastType): + return self.value == other.value + else: + return False + + def __hash__(self): + return hash((PRIMITIVE_FEAST_TYPES_TO_STRING[self.name])) + + +Invalid = PrimitiveFeastType.INVALID +Bytes = PrimitiveFeastType.BYTES +String = PrimitiveFeastType.STRING +Bool = PrimitiveFeastType.BOOL +Int32 = PrimitiveFeastType.INT32 +Int64 = PrimitiveFeastType.INT64 +Float32 = PrimitiveFeastType.FLOAT32 +Float64 = PrimitiveFeastType.FLOAT64 +UnixTimestamp = PrimitiveFeastType.UNIX_TIMESTAMP + + +SUPPORTED_BASE_TYPES = [ + Invalid, + String, + Bytes, + Bool, + Int32, + Int64, + Float32, + Float64, + UnixTimestamp, +] + +PRIMITIVE_FEAST_TYPES_TO_STRING = { + "INVALID": "Invalid", + "STRING": "String", + "BYTES": "Bytes", + "BOOL": "Bool", + "INT32": "Int32", + "INT64": "Int64", + "FLOAT32": "Float32", + "FLOAT64": "Float64", + "UNIX_TIMESTAMP": "UnixTimestamp", +} + + +class Array(ComplexFeastType): + """ + An Array represents a list of types. + + Attributes: + base_type: The base type of the array. + """ + + base_type: Union[PrimitiveFeastType, ComplexFeastType] + + def __init__(self, base_type: Union[PrimitiveFeastType, ComplexFeastType]): + if base_type not in SUPPORTED_BASE_TYPES: + raise ValueError( + f"Type {type(base_type)} is currently not supported as a base type for Array." + ) + + self.base_type = base_type + + def to_value_type(self) -> ValueType: + assert isinstance(self.base_type, PrimitiveFeastType) + value_type_name = PRIMITIVE_FEAST_TYPES_TO_VALUE_TYPES[self.base_type.name] + value_type_list_name = value_type_name + "_LIST" + return ValueType[value_type_list_name] + + def __str__(self): + return f"Array({self.base_type})" + + +FeastType = Union[ComplexFeastType, PrimitiveFeastType] + + +VALUE_TYPES_TO_FEAST_TYPES: Dict["ValueType", FeastType] = { + ValueType.UNKNOWN: Invalid, + ValueType.BYTES: Bytes, + ValueType.STRING: String, + ValueType.INT32: Int32, + ValueType.INT64: Int64, + ValueType.DOUBLE: Float64, + ValueType.FLOAT: Float32, + ValueType.BOOL: Bool, + ValueType.UNIX_TIMESTAMP: UnixTimestamp, + ValueType.BYTES_LIST: Array(Bytes), + ValueType.STRING_LIST: Array(String), + ValueType.INT32_LIST: Array(Int32), + ValueType.INT64_LIST: Array(Int64), + ValueType.DOUBLE_LIST: Array(Float64), + ValueType.FLOAT_LIST: Array(Float32), + ValueType.BOOL_LIST: Array(Bool), + ValueType.UNIX_TIMESTAMP_LIST: Array(UnixTimestamp), +} + + +def from_value_type(value_type: ValueType,) -> FeastType: + """ + Converts a ValueType enum to a Feast type. + + Args: + value_type: The ValueType to be converted. + + Raises: + ValueError: The conversion could not be performed. + """ + if value_type in VALUE_TYPES_TO_FEAST_TYPES: + return VALUE_TYPES_TO_FEAST_TYPES[value_type] + + raise ValueError(f"Could not convert value type {value_type} to FeastType.") diff --git a/sdk/python/feast/usage.py b/sdk/python/feast/usage.py index 6a6a7146ce7..90b659479d1 100644 --- a/sdk/python/feast/usage.py +++ b/sdk/python/feast/usage.py @@ -224,27 +224,27 @@ def tracing_span(name): def log_exceptions_and_usage(*args, **attrs): """ - This function decorator enables three components: - 1. Error tracking - 2. Usage statistic collection - 3. Time profiling - - This data is being collected, anonymized and sent to Feast Developers. - All events from nested decorated functions are being grouped into single event - to build comprehensive context useful for profiling and error tracking. - - Usage example (will result in one output event): - @log_exceptions_and_usage - def fn(...): - nested() - - @log_exceptions_and_usage(attr='value') - def nested(...): - deeply_nested() - - @log_exceptions_and_usage(attr2='value2', sample=RateSampler(rate=0.1)) - def deeply_nested(...): - ... + This function decorator enables three components: + 1. Error tracking + 2. Usage statistic collection + 3. Time profiling + + This data is being collected, anonymized and sent to Feast Developers. + All events from nested decorated functions are being grouped into single event + to build comprehensive context useful for profiling and error tracking. + + Usage example (will result in one output event): + @log_exceptions_and_usage + def fn(...): + nested() + + @log_exceptions_and_usage(attr='value') + def nested(...): + deeply_nested() + + @log_exceptions_and_usage(attr2='value2', sample=RateSampler(rate=0.1)) + def deeply_nested(...): + ... """ sampler = attrs.pop("sampler", AlwaysSampler()) diff --git a/sdk/python/feast/utils.py b/sdk/python/feast/utils.py index 890c48fcbe2..e521338680c 100644 --- a/sdk/python/feast/utils.py +++ b/sdk/python/feast/utils.py @@ -4,7 +4,7 @@ def make_tzaware(t: datetime) -> datetime: - """ We assume tz-naive datetimes are UTC """ + """We assume tz-naive datetimes are UTC""" if t.tzinfo is None: return t.replace(tzinfo=utc) else: diff --git a/sdk/python/requirements/py3.10-ci-requirements.txt b/sdk/python/requirements/py3.10-ci-requirements.txt new file mode 100644 index 00000000000..e120f8c58e4 --- /dev/null +++ b/sdk/python/requirements/py3.10-ci-requirements.txt @@ -0,0 +1,832 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --extra=ci --output-file=requirements/py3.10-ci-requirements.txt +# +absl-py==1.0.0 + # via tensorflow-metadata +adal==1.2.7 + # via + # azure-datalake-store + # msrestazure +adlfs==0.5.9 + # via feast (setup.py) +aiohttp==3.8.1 + # via + # adlfs + # gcsfs +aiosignal==1.2.0 + # via aiohttp +alabaster==0.7.12 + # via sphinx +altair==4.2.0 + # via great-expectations +anyio==3.5.0 + # via starlette +appdirs==1.4.4 + # via black +appnope==0.1.2 + # via + # ipykernel + # ipython +argon2-cffi==21.3.0 + # via notebook +argon2-cffi-bindings==21.2.0 + # via argon2-cffi +asgiref==3.5.0 + # via uvicorn +asn1crypto==1.4.0 + # via + # oscrypto + # snowflake-connector-python +assertpy==1.1 + # via feast (setup.py) +asttokens==2.0.5 + # via stack-data +async-timeout==4.0.2 + # via aiohttp +attrs==21.4.0 + # via + # aiohttp + # black + # jsonschema + # pytest +avro==1.10.0 + # via feast (setup.py) +azure-core==1.23.0 + # via + # adlfs + # azure-identity + # azure-storage-blob +azure-datalake-store==0.0.52 + # via adlfs +azure-identity==1.8.0 + # via adlfs +azure-storage-blob==12.9.0 + # via adlfs +babel==2.9.1 + # via sphinx +backcall==0.2.0 + # via ipython +black==19.10b0 + # via feast (setup.py) +bleach==4.1.0 + # via nbconvert +boto3==1.21.11 + # via + # feast (setup.py) + # moto +botocore==1.24.11 + # via + # boto3 + # moto + # s3transfer +cachecontrol==0.12.10 + # via firebase-admin +cachetools==4.2.4 + # via google-auth +certifi==2021.10.8 + # via + # minio + # msrest + # requests + # snowflake-connector-python +cffi==1.15.0 + # via + # argon2-cffi-bindings + # azure-datalake-store + # cryptography + # snowflake-connector-python +cfgv==3.3.1 + # via pre-commit +charset-normalizer==2.0.12 + # via + # aiohttp + # requests + # snowflake-connector-python +click==8.0.4 + # via + # black + # feast (setup.py) + # great-expectations + # pip-tools + # uvicorn +cloudpickle==2.0.0 + # via dask +colorama==0.4.4 + # via feast (setup.py) +coverage[toml]==6.3.2 + # via pytest-cov +cryptography==3.3.2 + # via + # adal + # azure-identity + # azure-storage-blob + # feast (setup.py) + # moto + # msal + # pyjwt + # pyopenssl + # snowflake-connector-python +dask==2022.1.1 + # via feast (setup.py) +debugpy==1.5.1 + # via ipykernel +decorator==5.1.1 + # via + # gcsfs + # ipython +defusedxml==0.7.1 + # via nbconvert +deprecation==2.1.0 + # via testcontainers +dill==0.3.4 + # via feast (setup.py) +distlib==0.3.4 + # via virtualenv +docker==5.0.3 + # via + # feast (setup.py) + # testcontainers +docutils==0.17.1 + # via + # sphinx + # sphinx-rtd-theme +entrypoints==0.4 + # via + # altair + # jupyter-client + # nbconvert +execnet==1.9.0 + # via pytest-xdist +executing==0.8.3 + # via stack-data +fastapi==0.74.1 + # via feast (setup.py) +fastavro==1.4.9 + # via + # feast (setup.py) + # pandavro +filelock==3.6.0 + # via virtualenv +firebase-admin==4.5.2 + # via feast (setup.py) +flake8==4.0.1 + # via feast (setup.py) +frozenlist==1.3.0 + # via + # aiohttp + # aiosignal +fsspec==2022.2.0 + # via + # adlfs + # dask + # gcsfs +gcsfs==2022.2.0 + # via feast (setup.py) +google-api-core[grpc]==1.31.5 + # via + # feast (setup.py) + # firebase-admin + # google-api-python-client + # google-cloud-bigquery + # google-cloud-bigquery-storage + # google-cloud-core + # google-cloud-datastore + # google-cloud-firestore +google-api-python-client==2.39.0 + # via firebase-admin +google-auth==1.35.0 + # via + # gcsfs + # google-api-core + # google-api-python-client + # google-auth-httplib2 + # google-auth-oauthlib + # google-cloud-core + # google-cloud-storage +google-auth-httplib2==0.1.0 + # via google-api-python-client +google-auth-oauthlib==0.5.0 + # via gcsfs +google-cloud-bigquery==2.34.1 + # via feast (setup.py) +google-cloud-bigquery-storage==2.12.0 + # via feast (setup.py) +google-cloud-core==1.7.2 + # via + # feast (setup.py) + # google-cloud-bigquery + # google-cloud-datastore + # google-cloud-firestore + # google-cloud-storage +google-cloud-datastore==2.5.0 + # via feast (setup.py) +google-cloud-firestore==2.3.4 + # via firebase-admin +google-cloud-storage==1.40.0 + # via + # feast (setup.py) + # firebase-admin + # gcsfs +google-crc32c==1.3.0 + # via google-resumable-media +google-resumable-media==1.3.3 + # via + # google-cloud-bigquery + # google-cloud-storage +googleapis-common-protos==1.52.0 + # via + # feast (setup.py) + # google-api-core + # tensorflow-metadata +great-expectations==0.14.8 + # via feast (setup.py) +grpcio==1.44.0 + # via + # feast (setup.py) + # google-api-core + # google-cloud-bigquery + # grpcio-reflection + # grpcio-testing + # grpcio-tools +grpcio-reflection==1.44.0 + # via feast (setup.py) +grpcio-testing==1.44.0 + # via feast (setup.py) +grpcio-tools==1.44.0 + # via feast (setup.py) +h11==0.13.0 + # via uvicorn +hiredis==2.0.0 + # via feast (setup.py) +httplib2==0.20.4 + # via + # google-api-python-client + # google-auth-httplib2 +httptools==0.3.0 + # via uvicorn +identify==2.4.11 + # via pre-commit +idna==3.3 + # via + # anyio + # requests + # snowflake-connector-python + # yarl +imagesize==1.3.0 + # via sphinx +importlib-metadata==4.11.2 + # via great-expectations +iniconfig==1.1.1 + # via pytest +ipykernel==6.9.1 + # via + # ipywidgets + # notebook +ipython==8.1.1 + # via + # ipykernel + # ipywidgets +ipython-genutils==0.2.0 + # via + # ipywidgets + # nbformat + # notebook +ipywidgets==7.6.5 + # via great-expectations +isodate==0.6.1 + # via msrest +isort==5.10.1 + # via feast (setup.py) +jedi==0.18.1 + # via ipython +jinja2==3.0.3 + # via + # altair + # feast (setup.py) + # great-expectations + # moto + # nbconvert + # notebook + # sphinx +jmespath==0.10.0 + # via + # boto3 + # botocore +jsonpatch==1.32 + # via great-expectations +jsonpointer==2.2 + # via jsonpatch +jsonschema==4.4.0 + # via + # altair + # feast (setup.py) + # great-expectations + # nbformat +jupyter-client==7.1.2 + # via + # ipykernel + # nbclient + # notebook +jupyter-core==4.9.2 + # via + # jupyter-client + # nbconvert + # nbformat + # notebook +jupyterlab-pygments==0.1.2 + # via nbconvert +jupyterlab-widgets==1.0.2 + # via ipywidgets +locket==0.2.1 + # via partd +markupsafe==2.1.0 + # via + # jinja2 + # moto +matplotlib-inline==0.1.3 + # via + # ipykernel + # ipython +mccabe==0.6.1 + # via flake8 +minio==7.1.0 + # via feast (setup.py) +mistune==0.8.4 + # via + # great-expectations + # nbconvert +mmh3==3.0.0 + # via feast (setup.py) +mock==2.0.0 + # via feast (setup.py) +moto==3.0.5 + # via feast (setup.py) +msal==1.17.0 + # via + # azure-identity + # msal-extensions +msal-extensions==0.3.1 + # via azure-identity +msgpack==1.0.3 + # via cachecontrol +msrest==0.6.21 + # via + # azure-storage-blob + # msrestazure +msrestazure==0.6.4 + # via adlfs +multidict==6.0.2 + # via + # aiohttp + # yarl +mypy==0.931 + # via feast (setup.py) +mypy-extensions==0.4.3 + # via mypy +mypy-protobuf==3.1.0 + # via feast (setup.py) +nbclient==0.5.11 + # via nbconvert +nbconvert==6.4.2 + # via notebook +nbformat==5.1.3 + # via + # ipywidgets + # nbclient + # nbconvert + # notebook +nest-asyncio==1.5.4 + # via + # ipykernel + # jupyter-client + # nbclient + # notebook +nodeenv==1.6.0 + # via pre-commit +notebook==6.4.10 + # via widgetsnbextension +numpy==1.22.2 + # via + # altair + # great-expectations + # pandas + # pandavro + # pyarrow + # scipy +oauthlib==3.2.0 + # via requests-oauthlib +oscrypto==1.2.1 + # via snowflake-connector-python +packaging==21.3 + # via + # bleach + # dask + # deprecation + # google-api-core + # google-cloud-bigquery + # google-cloud-firestore + # pytest + # sphinx +pandas==1.3.5 + # via + # altair + # feast (setup.py) + # great-expectations + # pandavro + # snowflake-connector-python +pandavro==1.5.2 + # via feast (setup.py) +pandocfilters==1.5.0 + # via nbconvert +parso==0.8.3 + # via jedi +partd==1.2.0 + # via dask +pathspec==0.9.0 + # via black +pbr==5.8.1 + # via mock +pep517==0.12.0 + # via pip-tools +pexpect==4.8.0 + # via ipython +pickleshare==0.7.5 + # via ipython +pip-tools==6.5.1 + # via feast (setup.py) +platformdirs==2.5.1 + # via virtualenv +pluggy==1.0.0 + # via pytest +portalocker==2.4.0 + # via msal-extensions +pre-commit==2.17.0 + # via feast (setup.py) +prometheus-client==0.13.1 + # via notebook +prompt-toolkit==3.0.28 + # via ipython +proto-plus==1.19.6 + # via + # feast (setup.py) + # google-cloud-bigquery + # google-cloud-bigquery-storage + # google-cloud-datastore + # google-cloud-firestore +protobuf==3.19.4 + # via + # feast (setup.py) + # google-api-core + # google-cloud-bigquery + # googleapis-common-protos + # grpcio-reflection + # grpcio-testing + # grpcio-tools + # mypy-protobuf + # proto-plus + # tensorflow-metadata +psutil==5.9.0 + # via feast (setup.py) +ptyprocess==0.7.0 + # via + # pexpect + # terminado +pure-eval==0.2.2 + # via stack-data +py==1.11.0 + # via + # pytest + # pytest-forked +py-cpuinfo==8.0.0 + # via pytest-benchmark +py4j==0.10.9.3 + # via pyspark +pyarrow==6.0.1 + # via + # feast (setup.py) + # snowflake-connector-python +pyasn1==0.4.8 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.2.8 + # via google-auth +pybindgen==0.22.0 + # via feast (setup.py) +pycodestyle==2.8.0 + # via flake8 +pycparser==2.21 + # via cffi +pycryptodomex==3.14.1 + # via snowflake-connector-python +pydantic==1.9.0 + # via + # fastapi + # feast (setup.py) +pyflakes==2.4.0 + # via flake8 +pygments==2.11.2 + # via + # ipython + # jupyterlab-pygments + # nbconvert + # sphinx +pyjwt[crypto]==2.3.0 + # via + # adal + # msal + # snowflake-connector-python +pyopenssl==21.0.0 + # via snowflake-connector-python +pyparsing==2.4.7 + # via + # great-expectations + # httplib2 + # packaging +pyrsistent==0.18.1 + # via jsonschema +pyspark==3.2.1 + # via feast (setup.py) +pytest==7.0.1 + # via + # feast (setup.py) + # pytest-benchmark + # pytest-cov + # pytest-forked + # pytest-lazy-fixture + # pytest-mock + # pytest-ordering + # pytest-timeout + # pytest-xdist +pytest-benchmark==3.4.1 + # via feast (setup.py) +pytest-cov==3.0.0 + # via feast (setup.py) +pytest-forked==1.4.0 + # via pytest-xdist +pytest-lazy-fixture==0.6.3 + # via feast (setup.py) +pytest-mock==1.10.4 + # via feast (setup.py) +pytest-ordering==0.6 + # via feast (setup.py) +pytest-timeout==1.4.2 + # via feast (setup.py) +pytest-xdist==2.5.0 + # via feast (setup.py) +python-dateutil==2.8.2 + # via + # adal + # botocore + # google-cloud-bigquery + # great-expectations + # jupyter-client + # moto + # pandas +python-dotenv==0.19.2 + # via uvicorn +pytz==2021.3 + # via + # babel + # google-api-core + # great-expectations + # moto + # pandas + # snowflake-connector-python +pytz-deprecation-shim==0.1.0.post0 + # via tzlocal +pyyaml==6.0 + # via + # dask + # feast (setup.py) + # pre-commit + # uvicorn +pyzmq==22.3.0 + # via + # jupyter-client + # notebook +redis==3.5.3 + # via + # feast (setup.py) + # redis-py-cluster +redis-py-cluster==2.1.3 + # via feast (setup.py) +regex==2022.3.2 + # via black +requests==2.27.1 + # via + # adal + # adlfs + # azure-core + # azure-datalake-store + # cachecontrol + # docker + # gcsfs + # google-api-core + # google-cloud-bigquery + # google-cloud-storage + # great-expectations + # moto + # msal + # msrest + # requests-oauthlib + # responses + # snowflake-connector-python + # sphinx +requests-oauthlib==1.3.1 + # via + # google-auth-oauthlib + # msrest +responses==0.18.0 + # via moto +rsa==4.8 + # via google-auth +ruamel.yaml==0.17.17 + # via great-expectations +ruamel.yaml.clib==0.2.6 + # via ruamel.yaml +s3transfer==0.5.2 + # via boto3 +scipy==1.8.0 + # via great-expectations +send2trash==1.8.0 + # via notebook +six==1.16.0 + # via + # absl-py + # asttokens + # azure-core + # azure-identity + # bleach + # cryptography + # google-api-core + # google-auth + # google-auth-httplib2 + # google-cloud-core + # google-resumable-media + # grpcio + # isodate + # mock + # msrestazure + # pandavro + # pyopenssl + # python-dateutil + # virtualenv +sniffio==1.2.0 + # via anyio +snowballstemmer==2.2.0 + # via sphinx +snowflake-connector-python[pandas]==2.7.4 + # via feast (setup.py) +sphinx==4.3.2 + # via + # feast (setup.py) + # sphinx-rtd-theme +sphinx-rtd-theme==1.0.0 + # via feast (setup.py) +sphinxcontrib-applehelp==1.0.2 + # via sphinx +sphinxcontrib-devhelp==1.0.2 + # via sphinx +sphinxcontrib-htmlhelp==2.0.0 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.3 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 + # via sphinx +stack-data==0.2.0 + # via ipython +starlette==0.17.1 + # via fastapi +tabulate==0.8.9 + # via feast (setup.py) +tenacity==8.0.1 + # via feast (setup.py) +tensorflow-metadata==1.7.0 + # via feast (setup.py) +termcolor==1.1.0 + # via great-expectations +terminado==0.13.2 + # via notebook +testcontainers==3.4.2 + # via feast (setup.py) +testpath==0.6.0 + # via nbconvert +toml==0.10.2 + # via + # black + # feast (setup.py) + # pre-commit +tomli==2.0.1 + # via + # coverage + # mypy + # pep517 + # pytest +toolz==0.11.2 + # via + # altair + # dask + # partd +tornado==6.1 + # via + # ipykernel + # jupyter-client + # notebook + # terminado +tqdm==4.63.0 + # via + # feast (setup.py) + # great-expectations +traitlets==5.1.1 + # via + # ipykernel + # ipython + # ipywidgets + # jupyter-client + # jupyter-core + # matplotlib-inline + # nbclient + # nbconvert + # nbformat + # notebook +typed-ast==1.5.2 + # via black +types-protobuf==3.19.12 + # via + # feast (setup.py) + # mypy-protobuf +types-python-dateutil==2.8.9 + # via feast (setup.py) +types-pytz==2021.3.5 + # via feast (setup.py) +types-pyyaml==6.0.4 + # via feast (setup.py) +types-redis==4.1.17 + # via feast (setup.py) +types-requests==2.27.11 + # via feast (setup.py) +types-setuptools==57.4.9 + # via feast (setup.py) +types-tabulate==0.8.5 + # via feast (setup.py) +types-urllib3==1.26.10 + # via types-requests +typing-extensions==4.1.1 + # via + # azure-core + # great-expectations + # mypy + # pydantic +tzdata==2021.5 + # via pytz-deprecation-shim +tzlocal==4.1 + # via great-expectations +uritemplate==4.1.1 + # via google-api-python-client +urllib3==1.26.8 + # via + # botocore + # feast (setup.py) + # minio + # requests + # responses +uvicorn[standard]==0.17.5 + # via feast (setup.py) +uvloop==0.16.0 + # via uvicorn +virtualenv==20.13.2 + # via pre-commit +watchgod==0.7 + # via uvicorn +wcwidth==0.2.5 + # via prompt-toolkit +webencodings==0.5.1 + # via bleach +websocket-client==1.3.1 + # via docker +websockets==10.2 + # via uvicorn +werkzeug==2.0.3 + # via moto +wheel==0.37.1 + # via pip-tools +widgetsnbextension==3.5.2 + # via ipywidgets +wrapt==1.13.3 + # via testcontainers +xmltodict==0.12.0 + # via moto +yarl==1.7.2 + # via aiohttp +zipp==3.7.0 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/sdk/python/requirements/py3.10-requirements.txt b/sdk/python/requirements/py3.10-requirements.txt new file mode 100644 index 00000000000..e21a4ba4129 --- /dev/null +++ b/sdk/python/requirements/py3.10-requirements.txt @@ -0,0 +1,169 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --output-file=requirements/py3.10-requirements.txt +# +absl-py==1.0.0 + # via tensorflow-metadata +anyio==3.5.0 + # via starlette +asgiref==3.4.1 + # via uvicorn +attrs==21.4.0 + # via jsonschema +cachetools==4.2.4 + # via google-auth +certifi==2021.10.8 + # via requests +charset-normalizer==2.0.10 + # via requests +click==8.0.3 + # via + # feast (setup.py) + # uvicorn +cloudpickle==2.0.0 + # via dask +colorama==0.4.4 + # via feast (setup.py) +dask==2022.1.1 + # via feast (setup.py) +dill==0.3.4 + # via feast (setup.py) +fastapi==0.72.0 + # via feast (setup.py) +fastavro==1.4.9 + # via + # feast (setup.py) + # pandavro +fsspec==2022.2.0 + # via dask +google-api-core==2.4.0 + # via feast (setup.py) +google-auth==2.3.3 + # via google-api-core +googleapis-common-protos==1.52.0 + # via + # feast (setup.py) + # google-api-core + # tensorflow-metadata +grpcio==1.43.0 + # via + # feast (setup.py) + # grpcio-reflection +grpcio-reflection==1.43.0 + # via feast (setup.py) +h11==0.13.0 + # via uvicorn +httptools==0.3.0 + # via uvicorn +idna==3.3 + # via + # anyio + # requests +jinja2==3.0.3 + # via feast (setup.py) +jsonschema==4.4.0 + # via feast (setup.py) +locket==0.2.1 + # via partd +markupsafe==2.0.1 + # via jinja2 +mmh3==3.0.0 + # via feast (setup.py) +numpy==1.21.5 + # via + # pandas + # pandavro + # pyarrow +packaging==21.3 + # via dask +pandas==1.3.5 + # via + # feast (setup.py) + # pandavro +pandavro==1.5.2 + # via feast (setup.py) +partd==1.2.0 + # via dask +proto-plus==1.19.6 + # via feast (setup.py) +protobuf==3.19.3 + # via + # feast (setup.py) + # google-api-core + # googleapis-common-protos + # grpcio-reflection + # proto-plus + # tensorflow-metadata +pyarrow==6.0.1 + # via feast (setup.py) +pyasn1==0.4.8 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.2.8 + # via google-auth +pydantic==1.9.0 + # via + # fastapi + # feast (setup.py) +pyparsing==3.0.7 + # via packaging +pyrsistent==0.18.1 + # via jsonschema +python-dateutil==2.8.2 + # via pandas +python-dotenv==0.19.2 + # via uvicorn +pytz==2021.3 + # via pandas +pyyaml==6.0 + # via + # dask + # feast (setup.py) + # uvicorn +requests==2.27.1 + # via google-api-core +rsa==4.8 + # via google-auth +six==1.16.0 + # via + # absl-py + # google-auth + # grpcio + # pandavro + # python-dateutil +sniffio==1.2.0 + # via anyio +starlette==0.17.1 + # via fastapi +tabulate==0.8.9 + # via feast (setup.py) +tenacity==8.0.1 + # via feast (setup.py) +tensorflow-metadata==1.6.0 + # via feast (setup.py) +toml==0.10.2 + # via feast (setup.py) +toolz==0.11.2 + # via + # dask + # partd +tqdm==4.62.3 + # via feast (setup.py) +typing-extensions==4.0.1 + # via pydantic +urllib3==1.26.8 + # via requests +uvicorn[standard]==0.17.0 + # via feast (setup.py) +uvloop==0.16.0 + # via uvicorn +watchgod==0.7 + # via uvicorn +websockets==10.1 + # via uvicorn + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/sdk/python/requirements/py3.7-ci-requirements.txt b/sdk/python/requirements/py3.7-ci-requirements.txt index 6cb8c2931b8..4ec4bde7c42 100644 --- a/sdk/python/requirements/py3.7-ci-requirements.txt +++ b/sdk/python/requirements/py3.7-ci-requirements.txt @@ -255,9 +255,9 @@ grpcio==1.44.0 # grpcio-tools grpcio-reflection==1.44.0 # via feast (setup.py) -grpcio-testing==1.34.0 +grpcio-testing==1.44.0 # via feast (setup.py) -grpcio-tools==1.34.0 +grpcio-tools==1.44.0 # via feast (setup.py) h11==0.13.0 # via uvicorn @@ -400,7 +400,7 @@ mypy==0.931 # via feast (setup.py) mypy-extensions==0.4.3 # via mypy -mypy-protobuf==3.1.0 +mypy-protobuf==3.1 # via feast (setup.py) nbclient==0.5.11 # via nbconvert @@ -420,7 +420,7 @@ nest-asyncio==1.5.4 # notebook nodeenv==1.6.0 # via pre-commit -notebook==6.4.8 +notebook==6.4.10 # via widgetsnbextension numpy==1.21.5 # via @@ -502,6 +502,8 @@ protobuf==3.19.4 # mypy-protobuf # proto-plus # tensorflow-metadata +psutil==5.9.0 + # via feast (setup.py) ptyprocess==0.7.0 # via # pexpect @@ -524,6 +526,8 @@ pyasn1==0.4.8 # rsa pyasn1-modules==0.2.8 # via google-auth +pybindgen==0.22.0 + # via feast (setup.py) pycodestyle==2.8.0 # via flake8 pycparser==2.21 @@ -850,4 +854,4 @@ zipp==3.7.0 # The following packages are considered to be unsafe in a requirements file: # pip -# setuptools \ No newline at end of file +# setuptools diff --git a/sdk/python/requirements/py3.8-ci-requirements.txt b/sdk/python/requirements/py3.8-ci-requirements.txt index f5da5525ba0..5e2da9baa7d 100644 --- a/sdk/python/requirements/py3.8-ci-requirements.txt +++ b/sdk/python/requirements/py3.8-ci-requirements.txt @@ -69,7 +69,7 @@ babel==2.9.1 # via sphinx backcall==0.2.0 # via ipython -backports.zoneinfo==0.2.1 +backports-zoneinfo==0.2.1 # via # pytz-deprecation-shim # tzlocal @@ -257,9 +257,9 @@ grpcio==1.44.0 # grpcio-tools grpcio-reflection==1.44.0 # via feast (setup.py) -grpcio-testing==1.34.0 +grpcio-testing==1.44.0 # via feast (setup.py) -grpcio-tools==1.34.0 +grpcio-tools==1.44.0 # via feast (setup.py) h11==0.13.0 # via uvicorn @@ -412,7 +412,7 @@ nest-asyncio==1.5.4 # notebook nodeenv==1.6.0 # via pre-commit -notebook==6.4.8 +notebook==6.4.10 # via widgetsnbextension numpy==1.22.2 # via @@ -494,6 +494,8 @@ protobuf==3.19.4 # mypy-protobuf # proto-plus # tensorflow-metadata +psutil==5.9.0 + # via feast (setup.py) ptyprocess==0.7.0 # via # pexpect @@ -518,6 +520,8 @@ pyasn1==0.4.8 # rsa pyasn1-modules==0.2.8 # via google-auth +pybindgen==0.22.0 + # via feast (setup.py) pycodestyle==2.8.0 # via flake8 pycparser==2.21 @@ -646,7 +650,7 @@ responses==0.18.0 # via moto rsa==4.8 # via google-auth -ruamel.yaml==0.17.17 +ruamel-yaml==0.17.17 # via great-expectations ruamel.yaml.clib==0.2.6 # via ruamel.yaml diff --git a/sdk/python/requirements/py3.8-requirements.txt b/sdk/python/requirements/py3.8-requirements.txt index 90b42760132..4b996ef075a 100644 --- a/sdk/python/requirements/py3.8-requirements.txt +++ b/sdk/python/requirements/py3.8-requirements.txt @@ -22,8 +22,12 @@ click==8.0.3 # via # feast (setup.py) # uvicorn +cloudpickle==2.0.0 + # via dask colorama==0.4.4 # via feast (setup.py) +dask==2022.1.1 + # via feast (setup.py) dill==0.3.4 # via feast (setup.py) fastapi==0.72.0 @@ -32,6 +36,8 @@ fastavro==1.4.9 # via # feast (setup.py) # pandavro +fsspec==2022.2.0 + # via dask google-api-core==2.4.0 # via feast (setup.py) google-auth==2.3.3 @@ -61,6 +67,8 @@ jinja2==3.0.3 # via feast (setup.py) jsonschema==4.4.0 # via feast (setup.py) +locket==0.2.1 + # via partd markupsafe==2.0.1 # via jinja2 mmh3==3.0.0 @@ -70,12 +78,16 @@ numpy==1.21.5 # pandas # pandavro # pyarrow +packaging==21.3 + # via dask pandas==1.3.5 # via # feast (setup.py) # pandavro pandavro==1.5.2 # via feast (setup.py) +partd==1.2.0 + # via dask proto-plus==1.19.6 # via feast (setup.py) protobuf==3.19.3 @@ -98,6 +110,8 @@ pydantic==1.9.0 # via # fastapi # feast (setup.py) +pyparsing==3.0.7 + # via packaging pyrsistent==0.18.1 # via jsonschema python-dateutil==2.8.2 @@ -108,6 +122,7 @@ pytz==2021.3 # via pandas pyyaml==6.0 # via + # dask # feast (setup.py) # uvicorn requests==2.27.1 @@ -133,6 +148,10 @@ tensorflow-metadata==1.6.0 # via feast (setup.py) toml==0.10.2 # via feast (setup.py) +toolz==0.11.2 + # via + # dask + # partd tqdm==4.62.3 # via feast (setup.py) typing-extensions==4.0.1 diff --git a/sdk/python/requirements/py3.9-ci-requirements.txt b/sdk/python/requirements/py3.9-ci-requirements.txt index 0e7d6defebd..cf228b9412b 100644 --- a/sdk/python/requirements/py3.9-ci-requirements.txt +++ b/sdk/python/requirements/py3.9-ci-requirements.txt @@ -253,9 +253,9 @@ grpcio==1.44.0 # grpcio-tools grpcio-reflection==1.44.0 # via feast (setup.py) -grpcio-testing==1.34.0 +grpcio-testing==1.44.0 # via feast (setup.py) -grpcio-tools==1.34.0 +grpcio-tools==1.44.0 # via feast (setup.py) h11==0.13.0 # via uvicorn @@ -406,7 +406,7 @@ nest-asyncio==1.5.4 # notebook nodeenv==1.6.0 # via pre-commit -notebook==6.4.8 +notebook==6.4.10 # via widgetsnbextension numpy==1.22.2 # via @@ -488,6 +488,8 @@ protobuf==3.19.4 # mypy-protobuf # proto-plus # tensorflow-metadata +psutil==5.9.0 + # via feast (setup.py) ptyprocess==0.7.0 # via # pexpect @@ -512,6 +514,8 @@ pyasn1==0.4.8 # rsa pyasn1-modules==0.2.8 # via google-auth +pybindgen==0.22.0 + # via feast (setup.py) pycodestyle==2.8.0 # via flake8 pycparser==2.21 diff --git a/sdk/python/requirements/py3.9-requirements.txt b/sdk/python/requirements/py3.9-requirements.txt index 8db9fd4b14f..67ef8ada9e0 100644 --- a/sdk/python/requirements/py3.9-requirements.txt +++ b/sdk/python/requirements/py3.9-requirements.txt @@ -22,8 +22,12 @@ click==8.0.3 # via # feast (setup.py) # uvicorn +cloudpickle==2.0.0 + # via dask colorama==0.4.4 # via feast (setup.py) +dask==2022.1.1 + # via feast (setup.py) dill==0.3.4 # via feast (setup.py) fastapi==0.72.0 @@ -32,6 +36,8 @@ fastavro==1.4.9 # via # feast (setup.py) # pandavro +fsspec==2022.2.0 + # via dask google-api-core==2.4.0 # via feast (setup.py) google-auth==2.3.3 @@ -59,6 +65,8 @@ jinja2==3.0.3 # via feast (setup.py) jsonschema==4.4.0 # via feast (setup.py) +locket==0.2.1 + # via partd markupsafe==2.0.1 # via jinja2 mmh3==3.0.0 @@ -68,12 +76,16 @@ numpy==1.21.5 # pandas # pandavro # pyarrow +packaging==21.3 + # via dask pandas==1.3.5 # via # feast (setup.py) # pandavro pandavro==1.5.2 # via feast (setup.py) +partd==1.2.0 + # via dask proto-plus==1.19.6 # via feast (setup.py) protobuf==3.19.3 @@ -96,6 +108,8 @@ pydantic==1.9.0 # via # fastapi # feast (setup.py) +pyparsing==3.0.7 + # via packaging pyrsistent==0.18.1 # via jsonschema python-dateutil==2.8.2 @@ -106,6 +120,7 @@ pytz==2021.3 # via pandas pyyaml==6.0 # via + # dask # feast (setup.py) # uvicorn requests==2.27.1 @@ -131,6 +146,10 @@ tensorflow-metadata==1.6.0 # via feast (setup.py) toml==0.10.2 # via feast (setup.py) +toolz==0.11.2 + # via + # dask + # partd tqdm==4.62.3 # via feast (setup.py) typing-extensions==4.0.1 diff --git a/sdk/python/setup.cfg b/sdk/python/setup.cfg index ae8fe14ba16..e2d707e2720 100644 --- a/sdk/python/setup.cfg +++ b/sdk/python/setup.cfg @@ -1,10 +1,11 @@ [isort] +src_paths = feast,tests multi_line_output=3 include_trailing_comma=True force_grid_wrap=0 use_parentheses=True line_length=88 -skip=feast/protos +skip=feast/protos,feast/embedded_go/lib known_first_party=feast,feast_serving_server,feast_core_server default_section=THIRDPARTY @@ -13,8 +14,9 @@ ignore = E203, E266, E501, W503 max-line-length = 88 max-complexity = 20 select = B,C,E,F,W,T4 -exclude = .git,__pycache__,docs/conf.py,dist,feast/protos +exclude = .git,__pycache__,docs/conf.py,dist,feast/protos,feast/embedded_go/lib [mypy] -files=feast,test +files=feast,tests ignore_missing_imports=true +exclude=feast/embedded_go/lib diff --git a/sdk/python/setup.py b/sdk/python/setup.py index f95dd2b806b..cc883da95e3 100644 --- a/sdk/python/setup.py +++ b/sdk/python/setup.py @@ -13,25 +13,26 @@ # limitations under the License. import glob import os +import pathlib import re import shutil import subprocess -import pathlib - from distutils.cmd import Command +from pathlib import Path +from subprocess import CalledProcessError + from setuptools import find_packages try: from setuptools import setup - from setuptools.command.install import install - from setuptools.command.develop import develop - from setuptools.command.egg_info import egg_info - from setuptools.command.sdist import sdist from setuptools.command.build_py import build_py + from setuptools.command.develop import develop + from setuptools.command.install import install + from setuptools.dist import Distribution except ImportError: - from distutils.core import setup - from distutils.command.install import install from distutils.command.build_py import build_py + from distutils.core import setup + from distutils.dist import Distribution NAME = "feast" DESCRIPTION = "Python SDK for Feast" @@ -40,7 +41,7 @@ REQUIRES_PYTHON = ">=3.7.0" REQUIRED = [ - "Click>=7.*", + "click>=7.0.0", "colorama>=0.3.9", "dill==0.3.*", "fastavro>=1.1.0", @@ -53,7 +54,7 @@ "mmh3", "pandas>=1.0.0", "pandavro==1.5.*", - "protobuf>=3.10", + "protobuf>=3.10,<3.20", "proto-plus<1.19.7", "pyarrow>=4.0.0", "pydantic>=1.0.0", @@ -96,26 +97,31 @@ "pyspark>=3.0.0", ] +TRINO_REQUIRED = [ + "trino>=0.305.0,<0.400.0", +] + GE_REQUIRED = [ "great_expectations>=0.14.0,<0.15.0" ] CI_REQUIRED = ( - [ + [ "cryptography==3.3.2", "flake8", "black==19.10b0", "isort>=5", - "grpcio-tools==1.34.0", - "grpcio-testing==1.34.0", + "grpcio-tools==1.44.0", + "grpcio-testing==1.44.0", "minio==7.1.0", "mock==2.0.0", "moto", "mypy==0.931", - "mypy-protobuf==3.1.0", + "mypy-protobuf==3.1", "avro==1.10.0", "gcsfs", "urllib3>=1.25.4", + "psutil==5.9.0", "pytest>=6.0.0", "pytest-cov", "pytest-xdist", @@ -126,12 +132,13 @@ "pytest-mock==1.10.4", "Sphinx!=4.0.0,<4.4.0", "sphinx-rtd-theme", - "testcontainers==3.4.2", + "testcontainers>=3.5", "adlfs==0.5.9", "firebase-admin==4.5.2", "pre-commit", "assertpy==1.1", "pip-tools", + "pybindgen", "types-protobuf", "types-python-dateutil", "types-pytz", @@ -146,10 +153,11 @@ + AWS_REQUIRED + SNOWFLAKE_REQUIRED + SPARK_REQUIRED + + TRINO_REQUIRED + GE_REQUIRED ) -DEV_REQUIRED = ["mypy-protobuf>=3.1.0", "grpcio-testing==1.*"] + CI_REQUIRED +DEV_REQUIRED = ["mypy-protobuf==3.1", "grpcio-testing==1.*"] + CI_REQUIRED # Get git repo root directory repo_root = str(pathlib.Path(__file__).resolve().parent.parent.parent) @@ -172,53 +180,204 @@ else: use_scm_version = None +PROTO_SUBDIRS = ["core", "serving", "types", "storage"] + -class BuildProtoCommand(Command): - description = "Builds the proto files into python files." +class BuildPythonProtosCommand(Command): + description = "Builds the proto files into Python files." + user_options = [] def initialize_options(self): - self.protoc = ["python", "-m", "grpc_tools.protoc"] # find_executable("protoc") + self.python_protoc = [ + "python", + "-m", + "grpc_tools.protoc", + ] # find_executable("protoc") self.proto_folder = os.path.join(repo_root, "protos") - self.this_package = os.path.join(os.path.dirname(__file__) or os.getcwd(), 'feast/protos') - self.sub_folders = ["core", "serving", "types", "storage"] + self.python_folder = os.path.join( + os.path.dirname(__file__) or os.getcwd(), "feast/protos" + ) + self.sub_folders = PROTO_SUBDIRS def finalize_options(self): pass - def _generate_protos(self, path): + def _generate_python_protos(self, path: str): proto_files = glob.glob(os.path.join(self.proto_folder, path)) - - subprocess.check_call(self.protoc + [ - '-I', self.proto_folder, - '--python_out', self.this_package, - '--grpc_python_out', self.this_package, - '--mypy_out', self.this_package] + proto_files) + Path(self.python_folder).mkdir(exist_ok=True) + subprocess.check_call( + self.python_protoc + + [ + "-I", + self.proto_folder, + "--python_out", + self.python_folder, + "--grpc_python_out", + self.python_folder, + "--mypy_out", + self.python_folder, + ] + + proto_files, + ) def run(self): for sub_folder in self.sub_folders: - self._generate_protos(f'feast/{sub_folder}/*.proto') - - from pathlib import Path - - for path in Path('feast/protos').rglob('*.py'): + self._generate_python_protos(f"feast/{sub_folder}/*.proto") + # We need the __init__ files for each of the generated subdirs + # so that they are regular packages, and don't need the `--namespace-packages` flags + # when being typechecked using mypy. BUT, we need to exclude `types` because that clashes + # with an existing module in the python standard library. + if sub_folder == "types": + continue + with open(f"{self.python_folder}/feast/{sub_folder}/__init__.py", 'w'): + pass + + with open(f"{self.python_folder}/__init__.py", 'w'): + pass + with open(f"{self.python_folder}/feast/__init__.py", 'w'): + pass + + for path in Path("feast/protos").rglob("*.py"): for folder in self.sub_folders: # Read in the file - with open(path, 'r') as file: + with open(path, "r") as file: filedata = file.read() # Replace the target string - filedata = filedata.replace(f'from feast.{folder}', f'from feast.protos.feast.{folder}') + filedata = filedata.replace( + f"from feast.{folder}", f"from feast.protos.feast.{folder}" + ) # Write the file out again - with open(path, 'w') as file: + with open(path, "w") as file: file.write(filedata) +def _generate_path_with_gopath(): + go_path = subprocess.check_output(["go", "env", "GOPATH"]).decode("utf-8") + go_path = go_path.strip() + path_val = os.getenv("PATH") + path_val = f"{path_val}:{go_path}/bin" + + return path_val + + +def _ensure_go_and_proto_toolchain(): + try: + version = subprocess.check_output(["go", "version"]) + except Exception as e: + raise RuntimeError("Unable to find go toolchain") from e + + semver_string = re.search(r"go[\S]+", str(version)).group().lstrip("go") + parts = semver_string.split(".") + if not (int(parts[0]) >= 1 and int(parts[1]) >= 16): + raise RuntimeError(f"Go compiler too old; expected 1.16+ found {semver_string}") + + path_val = _generate_path_with_gopath() + + try: + subprocess.check_call(["protoc-gen-go", "--version"], env={ + "PATH": path_val + }) + subprocess.check_call(["protoc-gen-go-grpc", "--version"], env={ + "PATH": path_val + }) + except Exception as e: + raise RuntimeError("Unable to find go/grpc extensions for protoc") from e + + +class BuildGoProtosCommand(Command): + description = "Builds the proto files into Go files." + user_options = [] + + def initialize_options(self): + self.go_protoc = [ + "python", + "-m", + "grpc_tools.protoc", + ] # find_executable("protoc") + self.proto_folder = os.path.join(repo_root, "protos") + self.go_folder = os.path.join(repo_root, "go/protos") + self.sub_folders = PROTO_SUBDIRS + self.path_val = _generate_path_with_gopath() + + def finalize_options(self): + pass + + def _generate_go_protos(self, path: str): + proto_files = glob.glob(os.path.join(self.proto_folder, path)) + + try: + subprocess.check_call( + self.go_protoc + + ["-I", self.proto_folder, + "--go_out", self.go_folder, + "--go_opt=module=github.com/feast-dev/feast/go/protos", + "--go-grpc_out", self.go_folder, + "--go-grpc_opt=module=github.com/feast-dev/feast/go/protos"] + + proto_files, + env={ + "PATH": self.path_val + } + ) + except CalledProcessError as e: + print(f"Stderr: {e.stderr}") + print(f"Stdout: {e.stdout}") + + def run(self): + go_dir = Path(repo_root) / "go" / "protos" + go_dir.mkdir(exist_ok=True) + for sub_folder in self.sub_folders: + self._generate_go_protos(f"feast/{sub_folder}/*.proto") + + +class BuildGoEmbeddedCommand(Command): + description = "Builds Go embedded library" + user_options = [] + + def initialize_options(self) -> None: + self.path_val = _generate_path_with_gopath() + + self.go_env = {} + for var in ("GOCACHE", "GOPATH"): + self.go_env[var] = subprocess \ + .check_output(["go", "env", var]) \ + .decode("utf-8") \ + .strip() + + def finalize_options(self) -> None: + pass + + def _compile_embedded_lib(self): + print("Compile embedded go") + subprocess.check_call([ + "gopy", + "build", + "-output", + "feast/embedded_go/lib", + "-vm", + "python3", + "-no-make", + "github.com/feast-dev/feast/go/embedded" + ], env={ + "PATH": self.path_val, + "CGO_LDFLAGS_ALLOW": ".*", + **self.go_env, + }) + + def run(self): + self._compile_embedded_lib() + + class BuildCommand(build_py): """Custom build command.""" def run(self): - self.run_command('build_proto') + self.run_command("build_python_protos") + if os.getenv("COMPILE_GO", "false").lower() == "true": + _ensure_go_and_proto_toolchain() + self.run_command("build_go_protos") + self.run_command("build_go_lib") build_py.run(self) @@ -226,10 +385,21 @@ class DevelopCommand(develop): """Custom develop command.""" def run(self): - self.run_command('build_proto') + self.run_command("build_python_protos") + if os.getenv("COMPILE_GO", "false").lower() == "true": + _ensure_go_and_proto_toolchain() + self.run_command("build_go_protos") + self.run_command("build_go_lib") develop.run(self) +class BinaryDistribution(Distribution): + """Distribution which forces a binary package with platform name + when go compilation is enabled""" + def has_ext_modules(self): + return os.getenv("COMPILE_GO", "false").lower() == "true" + + setup( name=NAME, author=AUTHOR, @@ -250,6 +420,7 @@ def run(self): "redis": REDIS_REQUIRED, "snowflake": SNOWFLAKE_REQUIRED, "spark": SPARK_REQUIRED, + "trino": TRINO_REQUIRED, "ge": GE_REQUIRED, }, include_package_data=True, @@ -264,7 +435,13 @@ def run(self): ], entry_points={"console_scripts": ["feast=feast.cli:cli"]}, use_scm_version=use_scm_version, - setup_requires=["setuptools_scm", "grpcio", "grpcio-tools==1.34.0", "mypy-protobuf==3.1.0", "sphinx!=4.0.0"], + setup_requires=[ + "setuptools_scm", + "grpcio", + "grpcio-tools==1.44.0", + "mypy-protobuf==3.1", + "sphinx!=4.0.0", + ], package_data={ "": [ "protos/feast/**/*.proto", @@ -273,8 +450,11 @@ def run(self): ], }, cmdclass={ - "build_proto": BuildProtoCommand, + "build_python_protos": BuildPythonProtosCommand, + "build_go_protos": BuildGoProtosCommand, + "build_go_lib": BuildGoEmbeddedCommand, "build_py": BuildCommand, "develop": DevelopCommand, }, + distclass=BinaryDistribution, # generate wheel with platform-specific name ) diff --git a/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py b/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py index 3d2a253dc0e..a29383a5c9c 100644 --- a/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py +++ b/sdk/python/tests/benchmarks/test_benchmark_universal_online_retrieval.py @@ -38,7 +38,7 @@ def test_online_retrieval(environment, universal_data_sources, benchmark): sample_customers = random.sample(entities.customer_vals, 10) entity_rows = [ - {"driver": d, "customer_id": c, "val_to_add": 50} + {"driver_id": d, "customer_id": c, "val_to_add": 50} for (d, c) in zip(sample_drivers, sample_customers) ] diff --git a/sdk/python/tests/conftest.py b/sdk/python/tests/conftest.py index 9de146ac12a..c72a3af7543 100644 --- a/sdk/python/tests/conftest.py +++ b/sdk/python/tests/conftest.py @@ -13,6 +13,7 @@ # limitations under the License. import logging import multiprocessing +import pathlib import time from datetime import datetime, timedelta from multiprocessing import Process @@ -22,6 +23,8 @@ import pandas as pd import pytest from _pytest.nodes import Item +from testcontainers.core.container import DockerContainer +from testcontainers.core.waiting_utils import wait_for_logs from feast import FeatureStore from tests.data.data_creator import create_dataset @@ -53,6 +56,9 @@ def pytest_configure(config): config.addinivalue_line( "markers", "universal: mark tests that use the universal feature repo" ) + config.addinivalue_line( + "markers", "goserver: mark tests that use the go feature server" + ) def pytest_addoption(parser): @@ -68,12 +74,19 @@ def pytest_addoption(parser): parser.addoption( "--universal", action="store_true", default=False, help="Run universal tests", ) + parser.addoption( + "--goserver", + action="store_true", + default=False, + help="Run tests that use the go feature server", + ) def pytest_collection_modifyitems(config, items: List[Item]): should_run_integration = config.getoption("--integration") is True should_run_benchmark = config.getoption("--benchmark") is True should_run_universal = config.getoption("--universal") is True + should_run_goserver = config.getoption("--goserver") is True integration_tests = [t for t in items if "integration" in t.keywords] if not should_run_integration: @@ -99,6 +112,12 @@ def pytest_collection_modifyitems(config, items: List[Item]): for t in universal_tests: items.append(t) + goserver_tests = [t for t in items if "goserver" in t.keywords] + if should_run_goserver: + items.clear() + for t in goserver_tests: + items.append(t) + @pytest.fixture def simple_dataset_1() -> pd.DataFrame: @@ -145,11 +164,49 @@ def start_test_local_server(repo_path: str, port: int): fs.serve("localhost", port, no_access_log=True) +class TrinoContainerSingleton: + current_file = pathlib.Path(__file__).resolve() + catalog_dir = current_file.parent.joinpath( + "integration/feature_repos/universal/data_sources/catalog" + ) + container = None + is_running = False + + @classmethod + def get_singleton(cls): + if not cls.is_running: + cls.container = ( + DockerContainer("trinodb/trino:376") + .with_volume_mapping(cls.catalog_dir, "/etc/catalog/") + .with_exposed_ports("8080") + ) + + cls.container.start() + log_string_to_wait_for = "SERVER STARTED" + wait_for_logs( + container=cls.container, predicate=log_string_to_wait_for, timeout=30 + ) + cls.is_running = True + return cls.container + + @classmethod + def teardown(cls): + if cls.container: + cls.container.stop() + + @pytest.fixture( params=FULL_REPO_CONFIGS, scope="session", ids=[str(c) for c in FULL_REPO_CONFIGS] ) def environment(request, worker_id: str): - e = construct_test_environment(request.param, worker_id=worker_id) + if "TrinoSourceCreator" in request.param.offline_store_creator.__name__: + e = construct_test_environment( + request.param, + worker_id=worker_id, + offline_container=TrinoContainerSingleton.get_singleton(), + ) + else: + e = construct_test_environment(request.param, worker_id=worker_id) proc = Process( target=start_test_local_server, args=(e.feature_store.repo_path, e.get_local_server_port()), @@ -164,6 +221,8 @@ def cleanup(): e.feature_store.teardown() if proc.is_alive(): proc.kill() + if e.online_store_creator: + e.online_store_creator.teardown() request.addfinalizer(cleanup) @@ -216,6 +275,8 @@ def e2e_data_sources(environment: Environment, request): def cleanup(): environment.data_source_creator.teardown() + if environment.online_store_creator: + environment.online_store_creator.teardown() request.addfinalizer(cleanup) diff --git a/sdk/python/tests/doctest/test_all.py b/sdk/python/tests/doctest/test_all.py index bf3a09db1e2..65d5f3da289 100644 --- a/sdk/python/tests/doctest/test_all.py +++ b/sdk/python/tests/doctest/test_all.py @@ -11,8 +11,9 @@ def setup_feature_store(): """Prepares the local environment for a FeatureStore docstring test.""" from datetime import datetime, timedelta - from feast import Entity, Feature, FeatureStore, FeatureView, FileSource, ValueType + from feast import Entity, FeatureStore, FeatureView, Field, FileSource, ValueType from feast.repo_operations import init_repo + from feast.types import Float32, Int64 init_repo("feature_repo", "local") fs = FeatureStore(repo_path="feature_repo") @@ -21,17 +22,17 @@ def setup_feature_store(): ) driver_hourly_stats = FileSource( path="feature_repo/data/driver_stats.parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", entities=["driver_id"], ttl=timedelta(seconds=86400 * 1), - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], batch_source=driver_hourly_stats, ) diff --git a/sdk/python/tests/example_repos/example_feature_repo_1.py b/sdk/python/tests/example_repos/example_feature_repo_1.py index 8179906fa45..76b42b22416 100644 --- a/sdk/python/tests/example_repos/example_feature_repo_1.py +++ b/sdk/python/tests/example_repos/example_feature_repo_1.py @@ -3,37 +3,63 @@ from feast import ( BigQuerySource, Entity, - Feature, FeatureService, FeatureView, + Field, + PushSource, ValueType, ) +from feast.types import Float32, Int64, String driver_locations_source = BigQuerySource( table="feast-oss.public.drivers", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", + created_timestamp_column="created_timestamp", +) + +driver_locations_source_query = BigQuerySource( + query="SELECT * from feast-oss.public.drivers", + timestamp_field="event_timestamp", + created_timestamp_column="created_timestamp", +) + +driver_locations_source_query_2 = BigQuerySource( + query="SELECT lat * 2 FROM feast-oss.public.drivers", + timestamp_field="event_timestamp", created_timestamp_column="created_timestamp", ) customer_profile_source = BigQuerySource( name="customer_profile_source", - table_ref="feast-oss.public.customers", - event_timestamp_column="event_timestamp", + table="feast-oss.public.customers", + timestamp_field="event_timestamp", ) customer_driver_combined_source = BigQuerySource( - table_ref="feast-oss.public.customer_driver", - event_timestamp_column="event_timestamp", + table="feast-oss.public.customer_driver", timestamp_field="event_timestamp", +) + +driver_locations_push_source = PushSource( + name="driver_locations_push", + schema=[ + Field(name="driver_id", dtype=String), + Field(name="driver_lat", dtype=Float32), + Field(name="driver_long", dtype=String), + ], + batch_source=driver_locations_source, + timestamp_field="event_timestamp", ) driver = Entity( name="driver", # The name is derived from this argument, not object name. + join_key="driver_id", value_type=ValueType.INT64, description="driver id", ) customer = Entity( name="customer", # The name is derived from this argument, not object name. + join_key="customer_id", value_type=ValueType.STRING, ) @@ -42,23 +68,33 @@ name="driver_locations", entities=["driver"], ttl=timedelta(days=1), - features=[ - Feature(name="lat", dtype=ValueType.FLOAT), - Feature(name="lon", dtype=ValueType.STRING), - ], + schema=[Field(name="lat", dtype=Float32), Field(name="lon", dtype=String)], online=True, batch_source=driver_locations_source, tags={}, ) +pushed_driver_locations = FeatureView( + name="pushed_driver_locations", + entities=["driver"], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_lat", dtype=Float32), + Field(name="driver_long", dtype=String), + ], + online=True, + stream_source=driver_locations_push_source, + tags={}, +) + customer_profile = FeatureView( name="customer_profile", entities=["customer"], ttl=timedelta(days=1), - features=[ - Feature(name="avg_orders_day", dtype=ValueType.FLOAT), - Feature(name="name", dtype=ValueType.STRING), - Feature(name="age", dtype=ValueType.INT64), + schema=[ + Field(name="avg_orders_day", dtype=Float32), + Field(name="name", dtype=String), + Field(name="age", dtype=Int64), ], online=True, batch_source=customer_profile_source, @@ -69,7 +105,7 @@ name="customer_driver_combined", entities=["customer", "driver"], ttl=timedelta(days=1), - features=[Feature(name="trips", dtype=ValueType.INT64)], + schema=[Field(name="trips", dtype=Int64)], online=True, batch_source=customer_driver_combined_source, tags={}, diff --git a/sdk/python/tests/example_repos/example_feature_repo_2.py b/sdk/python/tests/example_repos/example_feature_repo_2.py index 96da67ac92d..1ca7cc3805c 100644 --- a/sdk/python/tests/example_repos/example_feature_repo_2.py +++ b/sdk/python/tests/example_repos/example_feature_repo_2.py @@ -1,10 +1,11 @@ from datetime import timedelta -from feast import Entity, Feature, FeatureView, FileSource, ValueType +from feast import Entity, FeatureView, Field, FileSource, ValueType +from feast.types import Float32, Int32, Int64 driver_hourly_stats = FileSource( path="%PARQUET_PATH%", # placeholder to be replaced by the test - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) @@ -15,10 +16,10 @@ name="driver_hourly_stats", entities=["driver_id"], ttl=timedelta(days=1), - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], online=True, batch_source=driver_hourly_stats, @@ -28,7 +29,7 @@ global_daily_stats = FileSource( path="%PARQUET_PATH_GLOBAL%", # placeholder to be replaced by the test - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) @@ -37,9 +38,9 @@ name="global_daily_stats", entities=[], ttl=timedelta(days=1), - features=[ - Feature(name="num_rides", dtype=ValueType.INT32), - Feature(name="avg_ride_length", dtype=ValueType.FLOAT), + schema=[ + Field(name="num_rides", dtype=Int32), + Field(name="avg_ride_length", dtype=Float32), ], online=True, batch_source=global_daily_stats, diff --git a/sdk/python/tests/example_repos/example_feature_repo_with_duplicated_featureview_names.py b/sdk/python/tests/example_repos/example_feature_repo_with_duplicated_featureview_names.py index 84d57bf0381..20ff666bd9c 100644 --- a/sdk/python/tests/example_repos/example_feature_repo_with_duplicated_featureview_names.py +++ b/sdk/python/tests/example_repos/example_feature_repo_with_duplicated_featureview_names.py @@ -1,4 +1,4 @@ -from google.protobuf.duration_pb2 import Duration +from datetime import timedelta from feast import FeatureView, FileSource @@ -11,7 +11,7 @@ entities=["driver_id"], online=False, batch_source=driver_hourly_stats, - ttl=Duration(seconds=10), + ttl=timedelta(days=1), tags={}, ) @@ -20,6 +20,6 @@ entities=["driver_id"], online=False, batch_source=driver_hourly_stats, - ttl=Duration(seconds=10), + ttl=timedelta(days=1), tags={}, ) diff --git a/sdk/python/tests/example_repos/example_feature_repo_with_entity_join_key.py b/sdk/python/tests/example_repos/example_feature_repo_with_entity_join_key.py index f89df1404c3..3e1bbbba779 100644 --- a/sdk/python/tests/example_repos/example_feature_repo_with_entity_join_key.py +++ b/sdk/python/tests/example_repos/example_feature_repo_with_entity_join_key.py @@ -1,10 +1,11 @@ -from google.protobuf.duration_pb2 import Duration +from datetime import timedelta -from feast import Entity, Feature, FeatureView, FileSource, ValueType +from feast import Entity, FeatureView, Field, FileSource, ValueType +from feast.types import Float32, Int64 driver_hourly_stats = FileSource( path="%PARQUET_PATH%", # placeholder to be replaced by the test - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) @@ -21,11 +22,11 @@ driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", entities=["driver_id"], - ttl=Duration(seconds=86400 * 1), - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT64), + ttl=timedelta(days=1), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), ], online=True, batch_source=driver_hourly_stats, diff --git a/sdk/python/tests/example_repos/example_feature_repo_with_inference.py b/sdk/python/tests/example_repos/example_feature_repo_with_inference.py deleted file mode 100644 index f2be472f550..00000000000 --- a/sdk/python/tests/example_repos/example_feature_repo_with_inference.py +++ /dev/null @@ -1,20 +0,0 @@ -from google.protobuf.duration_pb2 import Duration - -from feast import Entity, FeatureView, FileSource - -driver_hourly_stats = FileSource( - path="%PARQUET_PATH%", # placeholder to be replaced by the test - created_timestamp_column="created", -) - -driver = Entity(name="driver_id", description="driver id",) - -# features are inferred from columns of data source -driver_hourly_stats_view = FeatureView( - name="driver_hourly_stats", - entities=["driver_id"], - ttl=Duration(seconds=86400 * 1), - online=True, - batch_source=driver_hourly_stats, - tags={}, -) diff --git a/sdk/python/tests/example_repos/example_feature_repo_with_missing_bq_source.py b/sdk/python/tests/example_repos/example_feature_repo_with_missing_bq_source.py deleted file mode 100644 index 46efe5b2756..00000000000 --- a/sdk/python/tests/example_repos/example_feature_repo_with_missing_bq_source.py +++ /dev/null @@ -1,20 +0,0 @@ -from datetime import timedelta - -from feast import BigQuerySource, Entity, Feature, FeatureView, ValueType - -nonexistent_source = BigQuerySource( - table_ref="project.dataset.nonexistent_table", event_timestamp_column="" -) - -driver = Entity(name="driver", value_type=ValueType.INT64, description="driver id",) - -nonexistent_features = FeatureView( - name="driver_locations", - entities=["driver"], - ttl=timedelta(days=1), - features=[ - Feature(name="lat", dtype=ValueType.FLOAT), - Feature(name="lon", dtype=ValueType.STRING), - ], - batch_source=nonexistent_source, -) diff --git a/sdk/python/tests/integration/e2e/test_universal_e2e.py b/sdk/python/tests/integration/e2e/test_universal_e2e.py index 477c79614c5..957cf9fba6f 100644 --- a/sdk/python/tests/integration/e2e/test_universal_e2e.py +++ b/sdk/python/tests/integration/e2e/test_universal_e2e.py @@ -45,7 +45,7 @@ def check_offline_and_online_features( # Check online store response_dict = fs.get_online_features( [f"{fv.name}:value"], - [{"driver": driver_id}], + [{"driver_id": driver_id}], full_feature_names=full_feature_names, ).to_dict() diff --git a/sdk/python/tests/integration/e2e/test_usage_e2e.py b/sdk/python/tests/integration/e2e/test_usage_e2e.py index c7b62b3a5da..12c1eb86281 100644 --- a/sdk/python/tests/integration/e2e/test_usage_e2e.py +++ b/sdk/python/tests/integration/e2e/test_usage_e2e.py @@ -136,7 +136,7 @@ def test_exception_usage_off(dummy_exporter, enabling_toggle): def _reload_feast(): - """ After changing environment need to reload modules and rerun usage decorators """ + """After changing environment need to reload modules and rerun usage decorators""" modules = ( "feast.infra.local", "feast.infra.online_stores.sqlite", diff --git a/sdk/python/tests/integration/e2e/test_validation.py b/sdk/python/tests/integration/e2e/test_validation.py index 77706b74d10..76bbe152c57 100644 --- a/sdk/python/tests/integration/e2e/test_validation.py +++ b/sdk/python/tests/integration/e2e/test_validation.py @@ -61,34 +61,30 @@ def profiler_with_unrealistic_expectations(dataset: PandasDataset) -> Expectatio @pytest.mark.universal def test_historical_retrieval_with_validation(environment, universal_data_sources): store = environment.feature_store - (entities, datasets, data_sources) = universal_data_sources feature_views = construct_universal_feature_views(data_sources) - store.apply([driver(), customer(), location(), *feature_views.values()]) + # Create two identical retrieval jobs entity_df = datasets.entity_df.drop( columns=["order_id", "origin_id", "destination_id"] ) - reference_job = store.get_historical_features( entity_df=entity_df, features=_features, ) + job = store.get_historical_features(entity_df=entity_df, features=_features,) + # Save dataset using reference job and retrieve it store.create_saved_dataset( from_=reference_job, name="my_training_dataset", storage=environment.data_source_creator.create_saved_dataset_destination(), ) + saved_dataset = store.get_saved_dataset("my_training_dataset") - job = store.get_historical_features(entity_df=entity_df, features=_features,) - - # if validation pass there will be no exceptions on this point - job.to_df( - validation_reference=store.get_saved_dataset( - "my_training_dataset" - ).as_reference(profiler=configurable_profiler) - ) + # If validation pass there will be no exceptions on this point + reference = saved_dataset.as_reference(profiler=configurable_profiler) + job.to_df(validation_reference=reference) @pytest.mark.integration diff --git a/sdk/python/tests/integration/feature_repos/integration_test_repo_config.py b/sdk/python/tests/integration/feature_repos/integration_test_repo_config.py index e4ff6677648..f8cd66a6196 100644 --- a/sdk/python/tests/integration/feature_repos/integration_test_repo_config.py +++ b/sdk/python/tests/integration/feature_repos/integration_test_repo_config.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from typing import Dict, Type, Union +from typing import Dict, Optional, Type, Union from tests.integration.feature_repos.universal.data_source_creator import ( DataSourceCreator, @@ -7,9 +7,12 @@ from tests.integration.feature_repos.universal.data_sources.file import ( FileDataSourceCreator, ) +from tests.integration.feature_repos.universal.online_store_creator import ( + OnlineStoreCreator, +) -@dataclass(frozen=True) +@dataclass(frozen=False) class IntegrationTestRepoConfig: """ This class should hold all possible parameters that may need to be varied by individual tests. @@ -19,18 +22,31 @@ class IntegrationTestRepoConfig: online_store: Union[str, Dict] = "sqlite" offline_store_creator: Type[DataSourceCreator] = FileDataSourceCreator + online_store_creator: Optional[Type[OnlineStoreCreator]] = None full_feature_names: bool = True infer_features: bool = False python_feature_server: bool = False + go_feature_retrieval: bool = False def __repr__(self) -> str: - return "-".join( + if not self.online_store_creator: + if isinstance(self.online_store, str): + online_store_type = self.online_store + elif isinstance(self.online_store, dict): + if self.online_store["type"] == "redis": + online_store_type = self.online_store.get("redis_type", "redis") + else: + online_store_type = self.online_store["type"] + else: + online_store_type = self.online_store.__name__ + else: + online_store_type = self.online_store_creator.__name__ + + return ":".join( [ - f"Provider: {self.provider}", - f"{self.offline_store_creator.__name__.split('.')[-1].rstrip('DataSourceCreator')}", - self.online_store - if isinstance(self.online_store, str) - else self.online_store["type"], + f"{self.provider.upper()}", + f"{self.offline_store_creator.__name__.split('.')[-1].replace('DataSourceCreator', '')}", + online_store_type, ] ) diff --git a/sdk/python/tests/integration/feature_repos/repo_configuration.py b/sdk/python/tests/integration/feature_repos/repo_configuration.py index 89aea727a6e..9902f7c7b8e 100644 --- a/sdk/python/tests/integration/feature_repos/repo_configuration.py +++ b/sdk/python/tests/integration/feature_repos/repo_configuration.py @@ -12,6 +12,7 @@ import pandas as pd import yaml +from testcontainers.core.container import DockerContainer from feast import FeatureStore, FeatureView, OnDemandFeatureView, driver_test_data from feast.constants import FULL_REPO_CONFIGS_MODULE_ENV_NAME @@ -35,19 +36,32 @@ ) from tests.integration.feature_repos.universal.feature_views import ( conv_rate_plus_100_feature_view, - create_conv_rate_request_data_source, + create_conv_rate_request_source, create_customer_daily_profile_feature_view, - create_driver_age_request_feature_view, create_driver_hourly_stats_feature_view, create_field_mapping_feature_view, create_global_stats_feature_view, create_location_stats_feature_view, create_order_feature_view, + create_pushable_feature_view, +) +from tests.integration.feature_repos.universal.online_store.datastore import ( + DatastoreOnlineStoreCreator, +) +from tests.integration.feature_repos.universal.online_store.dynamodb import ( + DynamoDBOnlineStoreCreator, +) +from tests.integration.feature_repos.universal.online_store.redis import ( + RedisOnlineStoreCreator, +) +from tests.integration.feature_repos.universal.online_store_creator import ( + OnlineStoreCreator, ) DYNAMO_CONFIG = {"type": "dynamodb", "region": "us-west-2"} -# Port 12345 will chosen as default for redis node configuration because Redis Cluster is started off of nodes 6379 -> 6384. This causes conflicts in cli integration tests so we manually keep them separate. -REDIS_CONFIG = {"type": "redis", "connection_string": "localhost:12345,db=0"} +# Port 12345 will chosen as default for redis node configuration because Redis Cluster is started off of nodes +# 6379 -> 6384. This causes conflicts in cli integration tests so we manually keep them separate. +REDIS_CONFIG = {"type": "redis", "connection_string": "localhost:6379,db=0"} REDIS_CLUSTER_CONFIG = { "type": "redis", "redis_type": "redis_cluster", @@ -70,9 +84,7 @@ if os.getenv("FEAST_IS_LOCAL_TEST", "False") != "True": DEFAULT_FULL_REPO_CONFIGS.extend( [ - # Redis configurations IntegrationTestRepoConfig(online_store=REDIS_CONFIG), - IntegrationTestRepoConfig(online_store=REDIS_CLUSTER_CONFIG), # GCP configurations IntegrationTestRepoConfig( provider="gcp", @@ -102,8 +114,24 @@ offline_store_creator=SnowflakeDataSourceCreator, online_store=REDIS_CONFIG, ), + # Go implementation for online retrieval + IntegrationTestRepoConfig( + online_store=REDIS_CONFIG, go_feature_retrieval=True, + ), + # TODO(felixwang9817): Enable this test once https://github.com/feast-dev/feast/issues/2544 is resolved. + # IntegrationTestRepoConfig( + # online_store=REDIS_CONFIG, + # python_feature_server=True, + # go_feature_retrieval=True, + # ), ] ) +if os.getenv("FEAST_GO_FEATURE_RETRIEVAL", "False") == "True": + DEFAULT_FULL_REPO_CONFIGS = [ + IntegrationTestRepoConfig( + online_store=REDIS_CONFIG, go_feature_retrieval=True, + ), + ] full_repo_configs_module = os.environ.get(FULL_REPO_CONFIGS_MODULE_ENV_NAME) if full_repo_configs_module is not None: try: @@ -116,6 +144,20 @@ else: FULL_REPO_CONFIGS = DEFAULT_FULL_REPO_CONFIGS +if os.getenv("FEAST_LOCAL_ONLINE_CONTAINER", "False").lower() == "true": + replacements = {"datastore": DatastoreOnlineStoreCreator} + replacement_dicts = [ + (REDIS_CONFIG, RedisOnlineStoreCreator), + (DYNAMO_CONFIG, DynamoDBOnlineStoreCreator), + ] + for c in FULL_REPO_CONFIGS: + if isinstance(c.online_store, dict): + for _replacement in replacement_dicts: + if c.online_store == _replacement[0]: + c.online_store_creator = _replacement[1] + elif c.online_store in replacements: + c.online_store_creator = replacements[c.online_store] + @dataclass class UniversalEntities: @@ -196,6 +238,9 @@ class UniversalDataSources: global_ds: DataSource field_mapping: DataSource + def values(self): + return dataclasses.asdict(self).values() + def construct_universal_data_sources( datasets: UniversalDatasets, data_source_creator: DataSourceCreator @@ -203,37 +248,37 @@ def construct_universal_data_sources( customer_ds = data_source_creator.create_data_source( datasets.customer_df, destination_name="customer_profile", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) driver_ds = data_source_creator.create_data_source( datasets.driver_df, destination_name="driver_hourly", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) location_ds = data_source_creator.create_data_source( datasets.location_df, destination_name="location_hourly", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) orders_ds = data_source_creator.create_data_source( datasets.orders_df, destination_name="orders", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column=None, ) global_ds = data_source_creator.create_data_source( datasets.global_df, destination_name="global", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) field_mapping_ds = data_source_creator.create_data_source( datasets.field_mapping_df, destination_name="field_mapping", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", field_mapping={"column_name": "feature_name"}, ) @@ -253,17 +298,17 @@ class UniversalFeatureViews: global_fv: FeatureView driver: FeatureView driver_odfv: OnDemandFeatureView - driver_age_request_fv: FeatureView order: FeatureView location: FeatureView field_mapping: FeatureView + pushed_locations: FeatureView def values(self): return dataclasses.asdict(self).values() def construct_universal_feature_views( - data_sources: UniversalDataSources, + data_sources: UniversalDataSources, with_odfv: bool = True, ) -> UniversalFeatureViews: driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) return UniversalFeatureViews( @@ -273,13 +318,15 @@ def construct_universal_feature_views( driver_odfv=conv_rate_plus_100_feature_view( { "driver": driver_hourly_stats, - "input_request": create_conv_rate_request_data_source(), + "input_request": create_conv_rate_request_source(), } - ), - driver_age_request_fv=create_driver_age_request_feature_view(), + ) + if with_odfv + else None, order=create_order_feature_view(data_sources.orders), location=create_location_stats_feature_view(data_sources.location), field_mapping=create_field_mapping_feature_view(data_sources.field_mapping), + pushed_locations=create_pushable_feature_view(data_sources.location), ) @@ -291,6 +338,7 @@ class Environment: data_source_creator: DataSourceCreator python_feature_server: bool worker_id: str + online_store_creator: Optional[OnlineStoreCreator] = None def __post_init__(self): self.end_date = datetime.utcnow().replace(microsecond=0, second=0, minute=0) @@ -323,6 +371,7 @@ def construct_test_environment( test_repo_config: IntegrationTestRepoConfig, test_suite_name: str = "integration_test", worker_id: str = "worker_id", + offline_container: Optional[DockerContainer] = None, ) -> Environment: _uuid = str(uuid.uuid4()).replace("-", "")[:6] @@ -332,10 +381,19 @@ def construct_test_environment( project = f"{test_suite_name}_{run_id}_{run_num}" - offline_creator: DataSourceCreator = test_repo_config.offline_store_creator(project) - + offline_creator: DataSourceCreator = test_repo_config.offline_store_creator( + project, offline_container=offline_container + ) offline_store_config = offline_creator.create_offline_store_config() - online_store = test_repo_config.online_store + + if test_repo_config.online_store_creator: + online_creator = test_repo_config.online_store_creator(project) + online_store = ( + test_repo_config.online_store + ) = online_creator.create_online_store() + else: + online_creator = None + online_store = test_repo_config.online_store repo_dir_name = tempfile.mkdtemp() @@ -358,7 +416,6 @@ def construct_test_environment( registry = RegistryConfig( path=str(Path(repo_dir_name) / "registry.db"), cache_ttl_seconds=1, ) - config = RepoConfig( registry=registry, project=project, @@ -367,6 +424,7 @@ def construct_test_environment( online_store=online_store, repo_path=repo_dir_name, feature_server=feature_server, + go_feature_retrieval=test_repo_config.go_feature_retrieval, ) # Create feature_store.yaml out of the config @@ -384,6 +442,7 @@ def construct_test_environment( data_source_creator=offline_creator, python_feature_server=test_repo_config.python_feature_server, worker_id=worker_id, + online_store_creator=online_creator, ) return environment diff --git a/sdk/python/tests/integration/feature_repos/universal/data_source_creator.py b/sdk/python/tests/integration/feature_repos/universal/data_source_creator.py index dcefa29df1e..e2a700d0677 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_source_creator.py +++ b/sdk/python/tests/integration/feature_repos/universal/data_source_creator.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Dict +from typing import Dict, Optional import pandas as pd @@ -9,6 +9,9 @@ class DataSourceCreator(ABC): + def __init__(self, project_name: str, *args, **kwargs): + self.project_name = project_name + @abstractmethod def create_data_source( self, @@ -17,6 +20,7 @@ def create_data_source( event_timestamp_column="ts", created_timestamp_column="created_ts", field_mapping: Dict[str, str] = None, + timestamp_field: Optional[str] = None, ) -> DataSource: """ Create a data source based on the dataframe. Implementing this method requires the underlying implementation to @@ -27,9 +31,11 @@ def create_data_source( df: The dataframe to be used to create the data source. destination_name: This str is used by the implementing classes to isolate the multiple dataframes from each other. - event_timestamp_column: Pass through for the underlying data source. + event_timestamp_column: (Deprecated) Pass through for the underlying data source. created_timestamp_column: Pass through for the underlying data source. field_mapping: Pass through for the underlying data source. + timestamp_field: (Deprecated) Pass through for the underlying data source. + Returns: A Data source object, pointing to a table or file that is uploaded/persisted for the purpose of the diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/bigquery.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/bigquery.py index e0ac2050ea5..881f547617e 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/bigquery.py +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/bigquery.py @@ -17,9 +17,9 @@ class BigQueryDataSourceCreator(DataSourceCreator): dataset: Optional[Dataset] = None - def __init__(self, project_name: str): + def __init__(self, project_name: str, *args, **kwargs): + super().__init__(project_name) self.client = bigquery.Client() - self.project_name = project_name self.gcp_project = self.client.project self.dataset_id = f"{self.gcp_project}.{project_name}" @@ -53,7 +53,7 @@ def create_data_source( self, df: pd.DataFrame, destination_name: str, - event_timestamp_column="ts", + timestamp_field="ts", created_timestamp_column="created_ts", field_mapping: Dict[str, str] = None, **kwargs, @@ -74,10 +74,9 @@ def create_data_source( self.tables.append(destination_name) return BigQuerySource( - table_ref=destination_name, - event_timestamp_column=event_timestamp_column, + table=destination_name, + timestamp_field=timestamp_field, created_timestamp_column=created_timestamp_column, - date_partition_column="", field_mapping=field_mapping or {"ts_1": "ts"}, ) @@ -85,7 +84,7 @@ def create_saved_dataset_destination(self) -> SavedDatasetBigQueryStorage: table = self.get_prefixed_table_name( f"persisted_{str(uuid.uuid4()).replace('-', '_')}" ) - return SavedDatasetBigQueryStorage(table_ref=table) + return SavedDatasetBigQueryStorage(table=table) def get_prefixed_table_name(self, suffix: str) -> str: return f"{self.client.project}.{self.project_name}.{suffix}" diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/catalog/memory.properties b/sdk/python/tests/integration/feature_repos/universal/data_sources/catalog/memory.properties new file mode 100644 index 00000000000..6a291def3c3 --- /dev/null +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/catalog/memory.properties @@ -0,0 +1,2 @@ +connector.name=memory +memory.max-data-per-node=128MB \ No newline at end of file diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/file.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/file.py index baa3db6afc1..64c3aeacf3e 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/file.py +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/file.py @@ -21,15 +21,15 @@ class FileDataSourceCreator(DataSourceCreator): files: List[Any] - def __init__(self, project_name: str): - self.project_name = project_name + def __init__(self, project_name: str, *args, **kwargs): + super().__init__(project_name) self.files = [] def create_data_source( self, df: pd.DataFrame, destination_name: str, - event_timestamp_column="ts", + timestamp_field="ts", created_timestamp_column="created_ts", field_mapping: Dict[str, str] = None, ) -> DataSource: @@ -46,9 +46,8 @@ def create_data_source( return FileSource( file_format=ParquetFormat(), path=f"{f.name}", - event_timestamp_column=event_timestamp_column, + timestamp_field=timestamp_field, created_timestamp_column=created_timestamp_column, - date_partition_column="", field_mapping=field_mapping or {"ts_1": "ts"}, ) @@ -114,7 +113,7 @@ def create_data_source( df: pd.DataFrame, destination_name: Optional[str] = None, suffix: Optional[str] = None, - event_timestamp_column="ts", + timestamp_field="ts", created_timestamp_column="created_ts", field_mapping: Dict[str, str] = None, ) -> DataSource: @@ -128,9 +127,8 @@ def create_data_source( return FileSource( file_format=ParquetFormat(), path=f"s3://{self.bucket}/{filename}", - event_timestamp_column=event_timestamp_column, + timestamp_field=timestamp_field, created_timestamp_column=created_timestamp_column, - date_partition_column="", field_mapping=field_mapping or {"ts_1": "ts"}, s3_endpoint_override=f"http://{host}:{port}", ) diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/redshift.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/redshift.py index 49b31263cf9..7e305fee801 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/redshift.py +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/redshift.py @@ -18,9 +18,8 @@ class RedshiftDataSourceCreator(DataSourceCreator): tables: List[str] = [] - def __init__(self, project_name: str): - super().__init__() - self.project_name = project_name + def __init__(self, project_name: str, *args, **kwargs): + super().__init__(project_name) self.client = aws_utils.get_redshift_data_client("us-west-2") self.s3 = aws_utils.get_s3_resource("us-west-2") @@ -38,7 +37,7 @@ def create_data_source( df: pd.DataFrame, destination_name: str, suffix: Optional[str] = None, - event_timestamp_column="ts", + timestamp_field="ts", created_timestamp_column="created_ts", field_mapping: Dict[str, str] = None, ) -> DataSource: @@ -61,10 +60,10 @@ def create_data_source( return RedshiftSource( table=destination_name, - event_timestamp_column=event_timestamp_column, + timestamp_field=timestamp_field, created_timestamp_column=created_timestamp_column, - date_partition_column="", field_mapping=field_mapping or {"ts_1": "ts"}, + database=self.offline_store_config.database, ) def create_saved_dataset_destination(self) -> SavedDatasetRedshiftStorage: diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py index f76656f5b71..3942444f324 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py @@ -19,9 +19,8 @@ class SnowflakeDataSourceCreator(DataSourceCreator): tables: List[str] = [] - def __init__(self, project_name: str): - super().__init__() - self.project_name = project_name + def __init__(self, project_name: str, *args, **kwargs): + super().__init__(project_name) self.offline_store_config = SnowflakeOfflineStoreConfig( type="snowflake.offline", account=os.environ["SNOWFLAKE_CI_DEPLOYMENT"], @@ -38,7 +37,7 @@ def create_data_source( df: pd.DataFrame, destination_name: str, suffix: Optional[str] = None, - event_timestamp_column="ts", + timestamp_field="ts", created_timestamp_column="created_ts", field_mapping: Dict[str, str] = None, ) -> DataSource: @@ -53,10 +52,10 @@ def create_data_source( return SnowflakeSource( table=destination_name, - event_timestamp_column=event_timestamp_column, + timestamp_field=timestamp_field, created_timestamp_column=created_timestamp_column, - date_partition_column="", field_mapping=field_mapping or {"ts_1": "ts"}, + warehouse=self.offline_store_config.warehouse, ) def create_saved_dataset_destination(self) -> SavedDatasetSnowflakeStorage: diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/spark_data_source_creator.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/spark_data_source_creator.py index 4284c3cf4c4..65cdde94574 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/spark_data_source_creator.py +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/spark_data_source_creator.py @@ -23,7 +23,8 @@ class SparkDataSourceCreator(DataSourceCreator): spark_offline_store_config = None spark_session = None - def __init__(self, project_name: str): + def __init__(self, project_name: str, *args, **kwargs): + super().__init__(project_name) self.spark_conf = { "master": "local[*]", "spark.ui.enabled": "false", @@ -31,7 +32,6 @@ def __init__(self, project_name: str): "spark.sql.parser.quotedRegexColumnNames": "true", "spark.sql.session.timeZone": "UTC", } - self.project_name = project_name if not self.spark_offline_store_config: self.create_offline_store_config() if not self.spark_session: @@ -59,23 +59,21 @@ def create_data_source( self, df: pd.DataFrame, destination_name: str, - event_timestamp_column="ts", + timestamp_field="ts", created_timestamp_column="created_ts", field_mapping: Dict[str, str] = None, **kwargs, ) -> DataSource: - if event_timestamp_column in df: - df[event_timestamp_column] = pd.to_datetime( - df[event_timestamp_column], utc=True - ) + if timestamp_field in df: + df[timestamp_field] = pd.to_datetime(df[timestamp_field], utc=True) # Make sure the field mapping is correct and convert the datetime datasources. if field_mapping: timestamp_mapping = {value: key for key, value in field_mapping.items()} if ( - event_timestamp_column in timestamp_mapping - and timestamp_mapping[event_timestamp_column] in df + timestamp_field in timestamp_mapping + and timestamp_mapping[timestamp_field] in df ): - col = timestamp_mapping[event_timestamp_column] + col = timestamp_mapping[timestamp_field] df[col] = pd.to_datetime(df[col], utc=True) destination_name = self.get_prefixed_table_name(destination_name) if not self.spark_session: @@ -93,16 +91,17 @@ def create_data_source( return SparkSource( table=destination_name, - event_timestamp_column=event_timestamp_column, + timestamp_field=timestamp_field, created_timestamp_column=created_timestamp_column, date_partition_column="", - # maps certain column names to other names field_mapping=field_mapping or {"ts_1": "ts"}, ) def create_saved_dataset_destination(self) -> SavedDatasetSparkStorage: table = f"persisted_{str(uuid.uuid4()).replace('-', '_')}" - return SavedDatasetSparkStorage(table_ref=table, query="") + return SavedDatasetSparkStorage( + table=table, query=None, path=None, file_format=None + ) def get_prefixed_table_name(self, suffix: str) -> str: return f"{self.project_name}_{suffix}" diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/trino.py b/sdk/python/tests/integration/feature_repos/universal/data_sources/trino.py new file mode 100644 index 00000000000..07ae210b12c --- /dev/null +++ b/sdk/python/tests/integration/feature_repos/universal/data_sources/trino.py @@ -0,0 +1,119 @@ +import pathlib +import uuid +from typing import Dict, List, Optional + +import pandas as pd +from testcontainers.core.container import DockerContainer +from testcontainers.core.waiting_utils import wait_for_logs + +from feast.data_source import DataSource +from feast.infra.offline_stores.contrib.trino_offline_store.connectors.upload import ( + upload_pandas_dataframe_to_trino, +) +from feast.infra.offline_stores.contrib.trino_offline_store.trino import ( + TrinoOfflineStoreConfig, +) +from feast.infra.offline_stores.contrib.trino_offline_store.trino_queries import Trino +from feast.infra.offline_stores.contrib.trino_offline_store.trino_source import ( + SavedDatasetTrinoStorage, + TrinoSource, +) +from feast.repo_config import FeastConfigBaseModel +from tests.integration.feature_repos.universal.data_source_creator import ( + DataSourceCreator, +) + + +class TrinoSourceCreator(DataSourceCreator): + + tables: List[str] = [] + + def __init__(self, project_name: str, **kwargs): + super().__init__(project_name) + self.tables_created: List[str] = [] + + if "offline_container" not in kwargs or not kwargs.get( + "offline_container", None + ): + # If we don't get an offline container provided, we try to create it on the fly. + # the problem here is that each test creates its own conatiner, which basically + # browns out developer laptops. + current_file = pathlib.Path(__file__).parent.resolve() + catalog_dir = current_file.parent.joinpath("catalog") + self.container = ( + DockerContainer("trinodb/trino:376") + .with_volume_mapping(catalog_dir, "/etc/catalog/") + .with_exposed_ports("8080") + ) + + self.container.start() + self.provided_container = False + log_string_to_wait_for = "SERVER STARTED" + wait_for_logs( + container=self.container, predicate=log_string_to_wait_for, timeout=30 + ) + else: + self.provided_container = True + self.container = kwargs["offline_container"] + + self.exposed_port = self.container.get_exposed_port("8080") + self.client = Trino( + user="user", catalog="memory", host="localhost", port=self.exposed_port, + ) + + def teardown(self): + if not self.provided_container: + self.container.stop() + + def create_data_source( + self, + df: pd.DataFrame, + destination_name: str, + suffix: Optional[str] = None, + timestamp_field="ts", + created_timestamp_column="created_ts", + field_mapping: Optional[Dict[str, str]] = None, + ) -> DataSource: + destination_name = self.get_prefixed_table_name(destination_name) + self.client.execute_query( + f"CREATE SCHEMA IF NOT EXISTS memory.{self.project_name}" + ) + self.client.execute_query(f"DROP TABLE IF EXISTS {destination_name}") + + self.tables.append(destination_name) + + upload_pandas_dataframe_to_trino( + client=self.client, + df=df, + table=destination_name, + connector_args={"type": "memory"}, + ) + + return TrinoSource( + name="ci_trino_offline_store", + table=destination_name, + event_timestamp_column=timestamp_field, + created_timestamp_column=created_timestamp_column, + query=f"SELECT * FROM {destination_name}", + field_mapping=field_mapping or {"ts_1": "ts"}, + ) + + def create_saved_dataset_destination(self) -> SavedDatasetTrinoStorage: + table = self.get_prefixed_table_name( + f"persisted_ds_{str(uuid.uuid4()).replace('-', '_')}" + ) + self.tables.append(table) + + return SavedDatasetTrinoStorage(table=table) + + def get_prefixed_table_name(self, suffix: str) -> str: + return f"memory.{self.project_name}.{suffix}" + + def create_offline_store_config(self) -> FeastConfigBaseModel: + return TrinoOfflineStoreConfig( + host="localhost", + port=self.exposed_port, + catalog="memory", + dataset=self.project_name, + connector={"type": "memory"}, + ) diff --git a/sdk/python/tests/integration/feature_repos/universal/feature_views.py b/sdk/python/tests/integration/feature_repos/universal/feature_views.py index b0dc34197f3..5918e367532 100644 --- a/sdk/python/tests/integration/feature_repos/universal/feature_views.py +++ b/sdk/python/tests/integration/feature_repos/universal/feature_views.py @@ -4,23 +4,31 @@ import numpy as np import pandas as pd -from feast import Feature, FeatureView, OnDemandFeatureView, ValueType -from feast.data_source import DataSource, RequestDataSource -from feast.request_feature_view import RequestFeatureView +from feast import ( + Feature, + FeatureView, + Field, + OnDemandFeatureView, + PushSource, + ValueType, +) +from feast.data_source import DataSource, RequestSource +from feast.types import Array, FeastType, Float32, Float64, Int32, Int64 +from tests.integration.feature_repos.universal.entities import location def driver_feature_view( data_source: DataSource, name="test_correctness", infer_features: bool = False, - value_type: ValueType = ValueType.FLOAT, + dtype: FeastType = Float32, ) -> FeatureView: return FeatureView( name=name, entities=["driver"], - features=None if infer_features else [Feature("value", value_type)], + schema=None if infer_features else [Field(name="value", dtype=dtype)], ttl=timedelta(days=5), - batch_source=data_source, + source=data_source, ) @@ -33,9 +41,12 @@ def global_feature_view( return FeatureView( name=name, entities=[], - features=None if infer_features else [Feature("entityless_value", value_type)], + # Test that Features still work for FeatureViews. + features=None + if infer_features + else [Feature(name="entityless_value", dtype=value_type)], ttl=timedelta(days=5), - batch_source=data_source, + source=data_source, ) @@ -52,20 +63,21 @@ def conv_rate_plus_100(features_df: pd.DataFrame) -> pd.DataFrame: def conv_rate_plus_100_feature_view( - inputs: Dict[str, Union[RequestDataSource, FeatureView]], + sources: Dict[str, Union[RequestSource, FeatureView]], infer_features: bool = False, features: Optional[List[Feature]] = None, ) -> OnDemandFeatureView: + # Test that positional arguments and Features still work for ODFVs. _features = features or [ - Feature("conv_rate_plus_100", ValueType.DOUBLE), - Feature("conv_rate_plus_val_to_add", ValueType.DOUBLE), - Feature("conv_rate_plus_100_rounded", ValueType.INT32), + Feature(name="conv_rate_plus_100", dtype=ValueType.DOUBLE), + Feature(name="conv_rate_plus_val_to_add", dtype=ValueType.DOUBLE), + Feature(name="conv_rate_plus_100_rounded", dtype=ValueType.INT32), ] return OnDemandFeatureView( - name=conv_rate_plus_100.__name__, - inputs=inputs, - features=[] if infer_features else _features, - udf=conv_rate_plus_100, + conv_rate_plus_100.__name__, + [] if infer_features else _features, + sources, + conv_rate_plus_100, ) @@ -87,39 +99,33 @@ def similarity(features_df: pd.DataFrame) -> pd.DataFrame: def similarity_feature_view( - inputs: Dict[str, Union[RequestDataSource, FeatureView]], + sources: Dict[str, Union[RequestSource, FeatureView]], infer_features: bool = False, features: Optional[List[Feature]] = None, ) -> OnDemandFeatureView: - _features = features or [ - Feature("cos_double", ValueType.DOUBLE), - Feature("cos_float", ValueType.FLOAT), + _fields = [ + Field(name="cos_double", dtype=Float64), + Field(name="cos_float", dtype=Float32), ] + if features is not None: + _fields = [Field.from_feature(feature) for feature in features] + return OnDemandFeatureView( name=similarity.__name__, - inputs=inputs, - features=[] if infer_features else _features, + sources=sources, + schema=[] if infer_features else _fields, udf=similarity, ) -def create_driver_age_request_feature_view(): - return RequestFeatureView( - name="driver_age", - request_data_source=RequestDataSource( - name="driver_age_source", schema={"driver_age": ValueType.INT32} - ), - ) - - -def create_conv_rate_request_data_source(): - return RequestDataSource( - name="conv_rate_input", schema={"val_to_add": ValueType.INT32} +def create_conv_rate_request_source(): + return RequestSource( + name="conv_rate_input", schema=[Field(name="val_to_add", dtype=Int32)], ) -def create_similarity_request_data_source(): - return RequestDataSource( +def create_similarity_request_source(): + return RequestSource( name="similarity_input", schema={ "vector_double": ValueType.DOUBLE_LIST, @@ -132,11 +138,11 @@ def create_item_embeddings_feature_view(source, infer_features: bool = False): item_embeddings_feature_view = FeatureView( name="item_embeddings", entities=["item"], - features=None + schema=None if infer_features else [ - Feature(name="embedding_double", dtype=ValueType.DOUBLE_LIST), - Feature(name="embedding_float", dtype=ValueType.FLOAT_LIST), + Field(name="embedding_double", dtype=Array(Float64)), + Field(name="embedding_float", dtype=Array(Float32)), ], batch_source=source, ttl=timedelta(hours=2), @@ -148,14 +154,14 @@ def create_driver_hourly_stats_feature_view(source, infer_features: bool = False driver_stats_feature_view = FeatureView( name="driver_stats", entities=["driver"], - features=None + schema=None if infer_features else [ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT32), + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int32), ], - batch_source=source, + source=source, ttl=timedelta(hours=2), ) return driver_stats_feature_view @@ -165,14 +171,14 @@ def create_customer_daily_profile_feature_view(source, infer_features: bool = Fa customer_profile_feature_view = FeatureView( name="customer_profile", entities=["customer_id"], - features=None + schema=None if infer_features else [ - Feature(name="current_balance", dtype=ValueType.FLOAT), - Feature(name="avg_passenger_count", dtype=ValueType.FLOAT), - Feature(name="lifetime_trip_count", dtype=ValueType.INT32), + Field(name="current_balance", dtype=Float32), + Field(name="avg_passenger_count", dtype=Float32), + Field(name="lifetime_trip_count", dtype=Int32), ], - batch_source=source, + source=source, ttl=timedelta(days=2), ) return customer_profile_feature_view @@ -185,10 +191,11 @@ def create_global_stats_feature_view(source, infer_features: bool = False): features=None if infer_features else [ + # Test that Features still work for FeatureViews. Feature(name="num_rides", dtype=ValueType.INT32), Feature(name="avg_ride_length", dtype=ValueType.FLOAT), ], - batch_source=source, + source=source, ttl=timedelta(days=2), ) return global_stats_feature_view @@ -198,10 +205,10 @@ def create_order_feature_view(source, infer_features: bool = False): return FeatureView( name="order", entities=["driver", "customer_id"], - features=None + schema=None if infer_features - else [Feature(name="order_is_success", dtype=ValueType.INT32)], - batch_source=source, + else [Field(name="order_is_success", dtype=Int32)], + source=source, ttl=timedelta(days=2), ) @@ -209,11 +216,9 @@ def create_order_feature_view(source, infer_features: bool = False): def create_location_stats_feature_view(source, infer_features: bool = False): location_stats_feature_view = FeatureView( name="location_stats", - entities=["location_id"], - features=None - if infer_features - else [Feature(name="temperature", dtype=ValueType.INT32)], - batch_source=source, + entities=[location()], + schema=None if infer_features else [Field(name="temperature", dtype=Int32)], + source=source, ttl=timedelta(days=2), ) return location_stats_feature_view @@ -223,7 +228,28 @@ def create_field_mapping_feature_view(source): return FeatureView( name="field_mapping", entities=[], + # Test that Features still work for FeatureViews. features=[Feature(name="feature_name", dtype=ValueType.INT32)], - batch_source=source, + source=source, + ttl=timedelta(days=2), + ) + + +def create_pushable_feature_view(batch_source: DataSource): + push_source = PushSource( + name="location_stats_push_source", + schema=[ + Field(name="location_id", dtype=Int64), + Field(name="temperature", dtype=Int32), + ], + timestamp_field="timestamp", + batch_source=batch_source, + ) + return FeatureView( + name="pushable_location_stats", + entities=["location_id"], + # Test that Features still work for FeatureViews. + features=[Feature(name="temperature", dtype=ValueType.INT32)], ttl=timedelta(days=2), + source=push_source, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/__init__.py b/sdk/python/tests/integration/feature_repos/universal/online_store/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/datastore.py b/sdk/python/tests/integration/feature_repos/universal/online_store/datastore.py new file mode 100644 index 00000000000..52851e80d88 --- /dev/null +++ b/sdk/python/tests/integration/feature_repos/universal/online_store/datastore.py @@ -0,0 +1,38 @@ +import os +from typing import Dict + +from google.cloud import datastore +from testcontainers.core.container import DockerContainer +from testcontainers.core.waiting_utils import wait_for_logs + +from tests.integration.feature_repos.universal.online_store_creator import ( + OnlineStoreCreator, +) + + +class DatastoreOnlineStoreCreator(OnlineStoreCreator): + def __init__(self, project_name: str): + super().__init__(project_name) + self.container = ( + DockerContainer( + "gcr.io/google.com/cloudsdktool/cloud-sdk:380.0.0-emulators" + ) + .with_command( + "gcloud beta emulators datastore start --project test-project --host-port 0.0.0.0:8081" + ) + .with_exposed_ports("8081") + ) + + def create_online_store(self) -> Dict[str, str]: + self.container.start() + log_string_to_wait_for = r"\[datastore\] Dev App Server is now running" + wait_for_logs( + container=self.container, predicate=log_string_to_wait_for, timeout=5 + ) + exposed_port = self.container.get_exposed_port("8081") + os.environ[datastore.client.DATASTORE_EMULATOR_HOST] = f"0.0.0.0:{exposed_port}" + return {"type": "datastore", "project_id": "test-project"} + + def teardown(self): + del os.environ[datastore.client.DATASTORE_EMULATOR_HOST] + self.container.stop() diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/dynamodb.py b/sdk/python/tests/integration/feature_repos/universal/online_store/dynamodb.py new file mode 100644 index 00000000000..e4d8e0c3d02 --- /dev/null +++ b/sdk/python/tests/integration/feature_repos/universal/online_store/dynamodb.py @@ -0,0 +1,34 @@ +from typing import Dict + +from testcontainers.core.container import DockerContainer +from testcontainers.core.waiting_utils import wait_for_logs + +from tests.integration.feature_repos.universal.online_store_creator import ( + OnlineStoreCreator, +) + + +class DynamoDBOnlineStoreCreator(OnlineStoreCreator): + def __init__(self, project_name: str): + super().__init__(project_name) + self.container = DockerContainer( + "amazon/dynamodb-local:latest" + ).with_exposed_ports("8000") + + def create_online_store(self) -> Dict[str, str]: + self.container.start() + log_string_to_wait_for = ( + "Initializing DynamoDB Local with the following configuration:" + ) + wait_for_logs( + container=self.container, predicate=log_string_to_wait_for, timeout=5 + ) + exposed_port = self.container.get_exposed_port("8000") + return { + "type": "dynamodb", + "endpoint_url": f"http://localhost:{exposed_port}", + "region": "us-west-2", + } + + def teardown(self): + self.container.stop() diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/redis.py b/sdk/python/tests/integration/feature_repos/universal/online_store/redis.py new file mode 100644 index 00000000000..073760f5145 --- /dev/null +++ b/sdk/python/tests/integration/feature_repos/universal/online_store/redis.py @@ -0,0 +1,26 @@ +from typing import Dict + +from testcontainers.core.container import DockerContainer +from testcontainers.core.waiting_utils import wait_for_logs + +from tests.integration.feature_repos.universal.online_store_creator import ( + OnlineStoreCreator, +) + + +class RedisOnlineStoreCreator(OnlineStoreCreator): + def __init__(self, project_name: str): + super().__init__(project_name) + self.container = DockerContainer("redis").with_exposed_ports("6379") + + def create_online_store(self) -> Dict[str, str]: + self.container.start() + log_string_to_wait_for = "Ready to accept connections" + wait_for_logs( + container=self.container, predicate=log_string_to_wait_for, timeout=5 + ) + exposed_port = self.container.get_exposed_port("6379") + return {"type": "redis", "connection_string": f"localhost:{exposed_port},db=0"} + + def teardown(self): + self.container.stop() diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store_creator.py b/sdk/python/tests/integration/feature_repos/universal/online_store_creator.py new file mode 100644 index 00000000000..0fa0dbed3e1 --- /dev/null +++ b/sdk/python/tests/integration/feature_repos/universal/online_store_creator.py @@ -0,0 +1,14 @@ +from abc import ABC + +from feast.repo_config import FeastConfigBaseModel + + +class OnlineStoreCreator(ABC): + def __init__(self, project_name: str): + self.project_name = project_name + + def create_online_store(self) -> FeastConfigBaseModel: + ... + + def teardown(self): + ... diff --git a/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py b/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py index 6066009a6d6..dfe14d73f96 100644 --- a/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py +++ b/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py @@ -45,7 +45,7 @@ def test_registration_and_retrieval_from_custom_s3_endpoint(universal_data_sourc fs.materialize(environment.start_date, environment.end_date) out = fs.get_online_features( - features=["driver_stats:conv_rate"], entity_rows=[{"driver": 5001}] + features=["driver_stats:conv_rate"], entity_rows=[{"driver_id": 5001}] ).to_dict() assert out["conv_rate"][0] is not None diff --git a/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py b/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py index ab9b9515f39..0d6ef84ff47 100644 --- a/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py +++ b/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py @@ -15,12 +15,13 @@ FeatureNameCollisionError, RequestDataNotFoundInEntityDfException, ) -from feast.feature import Feature from feast.feature_service import FeatureService from feast.feature_view import FeatureView +from feast.field import Field from feast.infra.offline_stores.offline_utils import ( DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL, ) +from feast.types import Int32 from feast.value_type import ValueType from tests.integration.feature_repos.repo_configuration import ( construct_universal_feature_views, @@ -93,23 +94,23 @@ def get_expected_training_df( ): # Convert all pandas dataframes into records with UTC timestamps customer_records = convert_timestamp_records_to_utc( - customer_df.to_dict("records"), customer_fv.batch_source.event_timestamp_column + customer_df.to_dict("records"), customer_fv.batch_source.timestamp_field ) driver_records = convert_timestamp_records_to_utc( - driver_df.to_dict("records"), driver_fv.batch_source.event_timestamp_column + driver_df.to_dict("records"), driver_fv.batch_source.timestamp_field ) order_records = convert_timestamp_records_to_utc( orders_df.to_dict("records"), event_timestamp ) location_records = convert_timestamp_records_to_utc( - location_df.to_dict("records"), location_fv.batch_source.event_timestamp_column + location_df.to_dict("records"), location_fv.batch_source.timestamp_field ) global_records = convert_timestamp_records_to_utc( - global_df.to_dict("records"), global_fv.batch_source.event_timestamp_column + global_df.to_dict("records"), global_fv.batch_source.timestamp_field ) field_mapping_records = convert_timestamp_records_to_utc( field_mapping_df.to_dict("records"), - field_mapping_fv.batch_source.event_timestamp_column, + field_mapping_fv.batch_source.timestamp_field, ) entity_rows = convert_timestamp_records_to_utc( entity_df.to_dict("records"), event_timestamp @@ -120,7 +121,7 @@ def get_expected_training_df( for entity_row in entity_rows: customer_record = find_asof_record( customer_records, - ts_key=customer_fv.batch_source.event_timestamp_column, + ts_key=customer_fv.batch_source.timestamp_field, ts_start=entity_row[event_timestamp] - customer_fv.ttl, ts_end=entity_row[event_timestamp], filter_keys=["customer_id"], @@ -128,7 +129,7 @@ def get_expected_training_df( ) driver_record = find_asof_record( driver_records, - ts_key=driver_fv.batch_source.event_timestamp_column, + ts_key=driver_fv.batch_source.timestamp_field, ts_start=entity_row[event_timestamp] - driver_fv.ttl, ts_end=entity_row[event_timestamp], filter_keys=["driver_id"], @@ -136,7 +137,7 @@ def get_expected_training_df( ) order_record = find_asof_record( order_records, - ts_key=customer_fv.batch_source.event_timestamp_column, + ts_key=customer_fv.batch_source.timestamp_field, ts_start=entity_row[event_timestamp] - order_fv.ttl, ts_end=entity_row[event_timestamp], filter_keys=["customer_id", "driver_id"], @@ -144,7 +145,7 @@ def get_expected_training_df( ) origin_record = find_asof_record( location_records, - ts_key=location_fv.batch_source.event_timestamp_column, + ts_key=location_fv.batch_source.timestamp_field, ts_start=order_record[event_timestamp] - location_fv.ttl, ts_end=order_record[event_timestamp], filter_keys=["location_id"], @@ -152,7 +153,7 @@ def get_expected_training_df( ) destination_record = find_asof_record( location_records, - ts_key=location_fv.batch_source.event_timestamp_column, + ts_key=location_fv.batch_source.timestamp_field, ts_start=order_record[event_timestamp] - location_fv.ttl, ts_end=order_record[event_timestamp], filter_keys=["location_id"], @@ -160,14 +161,14 @@ def get_expected_training_df( ) global_record = find_asof_record( global_records, - ts_key=global_fv.batch_source.event_timestamp_column, + ts_key=global_fv.batch_source.timestamp_field, ts_start=order_record[event_timestamp] - global_fv.ttl, ts_end=order_record[event_timestamp], ) field_mapping_record = find_asof_record( field_mapping_records, - ts_key=field_mapping_fv.batch_source.event_timestamp_column, + ts_key=field_mapping_fv.batch_source.timestamp_field, ts_start=order_record[event_timestamp] - field_mapping_fv.ttl, ts_end=order_record[event_timestamp], ) @@ -219,7 +220,10 @@ def get_expected_training_df( ( f"field_mapping__{feature}" if full_feature_names else feature ): field_mapping_record.get(column, None) - for (column, feature) in field_mapping_fv.input.field_mapping.items() + for ( + column, + feature, + ) in field_mapping_fv.batch_source.field_mapping.items() } ) @@ -295,11 +299,7 @@ def test_historical_features(environment, universal_data_sources, full_feature_n feature_service = FeatureService( name="convrate_plus100", - features=[ - feature_views.driver[["conv_rate"]], - feature_views.driver_odfv, - feature_views.driver_age_request_fv, - ], + features=[feature_views.driver[["conv_rate"]], feature_views.driver_odfv], ) feature_service_entity_mapping = FeatureService( name="entity_mapping", @@ -366,7 +366,6 @@ def test_historical_features(environment, universal_data_sources, full_feature_n "order:order_is_success", "global_stats:num_rides", "global_stats:avg_ride_length", - "driver_age:driver_age", "field_mapping:feature_name", ], full_feature_names=full_feature_names, @@ -441,22 +440,6 @@ def test_historical_features_with_missing_request_data( full_feature_names=full_feature_names, ) - # If request data is missing that's needed for a request feature view, throw an error - with pytest.raises(RequestDataNotFoundInEntityDfException): - store.get_historical_features( - entity_df=datasets.entity_df, - features=[ - "customer_profile:current_balance", - "customer_profile:avg_passenger_count", - "customer_profile:lifetime_trip_count", - "driver_age:driver_age", - "global_stats:num_rides", - "global_stats:avg_ride_length", - "field_mapping:feature_name", - ], - full_feature_names=full_feature_names, - ) - @pytest.mark.integration @pytest.mark.universal @@ -465,7 +448,6 @@ def test_historical_features_with_entities_from_query( environment, universal_data_sources, full_feature_names ): store = environment.feature_store - (entities, datasets, data_sources) = universal_data_sources feature_views = construct_universal_feature_views(data_sources) @@ -473,13 +455,17 @@ def test_historical_features_with_entities_from_query( if not orders_table: raise pytest.skip("Offline source is not sql-based") - if ( - environment.test_repo_config.offline_store_creator.__name__ - == SnowflakeDataSourceCreator.__name__ - ): - entity_df_query = f'''SELECT "customer_id", "driver_id", "order_id", "origin_id", "destination_id", "event_timestamp" FROM "{orders_table}"''' + data_source_creator = environment.test_repo_config.offline_store_creator + if data_source_creator.__name__ == SnowflakeDataSourceCreator.__name__: + entity_df_query = f""" + SELECT "customer_id", "driver_id", "order_id", "origin_id", "destination_id", "event_timestamp" + FROM "{orders_table}" + """ else: - entity_df_query = f"SELECT customer_id, driver_id, order_id, origin_id, destination_id, event_timestamp FROM {orders_table}" + entity_df_query = f""" + SELECT customer_id, driver_id, order_id, origin_id, destination_id, event_timestamp + FROM {orders_table} + """ store.apply([driver(), customer(), location(), *feature_views.values()]) @@ -641,11 +627,12 @@ def test_historical_features_from_bigquery_sources_containing_backfills(environm now = datetime.now().replace(microsecond=0, second=0, minute=0) tomorrow = now + timedelta(days=1) + day_after_tomorrow = now + timedelta(days=2) entity_df = pd.DataFrame( data=[ - {"driver_id": 1001, "event_timestamp": now + timedelta(days=2)}, - {"driver_id": 1002, "event_timestamp": now + timedelta(days=2)}, + {"driver_id": 1001, "event_timestamp": day_after_tomorrow}, + {"driver_id": 1002, "event_timestamp": day_after_tomorrow}, ] ) @@ -684,12 +671,12 @@ def test_historical_features_from_bigquery_sources_containing_backfills(environm data=[ { "driver_id": 1001, - "event_timestamp": now + timedelta(days=2), + "event_timestamp": day_after_tomorrow, "avg_daily_trips": 20, }, { "driver_id": 1002, - "event_timestamp": now + timedelta(days=2), + "event_timestamp": day_after_tomorrow, "avg_daily_trips": 40, }, ] @@ -698,7 +685,7 @@ def test_historical_features_from_bigquery_sources_containing_backfills(environm driver_stats_data_source = environment.data_source_creator.create_data_source( df=driver_stats_df, destination_name=f"test_driver_stats_{int(time.time_ns())}_{random.randint(1000, 9999)}", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) @@ -706,7 +693,7 @@ def test_historical_features_from_bigquery_sources_containing_backfills(environm driver_fv = FeatureView( name="driver_stats", entities=["driver"], - features=[Feature(name="avg_daily_trips", dtype=ValueType.INT32)], + schema=[Field(name="avg_daily_trips", dtype=Int32)], batch_source=driver_stats_data_source, ttl=None, ) diff --git a/sdk/python/tests/integration/online_store/test_e2e_local.py b/sdk/python/tests/integration/online_store/test_e2e_local.py index 79902273440..c1aa10900ae 100644 --- a/sdk/python/tests/integration/online_store/test_e2e_local.py +++ b/sdk/python/tests/integration/online_store/test_e2e_local.py @@ -12,7 +12,7 @@ def _get_last_feature_row(df: pd.DataFrame, driver_id, max_date: datetime): - """ Manually extract last feature value from a dataframe for a given driver_id with up to `max_date` date """ + """Manually extract last feature value from a dataframe for a given driver_id with up to `max_date` date""" filtered = df[ (df["driver_id"] == driver_id) & (df["event_timestamp"] < max_date.replace(tzinfo=utc)) @@ -40,12 +40,12 @@ def _assert_online_features( # Float features should still be floats from the online store... assert ( - response.proto.results[0] - .values[ + response.proto.results[ list(response.proto.metadata.feature_names.val).index( "driver_hourly_stats__conv_rate" ) ] + .values[0] .float_val > 0 ) diff --git a/sdk/python/tests/integration/online_store/test_online_retrieval.py b/sdk/python/tests/integration/online_store/test_online_retrieval.py index 265fedd2826..9cf4d9a1823 100644 --- a/sdk/python/tests/integration/online_store/test_online_retrieval.py +++ b/sdk/python/tests/integration/online_store/test_online_retrieval.py @@ -34,7 +34,7 @@ def test_online() -> None: provider = store._get_provider() driver_key = EntityKeyProto( - join_keys=["driver"], entity_values=[ValueProto(int64_val=1)] + join_keys=["driver_id"], entity_values=[ValueProto(int64_val=1)] ) provider.online_write_batch( config=store.config, @@ -54,7 +54,7 @@ def test_online() -> None: ) customer_key = EntityKeyProto( - join_keys=["customer"], entity_values=[ValueProto(string_val="5")] + join_keys=["customer_id"], entity_values=[ValueProto(string_val="5")] ) provider.online_write_batch( config=store.config, @@ -75,7 +75,7 @@ def test_online() -> None: ) customer_key = EntityKeyProto( - join_keys=["customer", "driver"], + join_keys=["customer_id", "driver_id"], entity_values=[ValueProto(string_val="5"), ValueProto(int64_val=1)], ) provider.online_write_batch( @@ -100,15 +100,18 @@ def test_online() -> None: "customer_profile:name", "customer_driver_combined:trips", ], - entity_rows=[{"driver": 1, "customer": "5"}, {"driver": 1, "customer": 5}], + entity_rows=[ + {"driver_id": 1, "customer_id": "5"}, + {"driver_id": 1, "customer_id": 5}, + ], full_feature_names=False, ).to_dict() assert "lon" in result assert "avg_orders_day" in result assert "name" in result - assert result["driver"] == [1, 1] - assert result["customer"] == ["5", "5"] + assert result["driver_id"] == [1, 1] + assert result["customer_id"] == ["5", "5"] assert result["lon"] == ["1.0", "1.0"] assert result["avg_orders_day"] == [1.0, 1.0] assert result["name"] == ["John", "John"] @@ -117,7 +120,7 @@ def test_online() -> None: # Ensure features are still in result when keys not found result = store.get_online_features( features=["customer_driver_combined:trips"], - entity_rows=[{"driver": 0, "customer": 0}], + entity_rows=[{"driver_id": 0, "customer_id": 0}], full_feature_names=False, ).to_dict() @@ -127,7 +130,7 @@ def test_online() -> None: with pytest.raises(FeatureViewNotFoundException): store.get_online_features( features=["driver_locations_bad:lon"], - entity_rows=[{"driver": 1}], + entity_rows=[{"driver_id": 1}], full_feature_names=False, ) @@ -152,7 +155,7 @@ def test_online() -> None: "customer_profile:name", "customer_driver_combined:trips", ], - entity_rows=[{"driver": 1, "customer": 5}], + entity_rows=[{"driver_id": 1, "customer_id": 5}], full_feature_names=False, ).to_dict() assert result["lon"] == ["1.0"] @@ -173,7 +176,7 @@ def test_online() -> None: "customer_profile:name", "customer_driver_combined:trips", ], - entity_rows=[{"driver": 1, "customer": 5}], + entity_rows=[{"driver_id": 1, "customer_id": 5}], full_feature_names=False, ).to_dict() @@ -188,7 +191,7 @@ def test_online() -> None: "customer_profile:name", "customer_driver_combined:trips", ], - entity_rows=[{"driver": 1, "customer": 5}], + entity_rows=[{"driver_id": 1, "customer_id": 5}], full_feature_names=False, ).to_dict() assert result["lon"] == ["1.0"] @@ -214,7 +217,7 @@ def test_online() -> None: "customer_profile:name", "customer_driver_combined:trips", ], - entity_rows=[{"driver": 1, "customer": 5}], + entity_rows=[{"driver_id": 1, "customer_id": 5}], full_feature_names=False, ).to_dict() assert result["lon"] == ["1.0"] @@ -234,7 +237,7 @@ def test_online() -> None: "customer_profile:name", "customer_driver_combined:trips", ], - entity_rows=[{"driver": 1, "customer": 5}], + entity_rows=[{"driver_id": 1, "customer_id": 5}], full_feature_names=False, ).to_dict() assert result["lon"] == ["1.0"] @@ -284,7 +287,7 @@ def test_online_to_df(): 3 3.0 0.3 """ driver_key = EntityKeyProto( - join_keys=["driver"], entity_values=[ValueProto(int64_val=d)] + join_keys=["driver_id"], entity_values=[ValueProto(int64_val=d)] ) provider.online_write_batch( config=store.config, @@ -311,7 +314,7 @@ def test_online_to_df(): 6 6.0 foo6 60 """ customer_key = EntityKeyProto( - join_keys=["customer"], entity_values=[ValueProto(string_val=str(c))] + join_keys=["customer_id"], entity_values=[ValueProto(string_val=str(c))] ) provider.online_write_batch( config=store.config, @@ -340,7 +343,7 @@ def test_online_to_df(): 6 3 18 """ combo_keys = EntityKeyProto( - join_keys=["customer", "driver"], + join_keys=["customer_id", "driver_id"], entity_values=[ValueProto(string_val=str(c)), ValueProto(int64_val=d)], ) provider.online_write_batch( @@ -369,7 +372,7 @@ def test_online_to_df(): ], # Reverse the row order entity_rows=[ - {"driver": d, "customer": c} + {"driver_id": d, "customer_id": c} for (d, c) in zip(reversed(driver_ids), reversed(customer_ids)) ], ).to_df() @@ -381,8 +384,8 @@ def test_online_to_df(): 1 4 1.0 0.1 4.0 foo4 40 4 """ df_dict = { - "driver": driver_ids, - "customer": [str(c) for c in customer_ids], + "driver_id": driver_ids, + "customer_id": [str(c) for c in customer_ids], "lon": [str(d * lon_multiply) for d in driver_ids], "lat": [d * lat_multiply for d in driver_ids], "avg_orders_day": [c * avg_order_day_multiply for c in customer_ids], @@ -392,8 +395,8 @@ def test_online_to_df(): } # Requested column order ordered_column = [ - "driver", - "customer", + "driver_id", + "customer_id", "lon", "lat", "avg_orders_day", diff --git a/sdk/python/tests/integration/online_store/test_push_online_retrieval.py b/sdk/python/tests/integration/online_store/test_push_online_retrieval.py new file mode 100644 index 00000000000..9e9ec953c73 --- /dev/null +++ b/sdk/python/tests/integration/online_store/test_push_online_retrieval.py @@ -0,0 +1,41 @@ +import datetime + +import pandas as pd +import pytest + +from tests.integration.feature_repos.repo_configuration import ( + construct_universal_feature_views, +) +from tests.integration.feature_repos.universal.entities import ( + customer, + driver, + location, +) + + +@pytest.mark.integration +@pytest.mark.universal +def test_push_features_and_read(environment, universal_data_sources): + store = environment.feature_store + + (_, datasets, data_sources) = universal_data_sources + feature_views = construct_universal_feature_views(data_sources) + + store.apply([driver(), customer(), location(), *feature_views.values()]) + data = { + "location_id": [1], + "temperature": [4], + "event_timestamp": [pd.Timestamp(datetime.datetime.utcnow()).round("ms")], + "created": [pd.Timestamp(datetime.datetime.utcnow()).round("ms")], + } + df_ingest = pd.DataFrame(data) + + store.push("location_stats_push_source", df_ingest) + + online_resp = store.get_online_features( + features=["pushable_location_stats:temperature"], + entity_rows=[{"location_id": 1}], + ) + online_resp_dict = online_resp.to_dict() + assert online_resp_dict["location_id"] == [1] + assert online_resp_dict["temperature"] == [4] diff --git a/sdk/python/tests/integration/online_store/test_universal_online.py b/sdk/python/tests/integration/online_store/test_universal_online.py index bdbdfb35552..774c3f9a424 100644 --- a/sdk/python/tests/integration/online_store/test_universal_online.py +++ b/sdk/python/tests/integration/online_store/test_universal_online.py @@ -13,12 +13,13 @@ import requests from botocore.exceptions import BotoCoreError -from feast import Entity, Feature, FeatureService, FeatureView, ValueType +from feast import Entity, FeatureService, FeatureView, Field, ValueType from feast.errors import ( FeatureNameCollisionError, RequestDataNotFoundInEntityRowsException, ) from feast.online_response import TIMESTAMP_POSTFIX +from feast.types import String from feast.wait import wait_retry_backoff from tests.integration.feature_repos.repo_configuration import ( Environment, @@ -71,7 +72,7 @@ def test_entity_ttl_online_store(local_redis_environment, redis_universal_data_s "driver_stats:acc_rate", "driver_stats:conv_rate", ], - entity_rows=[{"driver": 1}], + entity_rows=[{"driver_id": 1}], ).to_df() assertpy.assert_that(df["avg_daily_trips"].iloc[0]).is_equal_to(4) assertpy.assert_that(df["acc_rate"].iloc[0]).is_close_to(0.6, 1e-6) @@ -87,7 +88,7 @@ def test_entity_ttl_online_store(local_redis_environment, redis_universal_data_s "driver_stats:acc_rate", "driver_stats:conv_rate", ], - entity_rows=[{"driver": 1}], + entity_rows=[{"driver_id": 1}], ).to_df() # assert that the entity features expired in the online store assertpy.assert_that(df["avg_daily_trips"].iloc[0]).is_none() @@ -121,7 +122,7 @@ def test_write_to_online_store_event_check(local_redis_environment): # Create Feature View fv1 = FeatureView( name="feature_view_123", - features=[Feature(name="string_col", dtype=ValueType.STRING)], + schema=[Field(name="string_col", dtype=String)], entities=["id"], batch_source=file_source, ttl=timedelta(minutes=5), @@ -230,7 +231,7 @@ def test_write_to_online_store(environment, universal_data_sources): "driver_stats:acc_rate", "driver_stats:conv_rate", ], - entity_rows=[{"driver": 123}], + entity_rows=[{"driver_id": 123}], ).to_df() assertpy.assert_that(df["avg_daily_trips"].iloc[0]).is_equal_to(14) assertpy.assert_that(df["acc_rate"].iloc[0]).is_close_to(0.91, 1e-6) @@ -271,7 +272,7 @@ def _get_online_features_dict_remotely( if response.get("message") != "Internal Server Error": break # Sleep between retries to give the server some time to start - time.sleep(1) + time.sleep(15) else: raise Exception("Failed to get online features from remote feature server") if "metadata" not in response: @@ -280,9 +281,9 @@ def _get_online_features_dict_remotely( ) keys = response["metadata"]["feature_names"] # Get rid of unnecessary structure in the response, leaving list of dicts - response = [row["values"] for row in response["results"]] + values = [row["values"] for row in response["results"]] # Convert list of dicts (response) into dict of lists which is the format of the return value - return {key: [row[idx] for row in response] for idx, key in enumerate(keys)} + return {key: feature_vector for key, feature_vector in zip(keys, values)} def get_online_features_dict( @@ -361,7 +362,7 @@ def test_online_retrieval_with_event_timestamps( "driver_stats:acc_rate", "driver_stats:conv_rate", ], - entity_rows=[{"driver": 1}, {"driver": 2}], + entity_rows=[{"driver_id": 1}, {"driver_id": 2}], ) df = response.to_df(True) assertpy.assert_that(len(df)).is_equal_to(2) @@ -389,6 +390,7 @@ def test_online_retrieval_with_event_timestamps( @pytest.mark.integration @pytest.mark.universal +@pytest.mark.goserver @pytest.mark.parametrize("full_feature_names", [True, False], ids=lambda v: str(v)) def test_online_retrieval(environment, universal_data_sources, full_feature_names): fs = environment.feature_store @@ -400,7 +402,7 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name features=[ feature_views.driver[["conv_rate"]], feature_views.driver_odfv, - feature_views.driver_age_request_fv, + feature_views.customer[["current_balance"]], ], ) feature_service_entity_mapping = FeatureService( @@ -466,7 +468,7 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name global_df = datasets.global_df entity_rows = [ - {"driver": d, "customer_id": c, "val_to_add": 50, "driver_age": 25} + {"driver_id": d, "customer_id": c, "val_to_add": 50} for (d, c) in zip(sample_drivers, sample_customers) ] @@ -481,7 +483,6 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name "order:order_is_success", "global_stats:num_rides", "global_stats:avg_ride_length", - "driver_age:driver_age", ] unprefixed_feature_refs = [f.rsplit(":", 1)[-1] for f in feature_refs if ":" in f] # Remove the on demand feature view output features, since they're not present in the source dataframe @@ -506,22 +507,14 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name assert online_features_no_conv_rate is not None - keys = online_features_dict.keys() + keys = set(online_features_dict.keys()) + expected_keys = set( + f.replace(":", "__") if full_feature_names else f.split(":")[-1] + for f in feature_refs + ) | {"customer_id", "driver_id"} assert ( - len(keys) == len(feature_refs) + 2 - ) # Add two for the driver id and the customer id entity keys - for feature in feature_refs: - # full_feature_names does not apply to request feature views - if full_feature_names and feature != "driver_age:driver_age": - assert feature.replace(":", "__") in keys - else: - assert feature.rsplit(":", 1)[-1] in keys - assert ( - "driver_stats" not in keys - and "customer_profile" not in keys - and "order" not in keys - and "global_stats" not in keys - ) + keys == expected_keys + ), f"Response keys are different from expected: {keys - expected_keys} (extra) and {expected_keys - keys} (missing)" tc = unittest.TestCase() for i, entity_row in enumerate(entity_rows): @@ -537,14 +530,18 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name assert df_features["driver_id"] == online_features_dict["driver_id"][i] tc.assertAlmostEqual( online_features_dict[ - response_feature_name("conv_rate_plus_100", full_feature_names) + response_feature_name( + "conv_rate_plus_100", feature_refs, full_feature_names + ) ][i], df_features["conv_rate"] + 100, delta=0.0001, ) tc.assertAlmostEqual( online_features_dict[ - response_feature_name("conv_rate_plus_val_to_add", full_feature_names) + response_feature_name( + "conv_rate_plus_val_to_add", feature_refs, full_feature_names + ) ][i], df_features["conv_rate"] + df_features["val_to_add"], delta=0.0001, @@ -553,7 +550,9 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name tc.assertAlmostEqual( df_features[unprefixed_feature_ref], online_features_dict[ - response_feature_name(unprefixed_feature_ref, full_feature_names) + response_feature_name( + unprefixed_feature_ref, feature_refs, full_feature_names + ) ][i], delta=0.0001, ) @@ -562,17 +561,17 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name missing_responses_dict = get_online_features_dict( environment=environment, features=feature_refs, - entity_rows=[ - {"driver": 0, "customer_id": 0, "val_to_add": 100, "driver_age": 125} - ], + entity_rows=[{"driver_id": 0, "customer_id": 0, "val_to_add": 100}], full_feature_names=full_feature_names, ) assert missing_responses_dict is not None for unprefixed_feature_ref in unprefixed_feature_refs: - if unprefixed_feature_ref not in {"num_rides", "avg_ride_length", "driver_age"}: + if unprefixed_feature_ref not in {"num_rides", "avg_ride_length"}: tc.assertIsNone( missing_responses_dict[ - response_feature_name(unprefixed_feature_ref, full_feature_names) + response_feature_name( + unprefixed_feature_ref, feature_refs, full_feature_names + ) ][0] ) @@ -581,16 +580,7 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name get_online_features_dict( environment=environment, features=feature_refs, - entity_rows=[{"driver": 0, "customer_id": 0}], - full_feature_names=full_feature_names, - ) - - # Also with request data - with pytest.raises(RequestDataNotFoundInEntityRowsException): - get_online_features_dict( - environment=environment, - features=feature_refs, - entity_rows=[{"driver": 0, "customer_id": 0, "val_to_add": 20}], + entity_rows=[{"driver_id": 0, "customer_id": 0}], full_feature_names=full_feature_names, ) @@ -606,13 +596,8 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name ) entity_rows = [ - { - "driver": driver, - "customer_id": customer, - "origin_id": origin, - "destination_id": destination, - } - for (driver, customer, origin, destination) in zip( + {"origin_id": origin, "destination_id": destination} + for (_driver, _customer, origin, destination) in zip( sample_drivers, sample_customers, *sample_location_pairs ) ] @@ -621,9 +606,6 @@ def test_online_retrieval(environment, universal_data_sources, full_feature_name feature_service_entity_mapping, entity_rows, full_feature_names, - drivers_df, - customers_df, - orders_df, origins_df, destinations_df, ) @@ -678,7 +660,7 @@ def test_online_store_cleanup(environment, universal_data_sources): expected_values = df.sort_values(by="driver_id") features = [f"{simple_driver_fv.name}:value"] - entity_rows = [{"driver": driver_id} for driver_id in sorted(driver_entities)] + entity_rows = [{"driver_id": driver_id} for driver_id in sorted(driver_entities)] online_features = fs.get_online_features( features=features, entity_rows=entity_rows @@ -714,27 +696,15 @@ def eventually_apply() -> Tuple[None, bool]: assert all(v is None for v in online_features["value"]) -def response_feature_name(feature: str, full_feature_names: bool) -> str: - if ( - feature in {"current_balance", "avg_passenger_count", "lifetime_trip_count"} - and full_feature_names - ): - return f"customer_profile__{feature}" +def response_feature_name( + feature: str, feature_refs: List[str], full_feature_names: bool +) -> str: + if not full_feature_names: + return feature - if feature in {"conv_rate", "avg_daily_trips"} and full_feature_names: - return f"driver_stats__{feature}" - - if ( - feature in {"conv_rate_plus_100", "conv_rate_plus_val_to_add"} - and full_feature_names - ): - return f"conv_rate_plus_100__{feature}" - - if feature in {"order_is_success"} and full_feature_names: - return f"order__{feature}" - - if feature in {"num_rides", "avg_ride_length"} and full_feature_names: - return f"global_stats__{feature}" + for feature_ref in feature_refs: + if feature_ref.endswith(feature): + return feature_ref.replace(":", "__") return feature @@ -753,7 +723,7 @@ def get_latest_feature_values_from_dataframes( origin_df=None, destination_df=None, ): - latest_driver_row = get_latest_row(entity_row, driver_df, "driver_id", "driver") + latest_driver_row = get_latest_row(entity_row, driver_df, "driver_id", "driver_id") latest_customer_row = get_latest_row( entity_row, customer_df, "customer_id", "customer_id" ) @@ -761,7 +731,7 @@ def get_latest_feature_values_from_dataframes( # Since the event timestamp columns may contain timestamps of different timezones, # we must first convert the timestamps to UTC before we can compare them. order_rows = orders_df[ - (orders_df["driver_id"] == entity_row["driver"]) + (orders_df["driver_id"] == entity_row["driver_id"]) & (orders_df["customer_id"] == entity_row["customer_id"]) ] timestamps = order_rows[["event_timestamp"]] @@ -776,19 +746,12 @@ def get_latest_feature_values_from_dataframes( global_df["event_timestamp"].idxmax() ].to_dict() if origin_df is not None: - latest_origin_row = get_latest_row( - entity_row, origin_df, "location_id", "origin_id" - ) - latest_destination_row = get_latest_row( - entity_row, destination_df, "location_id", "destination_id" - ) - # Need full feature names for shadow entities - latest_origin_row["origin__temperature"] = latest_origin_row.pop("temperature") - latest_destination_row["destination__temperature"] = latest_destination_row.pop( - "temperature" + latest_location_row = get_latest_feature_values_for_location_df( + entity_row, origin_df, destination_df ) + request_data_features = entity_row.copy() - request_data_features.pop("driver") + request_data_features.pop("driver_id") request_data_features.pop("customer_id") if global_df is not None: return { @@ -805,8 +768,7 @@ def get_latest_feature_values_from_dataframes( **latest_customer_row, **latest_driver_row, **latest_orders_row, - **latest_origin_row, - **latest_destination_row, + **latest_location_row, **request_data_features, } return { @@ -817,6 +779,25 @@ def get_latest_feature_values_from_dataframes( } +def get_latest_feature_values_for_location_df(entity_row, origin_df, destination_df): + latest_origin_row = get_latest_row( + entity_row, origin_df, "location_id", "origin_id" + ) + latest_destination_row = get_latest_row( + entity_row, destination_df, "location_id", "destination_id" + ) + # Need full feature names for shadow entities + latest_origin_row["origin__temperature"] = latest_origin_row.pop("temperature") + latest_destination_row["destination__temperature"] = latest_destination_row.pop( + "temperature" + ) + + return { + **latest_origin_row, + **latest_destination_row, + } + + def assert_feature_service_correctness( environment, feature_service, @@ -834,17 +815,17 @@ def assert_feature_service_correctness( full_feature_names=full_feature_names, ) feature_service_keys = feature_service_online_features_dict.keys() - - assert ( - len(feature_service_keys) - == sum( - [ - len(projection.features) - for projection in feature_service.feature_view_projections - ] - ) - + 2 - ) # Add two for the driver id and the customer id entity keys + expected_feature_refs = [ + f"{projection.name_to_use()}__{feature.name}" + if full_feature_names + else feature.name + for projection in feature_service.feature_view_projections + for feature in projection.features + ] + assert set(feature_service_keys) == set(expected_feature_refs) | { + "customer_id", + "driver_id", + } tc = unittest.TestCase() for i, entity_row in enumerate(entity_rows): @@ -857,7 +838,9 @@ def assert_feature_service_correctness( ) tc.assertAlmostEqual( feature_service_online_features_dict[ - response_feature_name("conv_rate_plus_100", full_feature_names) + response_feature_name( + "conv_rate_plus_100", expected_feature_refs, full_feature_names + ) ][i], df_features["conv_rate"] + 100, delta=0.0001, @@ -869,9 +852,6 @@ def assert_feature_service_entity_mapping_correctness( feature_service, entity_rows, full_feature_names, - drivers_df, - customers_df, - orders_df, origins_df, destinations_df, ): @@ -884,22 +864,20 @@ def assert_feature_service_entity_mapping_correctness( ) feature_service_keys = feature_service_online_features_dict.keys() - assert ( - len(feature_service_keys) - == sum( - [ - len(projection.features) - for projection in feature_service.feature_view_projections - ] - ) - + 4 - ) # Add 4 for the driver_id, customer_id, origin_id, and destination_id entity keys + expected_features = [ + f"{projection.name_to_use()}__{feature.name}" + if full_feature_names + else feature.name + for projection in feature_service.feature_view_projections + for feature in projection.features + ] + assert set(feature_service_keys) == set(expected_features) | { + "destination_id", + "origin_id", + } for i, entity_row in enumerate(entity_rows): - df_features = get_latest_feature_values_from_dataframes( - driver_df=drivers_df, - customer_df=customers_df, - orders_df=orders_df, + df_features = get_latest_feature_values_for_location_df( origin_df=origins_df, destination_df=destinations_df, entity_row=entity_row, diff --git a/sdk/python/tests/integration/registration/test_cli.py b/sdk/python/tests/integration/registration/test_cli.py index c79d672fb94..655e53e7593 100644 --- a/sdk/python/tests/integration/registration/test_cli.py +++ b/sdk/python/tests/integration/registration/test_cli.py @@ -84,12 +84,12 @@ def test_universal_cli(environment: Environment): cwd=repo_path, ) assertpy.assert_that(result.returncode).is_equal_to(0) - assertpy.assert_that(fs.list_feature_views()).is_length(3) + assertpy.assert_that(fs.list_feature_views()).is_length(4) result = runner.run( ["data-sources", "describe", "customer_profile_source"], cwd=repo_path, ) assertpy.assert_that(result.returncode).is_equal_to(0) - assertpy.assert_that(fs.list_data_sources()).is_length(3) + assertpy.assert_that(fs.list_data_sources()).is_length(4) # entity & feature view describe commands should fail when objects don't exist result = runner.run(["entities", "describe", "foo"], cwd=repo_path) diff --git a/sdk/python/tests/integration/registration/test_feature_store.py b/sdk/python/tests/integration/registration/test_feature_store.py index d5496a6de75..39de7fc6888 100644 --- a/sdk/python/tests/integration/registration/test_feature_store.py +++ b/sdk/python/tests/integration/registration/test_feature_store.py @@ -21,19 +21,20 @@ from feast import FileSource from feast.data_format import ParquetFormat from feast.entity import Entity -from feast.feature import Feature from feast.feature_store import FeatureStore from feast.feature_view import FeatureView +from feast.field import Field from feast.infra.offline_stores.file import FileOfflineStoreConfig from feast.infra.online_stores.dynamodb import DynamoDBOnlineStoreConfig from feast.infra.online_stores.sqlite import SqliteOnlineStoreConfig from feast.protos.feast.types import Value_pb2 as ValueProto from feast.repo_config import RepoConfig +from feast.types import Array, Bytes, Float64, Int64, String from feast.value_type import ValueType from tests.utils.data_source_utils import ( prep_file_source, simple_bq_source_using_query_arg, - simple_bq_source_using_table_ref_arg, + simple_bq_source_using_table_arg, ) @@ -167,18 +168,18 @@ def test_apply_feature_view_success(test_feature_store): batch_source = FileSource( file_format=ParquetFormat(), path="file://feast/*", - event_timestamp_column="ts_col", + timestamp_field="ts_col", created_timestamp_column="timestamp", date_partition_column="date_partition_col", ) fv1 = FeatureView( name="my_feature_view_1", - features=[ - Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), - Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), - Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), - Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + schema=[ + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + Field(name="fs1_my_feature_4", dtype=Array(Bytes)), ], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, @@ -196,13 +197,13 @@ def test_apply_feature_view_success(test_feature_store): len(feature_views) == 1 and feature_views[0].name == "my_feature_view_1" and feature_views[0].features[0].name == "fs1_my_feature_1" - and feature_views[0].features[0].dtype == ValueType.INT64 + and feature_views[0].features[0].dtype == Int64 and feature_views[0].features[1].name == "fs1_my_feature_2" - and feature_views[0].features[1].dtype == ValueType.STRING + and feature_views[0].features[1].dtype == String and feature_views[0].features[2].name == "fs1_my_feature_3" - and feature_views[0].features[2].dtype == ValueType.STRING_LIST + and feature_views[0].features[2].dtype == Array(String) and feature_views[0].features[3].name == "fs1_my_feature_4" - and feature_views[0].features[3].dtype == ValueType.BYTES_LIST + and feature_views[0].features[3].dtype == Array(Bytes) and feature_views[0].entities[0] == "fs1_my_entity_1" ) @@ -234,7 +235,7 @@ def test_feature_view_inference_success(test_feature_store, dataframe_source): entities=["id"], ttl=timedelta(minutes=5), online=True, - batch_source=simple_bq_source_using_table_ref_arg(dataframe_source, "ts_1"), + batch_source=simple_bq_source_using_table_arg(dataframe_source, "ts_1"), tags={}, ) @@ -255,22 +256,22 @@ def test_feature_view_inference_success(test_feature_store, dataframe_source): actual_file_source = { (feature.name, feature.dtype) for feature in feature_view_1.features } - actual_bq_using_table_ref_arg_source = { + actual_bq_using_table_arg_source = { (feature.name, feature.dtype) for feature in feature_view_2.features } actual_bq_using_query_arg_source = { (feature.name, feature.dtype) for feature in feature_view_3.features } expected = { - ("float_col", ValueType.DOUBLE), - ("int64_col", ValueType.INT64), - ("string_col", ValueType.STRING), + ("float_col", Float64), + ("int64_col", Int64), + ("string_col", String), } assert ( expected == actual_file_source - == actual_bq_using_table_ref_arg_source + == actual_bq_using_table_arg_source == actual_bq_using_query_arg_source ) @@ -290,18 +291,18 @@ def test_apply_feature_view_integration(test_feature_store): batch_source = FileSource( file_format=ParquetFormat(), path="file://feast/*", - event_timestamp_column="ts_col", + timestamp_field="ts_col", created_timestamp_column="timestamp", date_partition_column="date_partition_col", ) fv1 = FeatureView( name="my_feature_view_1", - features=[ - Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), - Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), - Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), - Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + schema=[ + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + Field(name="fs1_my_feature_4", dtype=Array(Bytes)), ], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, @@ -319,13 +320,13 @@ def test_apply_feature_view_integration(test_feature_store): len(feature_views) == 1 and feature_views[0].name == "my_feature_view_1" and feature_views[0].features[0].name == "fs1_my_feature_1" - and feature_views[0].features[0].dtype == ValueType.INT64 + and feature_views[0].features[0].dtype == Int64 and feature_views[0].features[1].name == "fs1_my_feature_2" - and feature_views[0].features[1].dtype == ValueType.STRING + and feature_views[0].features[1].dtype == String and feature_views[0].features[2].name == "fs1_my_feature_3" - and feature_views[0].features[2].dtype == ValueType.STRING_LIST + and feature_views[0].features[2].dtype == Array(String) and feature_views[0].features[3].name == "fs1_my_feature_4" - and feature_views[0].features[3].dtype == ValueType.BYTES_LIST + and feature_views[0].features[3].dtype == Array(Bytes) and feature_views[0].entities[0] == "fs1_my_entity_1" ) @@ -333,13 +334,13 @@ def test_apply_feature_view_integration(test_feature_store): assert ( feature_view.name == "my_feature_view_1" and feature_view.features[0].name == "fs1_my_feature_1" - and feature_view.features[0].dtype == ValueType.INT64 + and feature_view.features[0].dtype == Int64 and feature_view.features[1].name == "fs1_my_feature_2" - and feature_view.features[1].dtype == ValueType.STRING + and feature_view.features[1].dtype == String and feature_view.features[2].name == "fs1_my_feature_3" - and feature_view.features[2].dtype == ValueType.STRING_LIST + and feature_view.features[2].dtype == Array(String) and feature_view.features[3].name == "fs1_my_feature_4" - and feature_view.features[3].dtype == ValueType.BYTES_LIST + and feature_view.features[3].dtype == Array(Bytes) and feature_view.entities[0] == "fs1_my_entity_1" ) @@ -359,7 +360,7 @@ def test_apply_object_and_read(test_feature_store): batch_source = FileSource( file_format=ParquetFormat(), path="file://feast/*", - event_timestamp_column="ts_col", + timestamp_field="ts_col", created_timestamp_column="timestamp", ) @@ -373,11 +374,11 @@ def test_apply_object_and_read(test_feature_store): fv1 = FeatureView( name="my_feature_view_1", - features=[ - Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), - Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), - Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), - Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + schema=[ + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + Field(name="fs1_my_feature_4", dtype=Array(Bytes)), ], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, @@ -387,11 +388,11 @@ def test_apply_object_and_read(test_feature_store): fv2 = FeatureView( name="my_feature_view_2", - features=[ - Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), - Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), - Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), - Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + schema=[ + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + Field(name="fs1_my_feature_4", dtype=Array(Bytes)), ], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, @@ -440,7 +441,7 @@ def test_reapply_feature_view_success(test_feature_store, dataframe_source): # Create Feature View fv1 = FeatureView( name="my_feature_view_1", - features=[Feature(name="string_col", dtype=ValueType.STRING)], + schema=[Field(name="string_col", dtype=String)], entities=["id"], batch_source=file_source, ttl=timedelta(minutes=5), @@ -470,7 +471,7 @@ def test_reapply_feature_view_success(test_feature_store, dataframe_source): # Change and apply Feature View fv1 = FeatureView( name="my_feature_view_1", - features=[Feature(name="int64_col", dtype=ValueType.INT64)], + schema=[Field(name="int64_col", dtype=Int64)], entities=["id"], batch_source=file_source, ttl=timedelta(minutes=5), @@ -485,7 +486,7 @@ def test_reapply_feature_view_success(test_feature_store, dataframe_source): def test_apply_conflicting_featureview_names(feature_store_with_local_registry): - """ Test applying feature views with non-case-insensitively unique names""" + """Test applying feature views with non-case-insensitively unique names""" driver_stats = FeatureView( name="driver_hourly_stats", diff --git a/sdk/python/tests/integration/registration/test_inference.py b/sdk/python/tests/integration/registration/test_inference.py index c334013b51e..526f422e9d6 100644 --- a/sdk/python/tests/integration/registration/test_inference.py +++ b/sdk/python/tests/integration/registration/test_inference.py @@ -1,3 +1,5 @@ +from copy import deepcopy + import pandas as pd import pytest @@ -11,22 +13,27 @@ SnowflakeSource, ValueType, ) -from feast.data_source import RequestDataSource +from feast.data_source import RequestSource from feast.errors import ( DataSourceNoNameException, RegistryInferenceFailure, SpecifiedFeaturesNotPresentError, ) from feast.feature_view import FeatureView +from feast.field import Field from feast.inference import ( update_data_sources_with_inferred_event_timestamp_col, update_entities_with_inferred_types_from_feature_views, ) +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import ( + SparkSource, +) from feast.on_demand_feature_view import on_demand_feature_view +from feast.types import PrimitiveFeastType, String, UnixTimestamp from tests.utils.data_source_utils import ( prep_file_source, simple_bq_source_using_query_arg, - simple_bq_source_using_table_ref_arg, + simple_bq_source_using_table_arg, ) @@ -83,7 +90,7 @@ def test_infer_datasource_names_file(): def test_infer_datasource_names_dwh(): table = "project.table" - dwh_classes = [BigQuerySource, RedshiftSource, SnowflakeSource] + dwh_classes = [BigQuerySource, RedshiftSource, SnowflakeSource, SparkSource] for dwh_class in dwh_classes: data_source = dwh_class(table=table) @@ -98,50 +105,78 @@ def test_infer_datasource_names_dwh(): assert data_source_with_query.name == source_name # If we have a query and no name, throw an error - with pytest.raises(DataSourceNoNameException): - print(f"Testing dwh {dwh_class}") + if dwh_class == SparkSource: + with pytest.raises(DataSourceNoNameException): + print(f"Testing dwh {dwh_class}") + data_source = dwh_class(query="test_query") + else: data_source = dwh_class(query="test_query") + assert data_source.name == "" @pytest.mark.integration -def test_update_data_sources_with_inferred_event_timestamp_col(simple_dataset_1): +def test_update_file_data_source_with_inferred_event_timestamp_col(simple_dataset_1): df_with_two_viable_timestamp_cols = simple_dataset_1.copy(deep=True) df_with_two_viable_timestamp_cols["ts_2"] = simple_dataset_1["ts_1"] with prep_file_source(df=simple_dataset_1) as file_source: data_sources = [ file_source, - simple_bq_source_using_table_ref_arg(simple_dataset_1), + simple_bq_source_using_table_arg(simple_dataset_1), simple_bq_source_using_query_arg(simple_dataset_1), ] update_data_sources_with_inferred_event_timestamp_col( data_sources, RepoConfig(provider="local", project="test") ) actual_event_timestamp_cols = [ - source.event_timestamp_column for source in data_sources + source.timestamp_field for source in data_sources ] assert actual_event_timestamp_cols == ["ts_1", "ts_1", "ts_1"] with prep_file_source(df=df_with_two_viable_timestamp_cols) as file_source: with pytest.raises(RegistryInferenceFailure): - # two viable event_timestamp_columns + # two viable timestamp_fields update_data_sources_with_inferred_event_timestamp_col( [file_source], RepoConfig(provider="local", project="test") ) +@pytest.mark.integration +@pytest.mark.universal +def test_update_data_sources_with_inferred_event_timestamp_col(universal_data_sources): + (_, _, data_sources) = universal_data_sources + data_sources_copy = deepcopy(data_sources) + + # remove defined timestamp_field to allow for inference + for data_source in data_sources_copy.values(): + data_source.timestamp_field = None + data_source.event_timestamp_column = None + + update_data_sources_with_inferred_event_timestamp_col( + data_sources_copy.values(), RepoConfig(provider="local", project="test"), + ) + actual_event_timestamp_cols = [ + source.timestamp_field for source in data_sources_copy.values() + ] + + assert actual_event_timestamp_cols == ["event_timestamp"] * len( + data_sources_copy.values() + ) + + def test_on_demand_features_type_inference(): # Create Feature Views - date_request = RequestDataSource( - name="date_request", schema={"some_date": ValueType.UNIX_TIMESTAMP} + date_request = RequestSource( + name="date_request", + schema=[Field(name="some_date", dtype=PrimitiveFeastType.UNIX_TIMESTAMP)], ) @on_demand_feature_view( - inputs={"date_request": date_request}, + sources={"date_request": date_request}, features=[ - Feature("output", ValueType.UNIX_TIMESTAMP), - Feature("string_output", ValueType.STRING), + Feature(name="output", dtype=ValueType.UNIX_TIMESTAMP), + Feature(name="string_output", dtype=ValueType.STRING), ], ) def test_view(features_df: pd.DataFrame) -> pd.DataFrame: @@ -153,10 +188,13 @@ def test_view(features_df: pd.DataFrame) -> pd.DataFrame: test_view.infer_features() @on_demand_feature_view( + # Note: we deliberately use `inputs` instead of `sources` to test that `inputs` + # still works correctly, even though it is deprecated. + # TODO(felixwang9817): Remove references to `inputs` once it is fully deprecated. inputs={"date_request": date_request}, features=[ - Feature("output", ValueType.UNIX_TIMESTAMP), - Feature("object_output", ValueType.STRING), + Feature(name="output", dtype=ValueType.UNIX_TIMESTAMP), + Feature(name="object_output", dtype=ValueType.STRING), ], ) def invalid_test_view(features_df: pd.DataFrame) -> pd.DataFrame: @@ -169,11 +207,14 @@ def invalid_test_view(features_df: pd.DataFrame) -> pd.DataFrame: invalid_test_view.infer_features() @on_demand_feature_view( - inputs={"date_request": date_request}, - features=[ - Feature("output", ValueType.UNIX_TIMESTAMP), - Feature("missing", ValueType.STRING), + # Note: we deliberately use positional arguments here to test that they work correctly, + # even though positional arguments are deprecated in favor of keyword arguments. + # TODO(felixwang9817): Remove positional arguments once they are fully deprecated. + [ + Feature(name="output", dtype=ValueType.UNIX_TIMESTAMP), + Feature(name="missing", dtype=ValueType.STRING), ], + {"date_request": date_request}, ) def test_view_with_missing_feature(features_df: pd.DataFrame) -> pd.DataFrame: data = pd.DataFrame() @@ -184,18 +225,27 @@ def test_view_with_missing_feature(features_df: pd.DataFrame) -> pd.DataFrame: test_view_with_missing_feature.infer_features() -def test_datasource_inference(): +# TODO(kevjumba): remove this in feast 0.23 when deprecating +@pytest.mark.parametrize( + "request_source_schema", + [ + [Field(name="some_date", dtype=PrimitiveFeastType.UNIX_TIMESTAMP)], + {"some_date": ValueType.UNIX_TIMESTAMP}, + ], +) +def test_datasource_inference(request_source_schema): # Create Feature Views - date_request = RequestDataSource( - name="date_request", schema={"some_date": ValueType.UNIX_TIMESTAMP} - ) + date_request = RequestSource(name="date_request", schema=request_source_schema,) @on_demand_feature_view( - inputs={"date_request": date_request}, - features=[ - Feature("output", ValueType.UNIX_TIMESTAMP), - Feature("string_output", ValueType.STRING), + # Note: we deliberately use positional arguments here to test that they work correctly, + # even though positional arguments are deprecated in favor of keyword arguments. + # TODO(felixwang9817): Remove positional arguments once they are fully deprecated. + [ + Feature(name="output", dtype=ValueType.UNIX_TIMESTAMP), + Feature(name="string_output", dtype=ValueType.STRING), ], + sources={"date_request": date_request}, ) def test_view(features_df: pd.DataFrame) -> pd.DataFrame: data = pd.DataFrame() @@ -206,10 +256,10 @@ def test_view(features_df: pd.DataFrame) -> pd.DataFrame: test_view.infer_features() @on_demand_feature_view( - inputs={"date_request": date_request}, - features=[ - Feature("output", ValueType.UNIX_TIMESTAMP), - Feature("object_output", ValueType.STRING), + sources={"date_request": date_request}, + schema=[ + Field(name="output", dtype=UnixTimestamp), + Field(name="object_output", dtype=String), ], ) def invalid_test_view(features_df: pd.DataFrame) -> pd.DataFrame: @@ -222,10 +272,10 @@ def invalid_test_view(features_df: pd.DataFrame) -> pd.DataFrame: invalid_test_view.infer_features() @on_demand_feature_view( - inputs={"date_request": date_request}, + sources={"date_request": date_request}, features=[ - Feature("output", ValueType.UNIX_TIMESTAMP), - Feature("missing", ValueType.STRING), + Feature(name="output", dtype=ValueType.UNIX_TIMESTAMP), + Feature(name="missing", dtype=ValueType.STRING), ], ) def test_view_with_missing_feature(features_df: pd.DataFrame) -> pd.DataFrame: diff --git a/sdk/python/tests/integration/registration/test_registry.py b/sdk/python/tests/integration/registration/test_registry.py index 535497634d4..072be15bfee 100644 --- a/sdk/python/tests/integration/registration/test_registry.py +++ b/sdk/python/tests/integration/registration/test_registry.py @@ -24,10 +24,12 @@ from feast.entity import Entity from feast.feature import Feature from feast.feature_view import FeatureView -from feast.on_demand_feature_view import RequestDataSource, on_demand_feature_view +from feast.field import Field +from feast.on_demand_feature_view import RequestSource, on_demand_feature_view from feast.protos.feast.types import Value_pb2 as ValueProto from feast.registry import Registry from feast.repo_config import RegistryConfig +from feast.types import Array, Bytes, Float32, Int32, Int64, PrimitiveFeastType, String from feast.value_type import ValueType @@ -167,18 +169,17 @@ def test_apply_feature_view_success(test_registry): batch_source = FileSource( file_format=ParquetFormat(), path="file://feast/*", - event_timestamp_column="ts_col", + timestamp_field="ts_col", created_timestamp_column="timestamp", - date_partition_column="date_partition_col", ) fv1 = FeatureView( name="my_feature_view_1", - features=[ - Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), - Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), - Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), - Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + schema=[ + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + Field(name="fs1_my_feature_4", dtype=Array(Bytes)), ], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, @@ -198,13 +199,13 @@ def test_apply_feature_view_success(test_registry): len(feature_views) == 1 and feature_views[0].name == "my_feature_view_1" and feature_views[0].features[0].name == "fs1_my_feature_1" - and feature_views[0].features[0].dtype == ValueType.INT64 + and feature_views[0].features[0].dtype == Int64 and feature_views[0].features[1].name == "fs1_my_feature_2" - and feature_views[0].features[1].dtype == ValueType.STRING + and feature_views[0].features[1].dtype == String and feature_views[0].features[2].name == "fs1_my_feature_3" - and feature_views[0].features[2].dtype == ValueType.STRING_LIST + and feature_views[0].features[2].dtype == Array(String) and feature_views[0].features[3].name == "fs1_my_feature_4" - and feature_views[0].features[3].dtype == ValueType.BYTES_LIST + and feature_views[0].features[3].dtype == Array(Bytes) and feature_views[0].entities[0] == "fs1_my_entity_1" ) @@ -212,13 +213,13 @@ def test_apply_feature_view_success(test_registry): assert ( feature_view.name == "my_feature_view_1" and feature_view.features[0].name == "fs1_my_feature_1" - and feature_view.features[0].dtype == ValueType.INT64 + and feature_view.features[0].dtype == Int64 and feature_view.features[1].name == "fs1_my_feature_2" - and feature_view.features[1].dtype == ValueType.STRING + and feature_view.features[1].dtype == String and feature_view.features[2].name == "fs1_my_feature_3" - and feature_view.features[2].dtype == ValueType.STRING_LIST + and feature_view.features[2].dtype == Array(String) and feature_view.features[3].name == "fs1_my_feature_4" - and feature_view.features[3].dtype == ValueType.BYTES_LIST + and feature_view.features[3].dtype == Array(Bytes) and feature_view.entities[0] == "fs1_my_entity_1" ) @@ -236,23 +237,28 @@ def test_apply_feature_view_success(test_registry): @pytest.mark.parametrize( "test_registry", [lazy_fixture("local_registry")], ) -def test_modify_feature_views_success(test_registry): +# TODO(kevjumba): remove this in feast 0.23 when deprecating +@pytest.mark.parametrize( + "request_source_schema", + [ + [Field(name="my_input_1", dtype=PrimitiveFeastType.INT32)], + {"my_input_1": ValueType.INT32}, + ], +) +def test_modify_feature_views_success(test_registry, request_source_schema): # Create Feature Views batch_source = FileSource( file_format=ParquetFormat(), path="file://feast/*", - event_timestamp_column="ts_col", + timestamp_field="ts_col", created_timestamp_column="timestamp", - date_partition_column="date_partition_col", ) - request_source = RequestDataSource( - name="request_source", schema={"my_input_1": ValueType.INT32} - ) + request_source = RequestSource(name="request_source", schema=request_source_schema,) fv1 = FeatureView( name="my_feature_view_1", - features=[Feature(name="fs1_my_feature_1", dtype=ValueType.INT64)], + schema=[Field(name="fs1_my_feature_1", dtype=Int64)], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, batch_source=batch_source, @@ -264,7 +270,7 @@ def test_modify_feature_views_success(test_registry): Feature(name="odfv1_my_feature_1", dtype=ValueType.STRING), Feature(name="odfv1_my_feature_2", dtype=ValueType.INT32), ], - inputs={"request_source": request_source}, + sources={"request_source": request_source}, ) def odfv1(feature_df: pd.DataFrame) -> pd.DataFrame: data = pd.DataFrame() @@ -284,7 +290,7 @@ def odfv1(feature_df: pd.DataFrame) -> pd.DataFrame: Feature(name="odfv1_my_feature_1", dtype=ValueType.FLOAT), Feature(name="odfv1_my_feature_2", dtype=ValueType.INT32), ], - inputs={"request_source": request_source}, + sources={"request_source": request_source}, ) def odfv1(feature_df: pd.DataFrame) -> pd.DataFrame: data = pd.DataFrame() @@ -302,9 +308,9 @@ def odfv1(feature_df: pd.DataFrame) -> pd.DataFrame: len(on_demand_feature_views) == 1 and on_demand_feature_views[0].name == "odfv1" and on_demand_feature_views[0].features[0].name == "odfv1_my_feature_1" - and on_demand_feature_views[0].features[0].dtype == ValueType.FLOAT + and on_demand_feature_views[0].features[0].dtype == Float32 and on_demand_feature_views[0].features[1].name == "odfv1_my_feature_2" - and on_demand_feature_views[0].features[1].dtype == ValueType.INT32 + and on_demand_feature_views[0].features[1].dtype == Int32 ) request_schema = on_demand_feature_views[0].get_request_data_schema() assert ( @@ -316,9 +322,9 @@ def odfv1(feature_df: pd.DataFrame) -> pd.DataFrame: assert ( feature_view.name == "odfv1" and feature_view.features[0].name == "odfv1_my_feature_1" - and feature_view.features[0].dtype == ValueType.FLOAT + and feature_view.features[0].dtype == Float32 and feature_view.features[1].name == "odfv1_my_feature_2" - and feature_view.features[1].dtype == ValueType.INT32 + and feature_view.features[1].dtype == Int32 ) request_schema = feature_view.get_request_data_schema() assert ( @@ -334,7 +340,7 @@ def odfv1(feature_df: pd.DataFrame) -> pd.DataFrame: len(feature_views) == 1 and feature_views[0].name == "my_feature_view_1" and feature_views[0].features[0].name == "fs1_my_feature_1" - and feature_views[0].features[0].dtype == ValueType.INT64 + and feature_views[0].features[0].dtype == Int64 and feature_views[0].entities[0] == "fs1_my_entity_1" ) @@ -342,7 +348,7 @@ def odfv1(feature_df: pd.DataFrame) -> pd.DataFrame: assert ( feature_view.name == "my_feature_view_1" and feature_view.features[0].name == "fs1_my_feature_1" - and feature_view.features[0].dtype == ValueType.INT64 + and feature_view.features[0].dtype == Int64 and feature_view.entities[0] == "fs1_my_entity_1" ) @@ -362,18 +368,17 @@ def test_apply_feature_view_integration(test_registry): batch_source = FileSource( file_format=ParquetFormat(), path="file://feast/*", - event_timestamp_column="ts_col", + timestamp_field="ts_col", created_timestamp_column="timestamp", - date_partition_column="date_partition_col", ) fv1 = FeatureView( name="my_feature_view_1", - features=[ - Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), - Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), - Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), - Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + schema=[ + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + Field(name="fs1_my_feature_4", dtype=Array(Bytes)), ], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, @@ -393,13 +398,13 @@ def test_apply_feature_view_integration(test_registry): len(feature_views) == 1 and feature_views[0].name == "my_feature_view_1" and feature_views[0].features[0].name == "fs1_my_feature_1" - and feature_views[0].features[0].dtype == ValueType.INT64 + and feature_views[0].features[0].dtype == Int64 and feature_views[0].features[1].name == "fs1_my_feature_2" - and feature_views[0].features[1].dtype == ValueType.STRING + and feature_views[0].features[1].dtype == String and feature_views[0].features[2].name == "fs1_my_feature_3" - and feature_views[0].features[2].dtype == ValueType.STRING_LIST + and feature_views[0].features[2].dtype == Array(String) and feature_views[0].features[3].name == "fs1_my_feature_4" - and feature_views[0].features[3].dtype == ValueType.BYTES_LIST + and feature_views[0].features[3].dtype == Array(Bytes) and feature_views[0].entities[0] == "fs1_my_entity_1" ) @@ -407,13 +412,13 @@ def test_apply_feature_view_integration(test_registry): assert ( feature_view.name == "my_feature_view_1" and feature_view.features[0].name == "fs1_my_feature_1" - and feature_view.features[0].dtype == ValueType.INT64 + and feature_view.features[0].dtype == Int64 and feature_view.features[1].name == "fs1_my_feature_2" - and feature_view.features[1].dtype == ValueType.STRING + and feature_view.features[1].dtype == String and feature_view.features[2].name == "fs1_my_feature_3" - and feature_view.features[2].dtype == ValueType.STRING_LIST + and feature_view.features[2].dtype == Array(String) and feature_view.features[3].name == "fs1_my_feature_4" - and feature_view.features[3].dtype == ValueType.BYTES_LIST + and feature_view.features[3].dtype == Array(Bytes) and feature_view.entities[0] == "fs1_my_entity_1" ) @@ -438,18 +443,17 @@ def test_apply_data_source(test_registry: Registry): name="test_source", file_format=ParquetFormat(), path="file://feast/*", - event_timestamp_column="ts_col", + timestamp_field="ts_col", created_timestamp_column="timestamp", - date_partition_column="date_partition_col", ) fv1 = FeatureView( name="my_feature_view_1", - features=[ - Feature(name="fs1_my_feature_1", dtype=ValueType.INT64), - Feature(name="fs1_my_feature_2", dtype=ValueType.STRING), - Feature(name="fs1_my_feature_3", dtype=ValueType.STRING_LIST), - Feature(name="fs1_my_feature_4", dtype=ValueType.BYTES_LIST), + schema=[ + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + Field(name="fs1_my_feature_4", dtype=Array(Bytes)), ], entities=["fs1_my_entity_1"], tags={"team": "matchmaking"}, @@ -473,7 +477,7 @@ def test_apply_data_source(test_registry: Registry): assert registry_data_source == batch_source # Check that change to batch source propagates - batch_source.event_timestamp_column = "new_ts_col" + batch_source.timestamp_field = "new_ts_col" test_registry.apply_data_source(batch_source, project, commit=False) test_registry.apply_feature_view(fv1, project, commit=True) registry_feature_views = test_registry.list_feature_views(project) diff --git a/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py b/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py index e8cc1552e2a..9dced8f13ad 100644 --- a/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py +++ b/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py @@ -3,16 +3,17 @@ import pandas as pd import pytest -from feast import Feature, ValueType +from feast import Field from feast.errors import SpecifiedFeaturesNotPresentError from feast.infra.offline_stores.file_source import FileSource +from feast.types import Float64 from tests.integration.feature_repos.universal.entities import customer, driver, item from tests.integration.feature_repos.universal.feature_views import ( conv_rate_plus_100_feature_view, - create_conv_rate_request_data_source, + create_conv_rate_request_source, create_driver_hourly_stats_feature_view, create_item_embeddings_feature_view, - create_similarity_request_data_source, + create_similarity_request_source, similarity_feature_view, ) @@ -26,9 +27,9 @@ def test_infer_odfv_features(environment, universal_data_sources, infer_features (entities, datasets, data_sources) = universal_data_sources driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) - request_data_source = create_conv_rate_request_data_source() + request_source = create_conv_rate_request_source() driver_odfv = conv_rate_plus_100_feature_view( - {"driver": driver_hourly_stats, "input_request": request_data_source}, + {"driver": driver_hourly_stats, "input_request": request_source}, infer_features=infer_features, ) @@ -55,12 +56,12 @@ def test_infer_odfv_list_features(environment, infer_features, tmp_path): items_df.to_parquet(output_path) fake_items_src = FileSource( path=output_path, - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) items = create_item_embeddings_feature_view(fake_items_src) sim_odfv = similarity_feature_view( - {"items": items, "input_request": create_similarity_request_data_source()}, + {"items": items, "input_request": create_similarity_request_source()}, infer_features=infer_features, ) store = environment.feature_store @@ -76,11 +77,11 @@ def test_infer_odfv_features_with_error(environment, universal_data_sources): (entities, datasets, data_sources) = universal_data_sources - features = [Feature("conv_rate_plus_200", ValueType.DOUBLE)] + features = [Field(name="conv_rate_plus_200", dtype=Float64)] driver_hourly_stats = create_driver_hourly_stats_feature_view(data_sources.driver) - request_data_source = create_conv_rate_request_data_source() + request_source = create_conv_rate_request_source() driver_odfv = conv_rate_plus_100_feature_view( - {"driver": driver_hourly_stats, "input_request": request_data_source}, + {"driver": driver_hourly_stats, "input_request": request_source}, features=features, ) diff --git a/sdk/python/tests/integration/registration/test_universal_types.py b/sdk/python/tests/integration/registration/test_universal_types.py index 59ca119f98a..81fa0200fdd 100644 --- a/sdk/python/tests/integration/registration/test_universal_types.py +++ b/sdk/python/tests/integration/registration/test_universal_types.py @@ -9,6 +9,7 @@ import pytest from feast.infra.offline_stores.offline_store import RetrievalJob +from feast.types import Array, Bool, Float32, Int32, Int64, UnixTimestamp from feast.value_type import ValueType from tests.data.data_creator import create_dataset from tests.integration.feature_repos.repo_configuration import ( @@ -158,8 +159,14 @@ def test_entity_inference_types_match(offline_types_test_fixtures): @pytest.mark.integration @pytest.mark.universal def test_feature_get_historical_features_types_match(offline_types_test_fixtures): + """ + Note: to make sure this test works, we need to ensure that get_historical_features + returns at least one non-null row to make sure type inferral works. This can only + be achieved by carefully matching entity_df to the data fixtures. + """ environment, config, data_source, fv = offline_types_test_fixtures fs = environment.feature_store + entity = driver() fv = create_feature_view( "get_historical_features_types_match", config.feature_dtype, @@ -167,20 +174,19 @@ def test_feature_get_historical_features_types_match(offline_types_test_fixtures config.has_empty_list, data_source, ) - entity = driver() fs.apply([fv, entity]) - features = [f"{fv.name}:value"] entity_df = pd.DataFrame() entity_df["driver_id"] = ( ["1", "3"] if config.entity_type == ValueType.STRING else [1, 3] ) - now = datetime.utcnow() - ts = pd.Timestamp(now).round("ms") + ts = pd.Timestamp(datetime.utcnow()).round("ms") entity_df["ts"] = [ ts - timedelta(hours=4), ts - timedelta(hours=2), ] + features = [f"{fv.name}:value"] + historical_features = fs.get_historical_features( entity_df=entity_df, features=features, ) @@ -230,7 +236,7 @@ def test_feature_get_online_features_types_match(online_types_test_fixtures): driver_id_value = "1" if config.entity_type == ValueType.STRING else 1 online_features = fs.get_online_features( - features=features, entity_rows=[{"driver": driver_id_value}], + features=features, entity_rows=[{"driver_id": driver_id_value}], ).to_dict() feature_list_dtype_to_expected_online_response_value_type = { @@ -265,28 +271,28 @@ def create_feature_view( ): if feature_is_list is True: if feature_dtype == "int32": - value_type = ValueType.INT32_LIST + dtype = Array(Int32) elif feature_dtype == "int64": - value_type = ValueType.INT64_LIST + dtype = Array(Int64) elif feature_dtype == "float": - value_type = ValueType.FLOAT_LIST + dtype = Array(Float32) elif feature_dtype == "bool": - value_type = ValueType.BOOL_LIST + dtype = Array(Bool) elif feature_dtype == "datetime": - value_type = ValueType.UNIX_TIMESTAMP_LIST + dtype = Array(UnixTimestamp) else: if feature_dtype == "int32": - value_type = ValueType.INT32 + dtype = Int32 elif feature_dtype == "int64": - value_type = ValueType.INT64 + dtype = Int64 elif feature_dtype == "float": - value_type = ValueType.FLOAT + dtype = Float32 elif feature_dtype == "bool": - value_type = ValueType.BOOL + dtype = Bool elif feature_dtype == "datetime": - value_type = ValueType.UNIX_TIMESTAMP + dtype = UnixTimestamp - return driver_feature_view(data_source, name=name, value_type=value_type,) + return driver_feature_view(data_source, name=name, dtype=dtype,) def assert_expected_historical_feature_types( @@ -328,7 +334,7 @@ def assert_feature_list_types( bool, np.bool_, ), # Can be `np.bool_` if from `np.array` rather that `list` - "datetime": np.datetime64, + "datetime": (np.datetime64, datetime,), # datetime.datetime } expected_dtype = feature_list_dtype_to_expected_historical_feature_list_dtype[ feature_dtype diff --git a/sdk/python/tests/integration/scaffolding/test_partial_apply.py b/sdk/python/tests/integration/scaffolding/test_partial_apply.py index bfd078c7daa..3ab9bf196f2 100644 --- a/sdk/python/tests/integration/scaffolding/test_partial_apply.py +++ b/sdk/python/tests/integration/scaffolding/test_partial_apply.py @@ -1,7 +1,9 @@ +from datetime import timedelta + import pytest -from google.protobuf.duration_pb2 import Duration -from feast import BigQuerySource, Feature, FeatureView, ValueType +from feast import BigQuerySource, FeatureView, Field +from feast.types import Float32, String from tests.utils.cli_utils import CliRunner, get_example_repo from tests.utils.online_read_write_test import basic_rw_test @@ -19,19 +21,19 @@ def test_partial() -> None: ) as store: driver_locations_source = BigQuerySource( - table_ref="feast-oss.public.drivers", - event_timestamp_column="event_timestamp", + table="feast-oss.public.drivers", + timestamp_field="event_timestamp", created_timestamp_column="created_timestamp", ) driver_locations_100 = FeatureView( name="driver_locations_100", entities=["driver"], - ttl=Duration(seconds=86400 * 1), - features=[ - Feature(name="lat", dtype=ValueType.FLOAT), - Feature(name="lon", dtype=ValueType.STRING), - Feature(name="name", dtype=ValueType.STRING), + ttl=timedelta(days=1), + schema=[ + Field(name="lat", dtype=Float32), + Field(name="lon", dtype=String), + Field(name="name", dtype=String), ], online=True, batch_source=driver_locations_source, diff --git a/sdk/python/tests/unit/infra/online_store/test_dynamodb_online_store.py b/sdk/python/tests/unit/infra/online_store/test_dynamodb_online_store.py new file mode 100644 index 00000000000..7d6da0dc06d --- /dev/null +++ b/sdk/python/tests/unit/infra/online_store/test_dynamodb_online_store.py @@ -0,0 +1,196 @@ +from copy import deepcopy +from dataclasses import dataclass + +import boto3 +import pytest +from moto import mock_dynamodb2 + +from feast.infra.offline_stores.file import FileOfflineStoreConfig +from feast.infra.online_stores.dynamodb import ( + DynamoDBOnlineStore, + DynamoDBOnlineStoreConfig, + DynamoDBTable, +) +from feast.repo_config import RepoConfig +from tests.utils.online_store_utils import ( + _create_n_customer_test_samples, + _create_test_table, + _insert_data_test_table, +) + +REGISTRY = "s3://test_registry/registry.db" +PROJECT = "test_aws" +PROVIDER = "aws" +TABLE_NAME = "dynamodb_online_store" +REGION = "us-west-2" + + +@dataclass +class MockFeatureView: + name: str + + +@pytest.fixture +def repo_config(): + return RepoConfig( + registry=REGISTRY, + project=PROJECT, + provider=PROVIDER, + online_store=DynamoDBOnlineStoreConfig(region=REGION), + offline_store=FileOfflineStoreConfig(), + ) + + +def test_online_store_config_default(): + """Test DynamoDBOnlineStoreConfig default parameters.""" + aws_region = "us-west-2" + dynamodb_store_config = DynamoDBOnlineStoreConfig(region=aws_region) + assert dynamodb_store_config.type == "dynamodb" + assert dynamodb_store_config.batch_size == 40 + assert dynamodb_store_config.endpoint_url is None + assert dynamodb_store_config.region == aws_region + assert dynamodb_store_config.sort_response is True + assert dynamodb_store_config.table_name_template == "{project}.{table_name}" + + +def test_dynamodb_table_default_params(): + """Test DynamoDBTable default parameters.""" + tbl_name = "dynamodb-test" + aws_region = "us-west-2" + dynamodb_table = DynamoDBTable(tbl_name, aws_region) + assert dynamodb_table.name == tbl_name + assert dynamodb_table.region == aws_region + assert dynamodb_table.endpoint_url is None + assert dynamodb_table._dynamodb_client is None + assert dynamodb_table._dynamodb_resource is None + + +def test_online_store_config_custom_params(): + """Test DynamoDBOnlineStoreConfig custom parameters.""" + aws_region = "us-west-2" + batch_size = 20 + endpoint_url = "http://localhost:8000" + sort_response = False + table_name_template = "feast_test.dynamodb_table" + dynamodb_store_config = DynamoDBOnlineStoreConfig( + region=aws_region, + batch_size=batch_size, + endpoint_url=endpoint_url, + sort_response=sort_response, + table_name_template=table_name_template, + ) + assert dynamodb_store_config.type == "dynamodb" + assert dynamodb_store_config.batch_size == batch_size + assert dynamodb_store_config.endpoint_url == endpoint_url + assert dynamodb_store_config.region == aws_region + assert dynamodb_store_config.sort_response == sort_response + assert dynamodb_store_config.table_name_template == table_name_template + + +def test_dynamodb_table_custom_params(): + """Test DynamoDBTable custom parameters.""" + tbl_name = "dynamodb-test" + aws_region = "us-west-2" + endpoint_url = "http://localhost:8000" + dynamodb_table = DynamoDBTable(tbl_name, aws_region, endpoint_url) + assert dynamodb_table.name == tbl_name + assert dynamodb_table.region == aws_region + assert dynamodb_table.endpoint_url == endpoint_url + assert dynamodb_table._dynamodb_client is None + assert dynamodb_table._dynamodb_resource is None + + +def test_online_store_config_dynamodb_client(): + """Test DynamoDBOnlineStoreConfig configure DynamoDB client with endpoint_url.""" + aws_region = "us-west-2" + endpoint_url = "http://localhost:8000" + dynamodb_store = DynamoDBOnlineStore() + dynamodb_store_config = DynamoDBOnlineStoreConfig( + region=aws_region, endpoint_url=endpoint_url + ) + dynamodb_client = dynamodb_store._get_dynamodb_client( + dynamodb_store_config.region, dynamodb_store_config.endpoint_url + ) + assert dynamodb_client.meta.region_name == aws_region + assert dynamodb_client.meta.endpoint_url == endpoint_url + + +def test_dynamodb_table_dynamodb_client(): + """Test DynamoDBTable configure DynamoDB client with endpoint_url.""" + tbl_name = "dynamodb-test" + aws_region = "us-west-2" + endpoint_url = "http://localhost:8000" + dynamodb_table = DynamoDBTable(tbl_name, aws_region, endpoint_url) + dynamodb_client = dynamodb_table._get_dynamodb_client( + dynamodb_table.region, dynamodb_table.endpoint_url + ) + assert dynamodb_client.meta.region_name == aws_region + assert dynamodb_client.meta.endpoint_url == endpoint_url + + +def test_online_store_config_dynamodb_resource(): + """Test DynamoDBOnlineStoreConfig configure DynamoDB Resource with endpoint_url.""" + aws_region = "us-west-2" + endpoint_url = "http://localhost:8000" + dynamodb_store = DynamoDBOnlineStore() + dynamodb_store_config = DynamoDBOnlineStoreConfig( + region=aws_region, endpoint_url=endpoint_url + ) + dynamodb_resource = dynamodb_store._get_dynamodb_resource( + dynamodb_store_config.region, dynamodb_store_config.endpoint_url + ) + assert dynamodb_resource.meta.client.meta.region_name == aws_region + assert dynamodb_resource.meta.client.meta.endpoint_url == endpoint_url + + +def test_dynamodb_table_dynamodb_resource(): + """Test DynamoDBTable configure DynamoDB resource with endpoint_url.""" + tbl_name = "dynamodb-test" + aws_region = "us-west-2" + endpoint_url = "http://localhost:8000" + dynamodb_table = DynamoDBTable(tbl_name, aws_region, endpoint_url) + dynamodb_resource = dynamodb_table._get_dynamodb_resource( + dynamodb_table.region, dynamodb_table.endpoint_url + ) + assert dynamodb_resource.meta.client.meta.region_name == aws_region + assert dynamodb_resource.meta.client.meta.endpoint_url == endpoint_url + + +@mock_dynamodb2 +@pytest.mark.parametrize("n_samples", [5, 50, 100]) +def test_online_read(repo_config, n_samples): + """Test DynamoDBOnlineStore online_read method.""" + _create_test_table(PROJECT, f"{TABLE_NAME}_{n_samples}", REGION) + data = _create_n_customer_test_samples(n=n_samples) + _insert_data_test_table(data, PROJECT, f"{TABLE_NAME}_{n_samples}", REGION) + + entity_keys, features, *rest = zip(*data) + dynamodb_store = DynamoDBOnlineStore() + returned_items = dynamodb_store.online_read( + config=repo_config, + table=MockFeatureView(name=f"{TABLE_NAME}_{n_samples}"), + entity_keys=entity_keys, + ) + assert len(returned_items) == len(data) + assert [item[1] for item in returned_items] == list(features) + + +@mock_dynamodb2 +def test_write_batch_non_duplicates(repo_config): + """Test DynamoDBOnline Store deduplicate write batch request items.""" + dynamodb_tbl = f"{TABLE_NAME}_batch_non_duplicates" + _create_test_table(PROJECT, dynamodb_tbl, REGION) + data = _create_n_customer_test_samples() + data_duplicate = deepcopy(data) + dynamodb_resource = boto3.resource("dynamodb", region_name=REGION) + table_instance = dynamodb_resource.Table(f"{PROJECT}.{dynamodb_tbl}") + dynamodb_store = DynamoDBOnlineStore() + # Insert duplicate data + dynamodb_store._write_batch_non_duplicates( + table_instance, data + data_duplicate, progress=None + ) + # Request more items than inserted + response = table_instance.scan(Limit=20) + returned_items = response.get("Items", None) + assert returned_items is not None + assert len(returned_items) == len(data) diff --git a/sdk/python/tests/unit/infra/test_provider.py b/sdk/python/tests/unit/infra/test_provider.py new file mode 100644 index 00000000000..43c09760e9a --- /dev/null +++ b/sdk/python/tests/unit/infra/test_provider.py @@ -0,0 +1,48 @@ +# Copyright 2020 The Feast Authors +# +# 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 +# +# https://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. + +from datetime import timedelta + +from feast import BigQuerySource +from feast.entity import Entity +from feast.feature_view import FeatureView +from feast.field import Field +from feast.infra.provider import _get_column_names +from feast.types import String +from feast.value_type import ValueType + + +def test_get_column_names_preserves_feature_ordering(): + entity = Entity("my-entity", description="My entity", value_type=ValueType.STRING) + fv = FeatureView( + name="my-fv", + entities=["my-entity"], + ttl=timedelta(days=1), + batch_source=BigQuerySource(table="non-existent-mock"), + schema=[ + Field(name="a", dtype=String), + Field(name="b", dtype=String), + Field(name="c", dtype=String), + Field(name="d", dtype=String), + Field(name="e", dtype=String), + Field(name="f", dtype=String), + Field(name="g", dtype=String), + Field(name="h", dtype=String), + Field(name="i", dtype=String), + Field(name="j", dtype=String), + ], + ) + + _, feature_list, _, _ = _get_column_names(fv, [entity]) + assert feature_list == ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] diff --git a/sdk/python/tests/unit/test_data_sources.py b/sdk/python/tests/unit/test_data_sources.py new file mode 100644 index 00000000000..ceb9ff4ce67 --- /dev/null +++ b/sdk/python/tests/unit/test_data_sources.py @@ -0,0 +1,54 @@ +import pytest + +from feast import ValueType +from feast.data_source import PushSource, RequestDataSource, RequestSource +from feast.field import Field +from feast.infra.offline_stores.bigquery_source import BigQuerySource +from feast.types import PrimitiveFeastType + + +def test_push_with_batch(): + push_source = PushSource( + name="test", + schema=[ + Field(name="f1", dtype=PrimitiveFeastType.FLOAT32), + Field(name="f2", dtype=PrimitiveFeastType.BOOL), + ], + timestamp_field="event_timestamp", + batch_source=BigQuerySource(table="test.test"), + ) + push_source_proto = push_source.to_proto() + assert push_source_proto.HasField("batch_source") + assert push_source_proto.timestamp_field is not None + assert push_source_proto.push_options is not None + + push_source_unproto = PushSource.from_proto(push_source_proto) + + assert push_source.name == push_source_unproto.name + assert push_source.schema == push_source_unproto.schema + assert push_source.timestamp_field == push_source_unproto.timestamp_field + assert push_source.batch_source.name == push_source_unproto.batch_source.name + + +def test_request_data_source_deprecation(): + with pytest.warns(DeprecationWarning): + request_data_source = RequestDataSource( + name="vals_to_add", + schema={"val_to_add": ValueType.INT64, "val_to_add_2": ValueType.INT64}, + ) + request_data_source_proto = request_data_source.to_proto() + returned_request_source = RequestSource.from_proto(request_data_source_proto) + assert returned_request_source == request_data_source + + +def test_request_source_primitive_type_to_proto(): + schema = [ + Field(name="f1", dtype=PrimitiveFeastType.FLOAT32), + Field(name="f2", dtype=PrimitiveFeastType.BOOL), + ] + request_source = RequestSource( + name="source", schema=schema, description="desc", tags={}, owner="feast", + ) + request_proto = request_source.to_proto() + deserialized_request_source = RequestSource.from_proto(request_proto) + assert deserialized_request_source == request_source diff --git a/sdk/python/tests/unit/test_entity.py b/sdk/python/tests/unit/test_entity.py index ec3ed70253f..fee8bd9f009 100644 --- a/sdk/python/tests/unit/test_entity.py +++ b/sdk/python/tests/unit/test_entity.py @@ -11,32 +11,55 @@ # 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. +import assertpy +import pytest from feast.entity import Entity from feast.value_type import ValueType def test_join_key_default(): - entity = Entity("my-entity", description="My entity", value_type=ValueType.STRING) + with pytest.deprecated_call(): + entity = Entity( + "my-entity", description="My entity", value_type=ValueType.STRING + ) assert entity.join_key == "my-entity" def test_entity_class_contains_tags(): - entity = Entity( - "my-entity", - description="My entity", - value_type=ValueType.STRING, - tags={"key1": "val1", "key2": "val2"}, - ) + with pytest.deprecated_call(): + entity = Entity( + "my-entity", + description="My entity", + value_type=ValueType.STRING, + tags={"key1": "val1", "key2": "val2"}, + ) assert "key1" in entity.tags.keys() and entity.tags["key1"] == "val1" assert "key2" in entity.tags.keys() and entity.tags["key2"] == "val2" def test_entity_without_tags_empty_dict(): - entity = Entity("my-entity", description="My entity", value_type=ValueType.STRING) + with pytest.deprecated_call(): + entity = Entity( + "my-entity", description="My entity", value_type=ValueType.STRING + ) assert entity.tags == dict() assert len(entity.tags) == 0 def test_entity_without_description(): - Entity("my-entity", value_type=ValueType.STRING) + with pytest.deprecated_call(): + Entity("my-entity", value_type=ValueType.STRING) + + +def test_name_not_specified(): + assertpy.assert_that(lambda: Entity(value_type=ValueType.STRING)).raises(ValueError) + + +def test_multiple_args(): + assertpy.assert_that(lambda: Entity("a", ValueType.STRING)).raises(ValueError) + + +def test_name_keyword(recwarn): + Entity(name="my-entity", value_type=ValueType.STRING) + assert len(recwarn) == 0 diff --git a/sdk/python/tests/unit/test_types.py b/sdk/python/tests/unit/test_types.py new file mode 100644 index 00000000000..af490b4f3a9 --- /dev/null +++ b/sdk/python/tests/unit/test_types.py @@ -0,0 +1,34 @@ +import pytest + +from feast.types import Array, Float32, String, from_value_type +from feast.value_type import ValueType + + +def test_primitive_feast_type(): + assert String.to_value_type() == ValueType.STRING + assert from_value_type(String.to_value_type()) == String + assert Float32.to_value_type() == ValueType.FLOAT + assert from_value_type(Float32.to_value_type()) == Float32 + + +def test_array_feast_type(): + array_string = Array(String) + assert array_string.to_value_type() == ValueType.STRING_LIST + assert from_value_type(array_string.to_value_type()) == array_string + + array_float_32 = Array(Float32) + assert array_float_32.to_value_type() == ValueType.FLOAT_LIST + assert from_value_type(array_float_32.to_value_type()) == array_float_32 + + with pytest.raises(ValueError): + _ = Array(Array) + + with pytest.raises(ValueError): + _ = Array(Array(String)) + + +def test_all_value_types(): + for value in ValueType: + # We do not support the NULL type. + if value != ValueType.NULL: + assert from_value_type(value).to_value_type() == value diff --git a/sdk/python/tests/utils/data_source_utils.py b/sdk/python/tests/utils/data_source_utils.py index 5a5baceef07..5bb5a622d61 100644 --- a/sdk/python/tests/utils/data_source_utils.py +++ b/sdk/python/tests/utils/data_source_utils.py @@ -18,14 +18,12 @@ def prep_file_source(df, event_timestamp_column=None) -> Iterator[FileSource]: file_source = FileSource( file_format=ParquetFormat(), path=f.name, - event_timestamp_column=event_timestamp_column, + timestamp_field=event_timestamp_column, ) yield file_source -def simple_bq_source_using_table_ref_arg( - df, event_timestamp_column=None -) -> BigQuerySource: +def simple_bq_source_using_table_arg(df, event_timestamp_column=None) -> BigQuerySource: client = bigquery.Client() gcp_project = client.project bigquery_dataset = f"ds_{time.time_ns()}" @@ -37,22 +35,18 @@ def simple_bq_source_using_table_ref_arg( * 60 # 60 minutes in milliseconds (seems to be minimum limit for gcloud) ) client.update_dataset(dataset, ["default_table_expiration_ms"]) - table_ref = f"{gcp_project}.{bigquery_dataset}.table_{random.randrange(100, 999)}" + table = f"{gcp_project}.{bigquery_dataset}.table_{random.randrange(100, 999)}" - job = client.load_table_from_dataframe(df, table_ref) + job = client.load_table_from_dataframe(df, table) job.result() - return BigQuerySource( - table_ref=table_ref, event_timestamp_column=event_timestamp_column, - ) + return BigQuerySource(table=table, timestamp_field=event_timestamp_column,) def simple_bq_source_using_query_arg(df, event_timestamp_column=None) -> BigQuerySource: - bq_source_using_table_ref = simple_bq_source_using_table_ref_arg( - df, event_timestamp_column - ) + bq_source_using_table = simple_bq_source_using_table_arg(df, event_timestamp_column) return BigQuerySource( - name=bq_source_using_table_ref.table_ref, - query=f"SELECT * FROM {bq_source_using_table_ref.table_ref}", - event_timestamp_column=event_timestamp_column, + name=bq_source_using_table.table, + query=f"SELECT * FROM {bq_source_using_table.table}", + timestamp_field=event_timestamp_column, ) diff --git a/sdk/python/tests/utils/online_read_write_test.py b/sdk/python/tests/utils/online_read_write_test.py index 34ff7c7d3fa..39846cd2ad4 100644 --- a/sdk/python/tests/utils/online_read_write_test.py +++ b/sdk/python/tests/utils/online_read_write_test.py @@ -18,11 +18,11 @@ def basic_rw_test( provider = store._get_provider() entity_key = EntityKeyProto( - join_keys=["driver"], entity_values=[ValueProto(int64_val=1)] + join_keys=["driver_id"], entity_values=[ValueProto(int64_val=1)] ) def _driver_rw_test(event_ts, created_ts, write, expect_read): - """ A helper function to write values and read them back """ + """A helper function to write values and read them back""" write_lat, write_lon = write expect_lat, expect_lon = expect_read provider.online_write_batch( @@ -43,12 +43,12 @@ def _driver_rw_test(event_ts, created_ts, write, expect_read): ) if feature_service_name: - entity_dict = {"driver": 1} + entity_dict = {"driver_id": 1} feature_service = store.get_feature_service(feature_service_name) features = store.get_online_features( features=feature_service, entity_rows=[entity_dict] ).to_dict() - assert len(features["driver"]) == 1 + assert len(features["driver_id"]) == 1 assert features["lon"][0] == expect_lon assert abs(features["lat"][0] - expect_lat) < 1e-6 else: diff --git a/sdk/python/tests/utils/online_store_utils.py b/sdk/python/tests/utils/online_store_utils.py new file mode 100644 index 00000000000..f72b4d5a2a3 --- /dev/null +++ b/sdk/python/tests/utils/online_store_utils.py @@ -0,0 +1,56 @@ +from datetime import datetime + +import boto3 + +from feast import utils +from feast.infra.online_stores.helpers import compute_entity_id +from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto +from feast.protos.feast.types.Value_pb2 import Value as ValueProto + + +def _create_n_customer_test_samples(n=10): + return [ + ( + EntityKeyProto( + join_keys=["customer"], entity_values=[ValueProto(string_val=str(i))] + ), + { + "avg_orders_day": ValueProto(float_val=1.0), + "name": ValueProto(string_val="John"), + "age": ValueProto(int64_val=3), + }, + datetime.utcnow(), + None, + ) + for i in range(n) + ] + + +def _create_test_table(project, tbl_name, region): + client = boto3.client("dynamodb", region_name=region) + client.create_table( + TableName=f"{project}.{tbl_name}", + KeySchema=[{"AttributeName": "entity_id", "KeyType": "HASH"}], + AttributeDefinitions=[{"AttributeName": "entity_id", "AttributeType": "S"}], + BillingMode="PAY_PER_REQUEST", + ) + + +def _delete_test_table(project, tbl_name, region): + client = boto3.client("dynamodb", region_name=region) + client.delete_table(TableName=f"{project}.{tbl_name}") + + +def _insert_data_test_table(data, project, tbl_name, region): + dynamodb_resource = boto3.resource("dynamodb", region_name=region) + table_instance = dynamodb_resource.Table(f"{project}.{tbl_name}") + for entity_key, features, timestamp, created_ts in data: + entity_id = compute_entity_id(entity_key) + with table_instance.batch_writer() as batch: + batch.put_item( + Item={ + "entity_id": entity_id, + "event_ts": str(utils.make_tzaware(timestamp)), + "values": {k: v.SerializeToString() for k, v in features.items()}, + } + ) diff --git a/sdk/python/tests/utils/online_write_benchmark.py b/sdk/python/tests/utils/online_write_benchmark.py index 1b7b15ac969..6d6b73d5da6 100644 --- a/sdk/python/tests/utils/online_write_benchmark.py +++ b/sdk/python/tests/utils/online_write_benchmark.py @@ -11,11 +11,12 @@ from feast import FileSource from feast.driver_test_data import create_driver_hourly_stats_df from feast.entity import Entity -from feast.feature import Feature from feast.feature_store import FeatureStore from feast.feature_view import FeatureView +from feast.field import Field from feast.infra.provider import _convert_arrow_to_proto from feast.repo_config import RepoConfig +from feast.types import Float32, Int32 from feast.value_type import ValueType @@ -23,10 +24,10 @@ def create_driver_hourly_stats_feature_view(source): driver_stats_feature_view = FeatureView( name="driver_stats", entities=["driver_id"], - features=[ - Feature(name="conv_rate", dtype=ValueType.FLOAT), - Feature(name="acc_rate", dtype=ValueType.FLOAT), - Feature(name="avg_daily_trips", dtype=ValueType.INT32), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int32), ], batch_source=source, ttl=timedelta(hours=2), @@ -37,7 +38,7 @@ def create_driver_hourly_stats_feature_view(source): def create_driver_hourly_stats_source(parquet_path): return FileSource( path=parquet_path, - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created", ) diff --git a/ui/.babelrc.js b/ui/.babelrc.js new file mode 100644 index 00000000000..68a0192e504 --- /dev/null +++ b/ui/.babelrc.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [["@babel/preset-env"], ["@babel/preset-react"]], +}; diff --git a/ui/PUBLISHING_TO_NPM.md b/ui/PUBLISHING_TO_NPM.md new file mode 100644 index 00000000000..2ad42fd227b --- /dev/null +++ b/ui/PUBLISHING_TO_NPM.md @@ -0,0 +1,13 @@ +# Publishing the Feast Package to NPM + +The Feast UI is published as a module to NPM and can be found here: https://www.npmjs.com/package/@feast-dev/feast-ui + +To publish a new version of the module, you will need to be part of the @feast-dev team in NPM. Ask Tony to add you if necessary. You will also need to [login to your NPM account on the command line](https://docs.npmjs.com/cli/v8/commands/npm-adduser). + +## Steps for Publishing + +1. Make sure tests are passing. Run tests with `yarn tests` in the ui directory. +2. Bump the version number in `package.json` as appropriate. +3. Package the modules for distributions. Run the library build script with `yarn build:lib`. We use [Rollup](https://rollupjs.org/) for building the module, and the configs are in the `rollup.config.js` file. +4. Publish the package to NPM. Run `npm publish` +5. [Check NPM to see that the package was properly publish](https://www.npmjs.com/package/@feast-dev/feast-ui). diff --git a/ui/README.md b/ui/README.md index 9a5171bd1fb..80e20b31643 100644 --- a/ui/README.md +++ b/ui/README.md @@ -16,46 +16,135 @@ available for the rest of the UI. - `src/custom-tabs` includes sample custom tabs. This is a WIP plugin system where users can inject their own tabs and data to the UI. +## Usage + +There are two modes of usage: importing the UI as a module, or running the entire build as a React app. + +### Importing the UI as a module + +This is the recommended way to use Feast UI for teams maintaining their own internal UI for their deployment of Feast. + +Start with bootstrapping a React app with `create-react-app` -## Available Scripts +``` +npx create-react-app your-feast-ui +``` -In the project directory, you can run: +Then, in your app folder, install Feast UI and its peer dependencies. Assuming you use yarn -### `yarn start` +``` +yarn add @feast-dev/feast-ui +yarn add @elastic/eui @elastic/datemath @emotion/react moment prop-types inter-ui react-query react-router-dom use-query-params zod typescript query-string d3 @types/d3 +``` -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. +Edit `index.js` in the React app to use Feast UI. -The page will reload if you make edits.\ -You will also see any lint errors in the console. +```js +import React from "react"; +import ReactDOM from "react-dom"; +import "./index.css"; -### `yarn test` +import FeastUI from "@feast-dev/feast-ui"; +import "@feast-dev/feast-ui/dist/feast-ui.css"; -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. +ReactDOM.render( + + + , + document.getElementById("root") +); +``` + +When you start the React app, it will look for `project-list.json` to find a list of your projects. The JSON should looks something like this. + +```json +{ + "projects": [ + { + "name": "Credit Score Project", + "description": "Project for credit scoring team and associated models.", + "id": "credit_score_project", + "registryPath": "/registry.json" + }, + ] +} +``` + +``` +// Start the React App +yarn start +``` + +#### Customization + +The advantage of importing Feast UI as a module is in the ease of customization. The `` component exposes a `feastUIConfigs` prop thorough which you can customize the UI. Currently it supports a few parameters. + +##### Fetching the Project List -### `yarn build` +You can use `projectListPromise` to provide a promise that overrides where the Feast UI fetches the project list from. -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. +```jsx + { + return res.json(); + }) + }} +/> +``` -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! +##### Custom Tabs -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. +You can add custom tabs for any of the core Feast objects through the `tabsRegistry`. -### `yarn eject` +``` +const tabsRegistry = { + RegularFeatureViewCustomTabs: [ + { + label: "Custom Tab Demo", // Navigation Label for the tab + path: "demo-tab", // Subpath for the tab + Component: RFVDemoCustomTab, // a React Component + }, + ] +} -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +``` -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. +Examples of custom tabs can be found in the `/custom-tabs` folder. -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. +### Alternative: Run this Repo + +If you would like to simply try things out and see how the UI works, you can simply run the code in this repo. First: + +### `yarn install` + +That will install the all the dependencies that the UI needs, as well as development dependencies. Then in the project directory, you can run: + +### `yarn start` + +Runs the app in the development mode.\ +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.\ +You will also see any lint errors in the console. + +### `yarn test` + +Launches the test runner in the interactive watch mode.\ +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. -## Learn More +## On React and Create React App -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). +This project was bootstrapped with Create React App, and uses its scripts to simplify UI development. You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). To learn React, check out the [React documentation](https://reactjs.org/). diff --git a/ui/feature_repo/features.py b/ui/feature_repo/features.py index 8d9f5c66f14..0f74b424e7b 100644 --- a/ui/feature_repo/features.py +++ b/ui/feature_repo/features.py @@ -1,16 +1,20 @@ from datetime import timedelta from feast import ( + Bool, Entity, - Feature, FeatureService, FeatureView, + Field, FileSource, + Int64, + String, ValueType, ) -from feast.data_source import RequestDataSource +from feast.data_source import RequestSource from feast.request_feature_view import RequestFeatureView from feast.on_demand_feature_view import on_demand_feature_view +from feast.field import Field import pandas as pd zipcode = Entity( @@ -23,7 +27,7 @@ zipcode_source = FileSource( name="zipcode", path="data/zipcode_table.parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created_timestamp", ) @@ -31,13 +35,13 @@ name="zipcode_features", entities=["zipcode"], ttl=timedelta(days=3650), - features=[ - Feature(name="city", dtype=ValueType.STRING), - Feature(name="state", dtype=ValueType.STRING), - Feature(name="location_type", dtype=ValueType.STRING), - Feature(name="tax_returns_filed", dtype=ValueType.INT64), - Feature(name="population", dtype=ValueType.INT64), - Feature(name="total_wages", dtype=ValueType.INT64), + schema=[ + Field(name="city", dtype=String), + Field(name="state", dtype=String), + Field(name="location_type", dtype=String), + Field(name="tax_returns_filed", dtype=Int64), + Field(name="population", dtype=Int64), + Field(name="total_wages", dtype=Int64), ], batch_source=zipcode_source, tags={ @@ -52,13 +56,13 @@ name="zipcode_features", entities=["zipcode"], ttl=timedelta(days=3650), - features=[ - Feature(name="city", dtype=ValueType.STRING), - Feature(name="state", dtype=ValueType.STRING), - Feature(name="location_type", dtype=ValueType.STRING), - Feature(name="tax_returns_filed", dtype=ValueType.INT64), - Feature(name="population", dtype=ValueType.INT64), - Feature(name="total_wages", dtype=ValueType.INT64), + schema=[ + Field(name="city", dtype=String), + Field(name="state", dtype=String), + Field(name="location_type", dtype=String), + Field(name="tax_returns_filed", dtype=Int64), + Field(name="population", dtype=Int64), + Field(name="total_wages", dtype=Int64), ], batch_source=zipcode_source, tags={ @@ -73,9 +77,9 @@ name="zipcode_money_features", entities=["zipcode"], ttl=timedelta(days=3650), - features=[ - Feature(name="tax_returns_filed", dtype=ValueType.INT64), - Feature(name="total_wages", dtype=ValueType.INT64), + schema=[ + Field(name="tax_returns_filed", dtype=Int64), + Field(name="total_wages", dtype=Int64), ], batch_source=zipcode_source, tags={ @@ -96,7 +100,7 @@ credit_history_source = FileSource( name="credit_history", path="data/credit_history.parquet", - event_timestamp_column="event_timestamp", + timestamp_field="event_timestamp", created_timestamp_column="created_timestamp", ) @@ -104,16 +108,16 @@ name="credit_history", entities=["dob_ssn"], ttl=timedelta(days=9000), - features=[ - Feature(name="credit_card_due", dtype=ValueType.INT64), - Feature(name="mortgage_due", dtype=ValueType.INT64), - Feature(name="student_loan_due", dtype=ValueType.INT64), - Feature(name="vehicle_loan_due", dtype=ValueType.INT64), - Feature(name="hard_pulls", dtype=ValueType.INT64), - Feature(name="missed_payments_2y", dtype=ValueType.INT64), - Feature(name="missed_payments_1y", dtype=ValueType.INT64), - Feature(name="missed_payments_6m", dtype=ValueType.INT64), - Feature(name="bankruptcies", dtype=ValueType.INT64), + schema=[ + Field(name="credit_card_due", dtype=Int64), + Field(name="mortgage_due", dtype=Int64), + Field(name="student_loan_due", dtype=Int64), + Field(name="vehicle_loan_due", dtype=Int64), + Field(name="hard_pulls", dtype=Int64), + Field(name="missed_payments_2y", dtype=Int64), + Field(name="missed_payments_1y", dtype=Int64), + Field(name="missed_payments_6m", dtype=Int64), + Field(name="bankruptcies", dtype=Int64), ], batch_source=credit_history_source, tags={ @@ -126,16 +130,19 @@ # Define a request data source which encodes features / information only # available at request time (e.g. part of the user initiated HTTP request) -input_request = RequestDataSource( - name="transaction", schema={"transaction_amt": ValueType.INT64}, +input_request = RequestSource( + name="transaction", + schema=[ + Field(name="transaction_amt", dtype=Int64), + ], ) # Define an on demand feature view which can generate new features based on -# existing feature views and RequestDataSource features +# existing feature views and RequestSource features @on_demand_feature_view( - inputs={"credit_history": credit_history, "transaction": input_request,}, - features=[ - Feature(name="transaction_gt_last_credit_card_due", dtype=ValueType.BOOL), + sources={"credit_history": credit_history, "transaction": input_request,}, + schema=[ + Field(name="transaction_gt_last_credit_card_due", dtype=Bool), ], ) def transaction_gt_last_credit_card_due(inputs: pd.DataFrame) -> pd.DataFrame: diff --git a/ui/package.json b/ui/package.json index f53ea7ce6df..37a5ddf4318 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,19 +1,19 @@ { - "name": "feast-ui", - "version": "0.1.0", - "private": true, - "dependencies": { + "name": "@feast-dev/feast-ui", + "version": "0.19.0", + "private": false, + "files": [ + "dist" + ], + "main": "./dist/feast-ui.cjs", + "module": "./dist/feast-ui.module.js", + "peerDependencies": { "@elastic/datemath": "^5.0.3", - "@elastic/eui": "^50.0.0", - "@emotion/react": "^11.8.1", - "@testing-library/jest-dom": "^5.16.2", - "@testing-library/react": "^12.1.3", - "@testing-library/user-event": "^13.5.0", + "@elastic/eui": "^46.1.0", + "@emotion/react": "^11.7.1", "@types/d3": "^7.1.0", - "@types/jest": "^27.4.1", - "@types/node": "^17.0.21", - "@types/react": "^17.0.39", - "@types/react-dom": "^17.0.13", + "@types/react": "^17.0.20", + "@types/react-dom": "^17.0.9", "d3": "^7.3.0", "inter-ui": "^3.19.3", "moment": "^2.29.1", @@ -21,17 +21,38 @@ "query-string": "^7.1.1", "react": "^17.0.2", "react-dom": "^17.0.2", - "react-query": "^3.34.16", + "react-query": "^3.34.12", + "react-router-dom": "6", + "react-scripts": "^5.0.0", + "typescript": "^4.4.2", + "use-query-params": "^1.2.3", + "zod": "^3.11.6" + }, + "dependencies": { + "@elastic/datemath": "^5.0.3", + "@elastic/eui": "^46.1.0", + "@emotion/react": "^11.7.1", + "@types/d3": "^7.1.0", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@types/react": "^17.0.20", + "@types/react-dom": "^17.0.9", + "d3": "^7.3.0", + "inter-ui": "^3.19.3", + "moment": "^2.29.1", + "prop-types": "^15.8.1", + "query-string": "^7.1.1", + "react-query": "^3.34.12", "react-router-dom": "6", - "react-scripts": "5.0.0", - "typescript": "^4.6.2", + "react-scripts": "^5.0.0", "use-query-params": "^1.2.3", - "web-vitals": "^2.1.4", - "zod": "^3.13.4" + "zod": "^3.11.6" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", + "build:lib": "rimraf ./dist && tsc && rollup -c", + "build:lib-dev": "rimraf ./dist && tsc && rollup -c && yalc publish -f", "test": "react-scripts test", "eject": "react-scripts eject" }, @@ -59,6 +80,43 @@ ] }, "devDependencies": { - "msw": "^0.38.2" + "@babel/core": "^7.17.5", + "@babel/preset-env": "^7.16.11", + "@babel/preset-react": "^7.16.7", + "@rollup/plugin-babel": "^5.3.1", + "@rollup/plugin-commonjs": "^21.0.2", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.1.3", + "@rollup/plugin-typescript": "^8.3.1", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^12.0.0", + "@testing-library/user-event": "^13.2.1", + "msw": "^0.36.8", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "rimraf": "^3.0.2", + "rollup": "^2.68.0", + "rollup-plugin-copy": "^3.4.0", + "rollup-plugin-import-css": "^3.0.2", + "rollup-plugin-svg": "^2.0.0", + "rollup-plugin-svgo": "^1.1.0", + "rollup-plugin-terser": "^7.0.2", + "tslib": "^2.3.1", + "typescript": "^4.4.2" + }, + "description": "Web UI for the [Feast Feature Store](https://feast.dev/)", + "repository": { + "type": "git", + "url": "git+https://github.com/feast-dev/feast.git" + }, + "keywords": [ + "Feast", + "Feature", + "Store" + ], + "author": "tony@tecton.ai", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/feast-dev/feast/issues" } } diff --git a/ui/public/manifest.json b/ui/public/manifest.json index 080d6c77ac2..eaeed00748e 100644 --- a/ui/public/manifest.json +++ b/ui/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "Feast UI", + "name": "Feast UI", "icons": [ { "src": "favicon.ico", diff --git a/ui/public/registry.json b/ui/public/registry.json index 024fb1ac194..af328979e98 100644 --- a/ui/public/registry.json +++ b/ui/public/registry.json @@ -627,7 +627,7 @@ }, "userDefinedFunction": { "name": "transaction_gt_last_credit_card_due", - "body": "@on_demand_feature_view(\n inputs={\"credit_history\": credit_history, \"transaction\": input_request,},\n features=[\n Feature(name=\"transaction_gt_last_credit_card_due\", dtype=ValueType.BOOL),\n ],\n)\ndef transaction_gt_last_credit_card_due(inputs: pd.DataFrame) -> pd.DataFrame:\n df = pd.DataFrame()\n df[\"transaction_gt_last_credit_card_due\"] = (\n inputs[\"transaction_amt\"] > inputs[\"credit_card_due\"]\n )\n return df\n" + "body": "@on_demand_feature_view(\n sources={\"credit_history\": credit_history, \"transaction\": input_request,},\n schema=[\n Field(name=\"transaction_gt_last_credit_card_due\", dtype=Bool),\n ],\n)\ndef transaction_gt_last_credit_card_due(inputs: pd.DataFrame) -> pd.DataFrame:\n df = pd.DataFrame()\n df[\"transaction_gt_last_credit_card_due\"] = (\n inputs[\"transaction_amt\"] > inputs[\"credit_card_due\"]\n )\n return df\n" } }, "meta": { diff --git a/ui/rollup.config.js b/ui/rollup.config.js new file mode 100644 index 00000000000..93e17345fe6 --- /dev/null +++ b/ui/rollup.config.js @@ -0,0 +1,102 @@ +import pluginTypescript from "@rollup/plugin-typescript"; +import pluginCommonjs from "@rollup/plugin-commonjs"; +import pluginNodeResolve from "@rollup/plugin-node-resolve"; +import { babel } from "@rollup/plugin-babel"; +import json from "@rollup/plugin-json"; +import css from "rollup-plugin-import-css"; +import svg from "rollup-plugin-svg"; +import copy from "rollup-plugin-copy"; // https://npm.io/package/rollup-plugin-copy + +import * as path from "path"; +import pkg from "./package.json"; + +const moduleName = pkg.name.replace(/^@.*\//, ""); +const inputFileName = "src/FeastUI.tsx"; +const author = pkg.author; +const banner = ` + /** + * @license + * author: ${author} + * ${moduleName}.js v${pkg.version} + * Released under the ${pkg.license} license. + */ +`; + +const rollupConfig = [ + // ES + { + input: inputFileName, + output: [ + { + file: pkg.module, + format: "es", + sourcemap: "inline", + banner, + exports: "named", + }, + ], + external: [ + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.devDependencies || {}), + ], + plugins: [ + pluginTypescript(), + pluginCommonjs({ + extensions: [".js", ".ts"], + }), + babel({ + babelHelpers: "bundled", + configFile: path.resolve(__dirname, ".babelrc.js"), + }), + pluginNodeResolve({ + browser: false, + }), + css({ + output: "feast-ui.css", + }), + svg(), + json(), + copy({ + targets: [{ src: "src/assets/**/*", dest: "dist/assets/" }], + }), + ], + }, + + // CommonJS + { + input: inputFileName, + output: [ + { + file: pkg.main, + format: "cjs", + sourcemap: "inline", + banner, + exports: "default", + }, + ], + external: [ + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.devDependencies || {}), + ], + plugins: [ + pluginTypescript(), + pluginCommonjs({ + extensions: [".js", ".ts"], + }), + babel({ + babelHelpers: "bundled", + configFile: path.resolve(__dirname, ".babelrc.js"), + }), + pluginNodeResolve({ + browser: false, + }), + css({ + output: "feast-ui.css", + }), + svg(), + json(), + ], + }, +]; + +export default rollupConfig; diff --git a/ui/src/App.css b/ui/src/App.css index 47655db950b..4577c6f3334 100644 --- a/ui/src/App.css +++ b/ui/src/App.css @@ -1,4 +1,4 @@ html { - background: url("feast-icon-white.svg") no-repeat bottom left; + background: url("assets/feast-icon-white.svg") no-repeat bottom left; background-size: 20vh; } diff --git a/ui/src/App.tsx b/ui/src/App.tsx deleted file mode 100644 index f93c7c314fe..00000000000 --- a/ui/src/App.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from "react"; -import "inter-ui/inter.css"; -import "@elastic/eui/dist/eui_theme_light.css"; - -import { EuiProvider } from "@elastic/eui"; -import ProjectOverviewPage from "./pages/ProjectOverviewPage"; -import { Route, Routes } from "react-router"; -import Layout from "./pages/Layout"; -import NoMatch from "./pages/NoMatch"; -import DatasourceIndex from "./pages/data-sources/Index"; -import DatasetIndex from "./pages/saved-data-sets/Index"; -import EntityIndex from "./pages/entities/Index"; -import EntityInstance from "./pages/entities/EntityInstance"; -import FeatureServiceIndex from "./pages/feature-services/Index"; -import FeatureViewIndex from "./pages/feature-views/Index"; -import FeatureViewInstance from "./pages/feature-views/FeatureViewInstance"; -import FeatureServiceInstance from "./pages/feature-services/FeatureServiceInstance"; -import DataSourceInstance from "./pages/data-sources/DataSourceInstance"; -import RootProjectSelectionPage from "./pages/RootProjectSelectionPage"; -import DatasetInstance from "./pages/saved-data-sets/DatasetInstance"; -import NoProjectGuard from "./components/NoProjectGuard"; - -const App = () => { - return ( - - - }> - } /> - }> - } /> - } /> - } - /> - } /> - } - /> - } /> - } - /> - } /> - } /> - - } /> - } - /> - - - } /> - - - ); -}; - -export default App; diff --git a/ui/src/FeastUI.tsx b/ui/src/FeastUI.tsx new file mode 100644 index 00000000000..628b916f2d8 --- /dev/null +++ b/ui/src/FeastUI.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +import { BrowserRouter } from "react-router-dom"; +import { QueryClient, QueryClientProvider } from "react-query"; +import { QueryParamProvider } from "use-query-params"; +import RouteAdapter from "./hacks/RouteAdapter"; +import FeastUISansProviders, { FeastUIConfigs } from "./FeastUISansProviders"; + +interface FeastUIProps { + reactQueryClient?: QueryClient; + feastUIConfigs?: FeastUIConfigs; +} + +const defaultQueryClient = new QueryClient(); + +const FeastUI = ({ reactQueryClient, feastUIConfigs }: FeastUIProps) => { + const queryClient = reactQueryClient || defaultQueryClient; + + return ( + + + + + + + + ); +}; + +export default FeastUI; +export type { FeastUIConfigs }; diff --git a/ui/src/App.test.tsx b/ui/src/FeastUISansProviders.test.tsx similarity index 94% rename from ui/src/App.test.tsx rename to ui/src/FeastUISansProviders.test.tsx index fa6df6ebc53..1289cea028a 100644 --- a/ui/src/App.test.tsx +++ b/ui/src/FeastUISansProviders.test.tsx @@ -9,7 +9,7 @@ import { } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import App from "./App"; +import FeastUISansProviders from "./FeastUISansProviders"; import { projectsListWithDefaultProject, creditHistoryRegistry, @@ -32,7 +32,7 @@ afterEach(() => server.resetHandlers()); afterAll(() => server.close()); test("full app rendering", async () => { - render(); + render(); // Rendering the app without any paths should mean // rendering the @@ -61,7 +61,7 @@ test("full app rendering", async () => { const leftClick = { button: 0 }; test("routes are reachable", async () => { - render(); + render(); // Wait for content to load await screen.findByText(/Explore this Project/i); diff --git a/ui/src/FeastUISansProviders.tsx b/ui/src/FeastUISansProviders.tsx new file mode 100644 index 00000000000..a6df45b86df --- /dev/null +++ b/ui/src/FeastUISansProviders.tsx @@ -0,0 +1,125 @@ +import React from "react"; + +import "@elastic/eui/dist/eui_theme_light.css"; +import "./index.css"; + +import { Routes, Route } from "react-router-dom"; +import { EuiProvider, EuiErrorBoundary } from "@elastic/eui"; + +import ProjectOverviewPage from "./pages/ProjectOverviewPage"; +import Layout from "./pages/Layout"; +import NoMatch from "./pages/NoMatch"; +import DatasourceIndex from "./pages/data-sources/Index"; +import DatasetIndex from "./pages/saved-data-sets/Index"; +import EntityIndex from "./pages/entities/Index"; +import EntityInstance from "./pages/entities/EntityInstance"; +import FeatureServiceIndex from "./pages/feature-services/Index"; +import FeatureViewIndex from "./pages/feature-views/Index"; +import FeatureViewInstance from "./pages/feature-views/FeatureViewInstance"; +import FeatureServiceInstance from "./pages/feature-services/FeatureServiceInstance"; +import DataSourceInstance from "./pages/data-sources/DataSourceInstance"; +import RootProjectSelectionPage from "./pages/RootProjectSelectionPage"; +import DatasetInstance from "./pages/saved-data-sets/DatasetInstance"; +import NoProjectGuard from "./components/NoProjectGuard"; + +import TabsRegistryContext, { + FeastTabsRegistryInterface, +} from "./custom-tabs/TabsRegistryContext"; +import FeatureFlagsContext, { + FeatureFlags, +} from "./contexts/FeatureFlagsContext"; +import { + ProjectListContext, + ProjectsListContextInterface, +} from "./contexts/ProjectListContext"; + +interface FeastUIConfigs { + tabsRegistry: FeastTabsRegistryInterface; + featureFlags?: FeatureFlags; + projectListPromise?: Promise; +} + +const defaultProjectListPromise = () => { + return fetch("/projects-list.json", { + headers: { + "Content-Type": "application/json", + }, + }).then((res) => { + return res.json(); + }); +}; + +const FeastUISansProviders = ({ + feastUIConfigs, +}: { + feastUIConfigs?: FeastUIConfigs; +}) => { + const projectListContext: ProjectsListContextInterface = + feastUIConfigs?.projectListPromise + ? { + projectsListPromise: feastUIConfigs?.projectListPromise, + isCustom: true, + } + : { projectsListPromise: defaultProjectListPromise(), isCustom: false }; + + return ( + + + + + + + }> + } /> + }> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } + /> + } /> + } + /> + + } /> + } + /> + + + } /> + + + + + + + ); +}; + +export default FeastUISansProviders; +export type { FeastUIConfigs }; diff --git a/ui/src/feast-icon-blue.svg b/ui/src/assets/feast-icon-blue.svg similarity index 100% rename from ui/src/feast-icon-blue.svg rename to ui/src/assets/feast-icon-blue.svg diff --git a/ui/src/feast-icon-grey.svg b/ui/src/assets/feast-icon-grey.svg similarity index 100% rename from ui/src/feast-icon-grey.svg rename to ui/src/assets/feast-icon-grey.svg diff --git a/ui/src/feast-icon-white.svg b/ui/src/assets/feast-icon-white.svg similarity index 100% rename from ui/src/feast-icon-white.svg rename to ui/src/assets/feast-icon-white.svg diff --git a/ui/src/logo.svg b/ui/src/assets/logo.svg similarity index 100% rename from ui/src/logo.svg rename to ui/src/assets/logo.svg diff --git a/ui/src/components/EuiCustomLink.jsx b/ui/src/components/EuiCustomLink.jsx index a9c0d625f3a..cf646d43f73 100644 --- a/ui/src/components/EuiCustomLink.jsx +++ b/ui/src/components/EuiCustomLink.jsx @@ -1,7 +1,7 @@ // File name: "EuiCustomLink.js". import React from "react"; import { EuiLink } from "@elastic/eui"; -import { useNavigate, useHref } from "react-router"; +import { useNavigate, useHref } from "react-router-dom"; const isModifiedEvent = (event) => !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); diff --git a/ui/src/components/FeaturesListDisplay.tsx b/ui/src/components/FeaturesListDisplay.tsx index 2ab17fdbf5b..abd9c1d2e45 100644 --- a/ui/src/components/FeaturesListDisplay.tsx +++ b/ui/src/components/FeaturesListDisplay.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { enabledFeatureStatistics } from "../flags"; +import React, { useContext } from "react"; import { EuiBasicTable, EuiLoadingSpinner, EuiBadge } from "@elastic/eui"; import { FeastFeatureColumnType } from "../parsers/feastFeatureViews"; import useLoadFeatureViewSummaryStatistics from "../queries/useLoadFeatureViewSummaryStatistics"; import SparklineHistogram from "./SparklineHistogram"; +import FeatureFlagsContext from "../contexts/FeatureFlagsContext"; interface FeaturesListProps { featureViewName: string; @@ -11,6 +11,7 @@ interface FeaturesListProps { } const FeaturesList = ({ featureViewName, features }: FeaturesListProps) => { + const { enabledFeatureStatistics } = useContext(FeatureFlagsContext); const { isLoading, isError, isSuccess, data } = useLoadFeatureViewSummaryStatistics(featureViewName); diff --git a/ui/src/components/NoProjectGuard.tsx b/ui/src/components/NoProjectGuard.tsx index faa1fd92832..8501f6c9318 100644 --- a/ui/src/components/NoProjectGuard.tsx +++ b/ui/src/components/NoProjectGuard.tsx @@ -1,13 +1,17 @@ import { EuiEmptyPrompt, EuiLoadingContent } from "@elastic/eui"; -import React from "react"; +import React, { useContext } from "react"; import { Outlet, useParams } from "react-router-dom"; -import useLoadProjectsList from "../queries/useLoadProjectsList"; +import { + ProjectListContext, + useLoadProjectsList, +} from "../contexts/ProjectListContext"; import ProjectSelector from "./ProjectSelector"; const NoProjectGuard = () => { const { projectName } = useParams(); const { isLoading, isError, data } = useLoadProjectsList(); + const projectListContext = useContext(ProjectListContext); if (isLoading && !data) { return ; @@ -20,11 +24,18 @@ const NoProjectGuard = () => { color="danger" title={

Error Loading Project List

} body={ -

- Unable to find - projects-list.json. Check that you have a project list - file defined. -

+ projectListContext?.isCustom ? ( +

+ Unable to fetch project list. Check the promise provided to Feast + UI in projectListPromise. +

+ ) : ( +

+ Unable to find + projects-list.json. Check that you have a project + list file defined. +

+ ) } /> ); diff --git a/ui/src/components/ProjectSelector.test.tsx b/ui/src/components/ProjectSelector.test.tsx index c5b8d6cba38..0032b888398 100644 --- a/ui/src/components/ProjectSelector.test.tsx +++ b/ui/src/components/ProjectSelector.test.tsx @@ -3,7 +3,7 @@ import { render } from "../test-utils"; import { screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import App from "../App"; +import FeastUISansProviders from "../FeastUISansProviders"; import { projectsListWithDefaultProject, @@ -25,7 +25,7 @@ afterEach(() => server.resetHandlers()); afterAll(() => server.close()); test("in a full App render, it shows the right initial project", async () => { - render(); + render(); const select = await screen.findByRole("combobox", { name: "Select a Feast Project", @@ -40,7 +40,7 @@ test("in a full App render, it shows the right initial project", async () => { within(topLevelNavigation).getByDisplayValue("Credit Score Project"); - expect(options.length).toBe(2); + expect(options.length).toBe(1); // Wait for Project Data from Registry to Load await screen.findAllByRole("heading", { @@ -52,14 +52,6 @@ test("in a full App render, it shows the right initial project", async () => { name: /credit_scoring_aws/i, }); - // ... and Big Query Project is not selected - expect( - within(topLevelNavigation).getByRole("option", { - name: "Big Query Project", - selected: false, - }) - ).toBeInTheDocument(); - // Do the select option user event // https://stackoverflow.com/a/69478957 userEvent.selectOptions( @@ -67,14 +59,14 @@ test("in a full App render, it shows the right initial project", async () => { within(topLevelNavigation).getByRole("combobox"), // Find and select the Ireland option within(topLevelNavigation).getByRole("option", { - name: "Big Query Project", + name: "Credit Score Project", }) ); // The selection should updated expect( within(topLevelNavigation).getByRole("option", { - name: "Big Query Project", + name: "Credit Score Project", selected: true, }) ).toBeInTheDocument(); @@ -82,6 +74,6 @@ test("in a full App render, it shows the right initial project", async () => { // ... and the new heading should appear // meaning we successfully navigated await screen.findByRole("heading", { - name: /dbt_demo/i, + name: /credit_scoring_aws/i, }); }); diff --git a/ui/src/components/ProjectSelector.tsx b/ui/src/components/ProjectSelector.tsx index a1237e3d502..1bb7ebf85a7 100644 --- a/ui/src/components/ProjectSelector.tsx +++ b/ui/src/components/ProjectSelector.tsx @@ -1,7 +1,7 @@ import { EuiSelect, useGeneratedHtmlId } from "@elastic/eui"; import React from "react"; import { useNavigate, useParams } from "react-router-dom"; -import useLoadProjectsList from "../queries/useLoadProjectsList"; +import { useLoadProjectsList } from "../contexts/ProjectListContext"; const ProjectSelector = () => { const { projectName } = useParams(); diff --git a/ui/src/contexts/FeatureFlagsContext.ts b/ui/src/contexts/FeatureFlagsContext.ts new file mode 100644 index 00000000000..4b065d20754 --- /dev/null +++ b/ui/src/contexts/FeatureFlagsContext.ts @@ -0,0 +1,10 @@ +import React from "react"; + +interface FeatureFlags { + enabledFeatureStatistics?: boolean; +} + +const FeatureFlagsContext = React.createContext({}); + +export default FeatureFlagsContext; +export type { FeatureFlags }; diff --git a/ui/src/contexts/ProjectListContext.ts b/ui/src/contexts/ProjectListContext.ts new file mode 100644 index 00000000000..3ae8b572984 --- /dev/null +++ b/ui/src/contexts/ProjectListContext.ts @@ -0,0 +1,131 @@ +import React, { useContext, useState } from "react"; +import { useQuery } from "react-query"; + +import { z } from "zod"; + +const ProjectEntrySchema = z.object({ + id: z.string(), + name: z.string(), + description: z.string().optional(), + registryPath: z.string(), +}); + +const ProjectsListSchema = z.object({ + default: z.string().optional(), + projects: z.array(ProjectEntrySchema), +}); + +type ProjectsListType = z.infer; +interface ProjectsListContextInterface { + projectsListPromise: Promise; + isCustom: boolean; +} + +const ProjectListContext = React.createContext< + ProjectsListContextInterface | undefined +>(undefined); + +class ProjectListError extends Error { + constructor(message?: string | undefined) { + super(message); + this.name = "FeastProjectListError"; + } +} + +const projectListExampleString = ` + +\`\`\`json +{ + "projects": [ + { + "name": "Credit Score Project", + "description": "Project for credit scoring team and associated models.", + "id": "credit_score_project", + "registryPath": "/registry.json" + } + ] +} +\`\`\` +`; + +const anticipatedProjectListErrors = ( + err: Error, + isCustomProjectList: boolean +) => { + const isSyntaxError = err.stack?.indexOf("SyntaxError") === 0; + + // Straight up not a JSON + if (isSyntaxError) { + const message = `Unable to properly parse Project List JSON. Check that your project list is formatted properly.`; + + return new ProjectListError(message); + } + + // Some sort of 404 + const isFailedToFetch = err.message.indexOf("Failed to fetch") > -1; + if (isFailedToFetch) { + const followUpMessage = isCustomProjectList + ? "Check that the promise in your Feast UI configuration is set up properly." + : "Did you create a `project-list.json` file in the `/public/` directory? e.g." + + projectListExampleString; + + const message = "Failed to fetch Project List JSON. " + followUpMessage; + + return new ProjectListError(message); + } + + return null; +}; + +const useLoadProjectsList = () => { + const projectListPromise = useContext(ProjectListContext); + // Use setState to surface errors in Error Boundaries + // https://github.com/facebook/react/issues/14981#issuecomment-468460187 + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [_, setQueryError] = useState(undefined); + + return useQuery( + "feast-projects-list", + () => { + return projectListPromise?.projectsListPromise + .catch((e) => { + const anticipatedError = anticipatedProjectListErrors( + e, + projectListPromise.isCustom + ); + setQueryError(() => { + if (anticipatedError) { + throw anticipatedError; + } else { + throw new Error(e); + } + }); + }) + .then((json) => { + try { + const configs = ProjectsListSchema.parse(json); + return configs; + } catch (e) { + // If a json object is returned, but + // does not adhere to our anticipated + // format. + setQueryError(() => { + throw new ProjectListError( + `Error parsing project list JSON. JSON Object does not match expected type for a Feast project list. A project list JSON file should look like + ${projectListExampleString} + Zod (our parser) returned the following: \n\n${e}` + ); + }); + + throw new Error("Zod Error"); + } + }); + }, + { + enabled: !!projectListPromise?.projectsListPromise, + } + ); +}; + +export { ProjectListContext, ProjectsListSchema, useLoadProjectsList }; +export type { ProjectsListType, ProjectsListContextInterface }; diff --git a/ui/src/custom-tabs/CustomTabsRegistry.ts b/ui/src/custom-tabs/CustomTabsRegistry.ts deleted file mode 100644 index aa363beb120..00000000000 --- a/ui/src/custom-tabs/CustomTabsRegistry.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { - DatasetCustomTabRegistrationInterface, - DataSourceCustomTabRegistrationInterface, - EntityCustomTabRegistrationInterface, - FeatureServiceCustomTabRegistrationInterface, - OnDemandFeatureViewCustomTabRegistrationInterface, - RegularFeatureViewCustomTabRegistrationInterface, -} from "./types"; - -// How to add a Custom Tab -// 1. Pick which object type you want your tab -// to be in. e.g. Feature View, Feature Service, etc. -// -// 2. Write a regular React Component for Tab Content. -// It will be passed props with data about the Feast FCO -// e.g. RegularFeatureViewCustomTabProps, FeatureServiceCustomTabProps -// See: types.ts in this folder -// -// 3. Register the tab in the appropriate array below. Each entry -// is a record with three keys: label, path, and Component. -// Import your component and pass it as Component -import RFVDemoCustomTab from "./reguar-fv-demo-tab/DemoCustomTab"; -import ODFVDemoCustomTab from "./ondemand-fv-demo-tab/DemoCustomTab"; -import FSDemoCustomTab from "./feature-service-demo-tab/DemoCustomTab"; -import DSDemoCustomTab from "./data-source-demo-tab/DemoCustomTab"; -import EntDemoCustomTab from "./entity-demo-tab/DemoCustomTab"; -import DatasetDemoCustomTab from "./dataset-demo-tab/DemoCustomTab"; - -// Registry of Custom Tabs -const RegularFeatureViewCustomTabs: RegularFeatureViewCustomTabRegistrationInterface[] = - [ - { - label: "Custom Tab Demo", // Navigation Label for the tab - path: "demo-tab", // Subpath for the tab - Component: RFVDemoCustomTab, - }, - ]; - -const OnDemandFeatureViewCustomTabs: OnDemandFeatureViewCustomTabRegistrationInterface[] = - [ - { - label: "Custom Tab Demo", - path: "demo-tab", - Component: ODFVDemoCustomTab, - }, - ]; - -const FeatureServiceCustomTabs: FeatureServiceCustomTabRegistrationInterface[] = - [ - { - label: "Custom Tab Demo", - path: "fs-demo-tab", - Component: FSDemoCustomTab, - }, - ]; - -const DataSourceCustomTabs: DataSourceCustomTabRegistrationInterface[] = [ - { - label: "Custom Tab Demo", - path: "fs-demo-tab", - Component: DSDemoCustomTab, - }, -]; - -const EntityCustomTabs: EntityCustomTabRegistrationInterface[] = [ - { - label: "Custom Tab Demo", - path: "demo-tab", - Component: EntDemoCustomTab, - }, -]; - -const DatasetCustomTabs: DatasetCustomTabRegistrationInterface[] = [ - { - label: "Custom Tab Demo", - path: "demo-tab", - Component: DatasetDemoCustomTab, - }, -]; - -export { - RegularFeatureViewCustomTabs, - OnDemandFeatureViewCustomTabs, - FeatureServiceCustomTabs, - DataSourceCustomTabs, - EntityCustomTabs, - DatasetCustomTabs, -}; diff --git a/ui/src/pages/CustomTabUtils.tsx b/ui/src/custom-tabs/TabsRegistryContext.tsx similarity index 64% rename from ui/src/pages/CustomTabUtils.tsx rename to ui/src/custom-tabs/TabsRegistryContext.tsx index 577e1b86035..8ad58d7a16f 100644 --- a/ui/src/pages/CustomTabUtils.tsx +++ b/ui/src/custom-tabs/TabsRegistryContext.tsx @@ -1,30 +1,12 @@ -import React, { useState, useEffect } from "react"; +import React, { useEffect, useState } from "react"; -import { - DataSourceCustomTabs, - FeatureServiceCustomTabs, - RegularFeatureViewCustomTabs, - EntityCustomTabs, - OnDemandFeatureViewCustomTabs, - DatasetCustomTabs, -} from "../custom-tabs/CustomTabsRegistry"; import { useResolvedPath, resolvePath, useLocation, NavigateFunction, Route, -} from "react-router"; - -import { - CustomTabRegistrationInterface, - DataSourceCustomTabRegistrationInterface, - EntityCustomTabRegistrationInterface, - FeatureServiceCustomTabRegistrationInterface, - RegularFeatureViewCustomTabRegistrationInterface, - OnDemandFeatureViewCustomTabRegistrationInterface, - DatasetCustomTabRegistrationInterface, -} from "../custom-tabs/types"; +} from "react-router-dom"; import RegularFeatureViewCustomTabLoadingWrapper from "../utils/custom-tabs/RegularFeatureViewCustomTabLoadingWrapper"; import OnDemandFeatureViewCustomTabLoadingWrapper from "../utils/custom-tabs/OnDemandFeatureViewCustomTabLoadingWrapper"; @@ -33,12 +15,33 @@ import DataSourceCustomTabLoadingWrapper from "../utils/custom-tabs/DataSourceCu import EntityCustomTabLoadingWrapper from "../utils/custom-tabs/EntityCustomTabLoadingWrapper"; import DatasetCustomTabLoadingWrapper from "../utils/custom-tabs/DatasetCustomTabLoadingWrapper"; +import { + RegularFeatureViewCustomTabRegistrationInterface, + OnDemandFeatureViewCustomTabRegistrationInterface, + FeatureServiceCustomTabRegistrationInterface, + DataSourceCustomTabRegistrationInterface, + EntityCustomTabRegistrationInterface, + DatasetCustomTabRegistrationInterface, + CustomTabRegistrationInterface, +} from "./types"; + +interface FeastTabsRegistryInterface { + RegularFeatureViewCustomTabs?: RegularFeatureViewCustomTabRegistrationInterface[]; + OnDemandFeatureViewCustomTabs?: OnDemandFeatureViewCustomTabRegistrationInterface[]; + FeatureServiceCustomTabs?: FeatureServiceCustomTabRegistrationInterface[]; + DataSourceCustomTabs?: DataSourceCustomTabRegistrationInterface[]; + EntityCustomTabs?: EntityCustomTabRegistrationInterface[]; + DatasetCustomTabs?: DatasetCustomTabRegistrationInterface[]; +} + interface NavigationTabInterface { label: string; isSelected: boolean; onClick: () => void; } +const TabsRegistryContext = React.createContext({}); + const useGenericCustomTabsNavigation = < T extends CustomTabRegistrationInterface >( @@ -92,128 +95,163 @@ const useGenericCustomTabsNavigation = < }; }; +// Creating Routes +interface InnerComponent { + label: string; + path: string; + Component: (props: T) => JSX.Element; +} +type WrapperComponentType = ({ + Component, +}: { + Component: (props: T) => JSX.Element; +}) => JSX.Element; + +const genericCustomTabRoutes = ( + tabs: InnerComponent[], + WrapperComponent: WrapperComponentType +) => { + return tabs.map(({ path, Component }) => { + const WrappedComponent = () => { + return ; + }; + + return ( + } /> + ); + }); +}; + +// Navigation Hooks for Each Custom Tab Type const useRegularFeatureViewCustomTabs = (navigate: NavigateFunction) => { + const { RegularFeatureViewCustomTabs } = + React.useContext(TabsRegistryContext); + return useGenericCustomTabsNavigation( - RegularFeatureViewCustomTabs, + RegularFeatureViewCustomTabs || [], navigate ); }; const useOnDemandFeatureViewCustomTabs = (navigate: NavigateFunction) => { + const { OnDemandFeatureViewCustomTabs } = + React.useContext(TabsRegistryContext); + return useGenericCustomTabsNavigation( - OnDemandFeatureViewCustomTabs, + OnDemandFeatureViewCustomTabs || [], navigate ); }; const useFeatureServiceCustomTabs = (navigate: NavigateFunction) => { + const { FeatureServiceCustomTabs } = React.useContext(TabsRegistryContext); + return useGenericCustomTabsNavigation( - FeatureServiceCustomTabs, + FeatureServiceCustomTabs || [], navigate ); }; const useDataSourceCustomTabs = (navigate: NavigateFunction) => { + const { DataSourceCustomTabs } = React.useContext(TabsRegistryContext); + return useGenericCustomTabsNavigation( - DataSourceCustomTabs, + DataSourceCustomTabs || [], navigate ); }; const useEntityCustomTabs = (navigate: NavigateFunction) => { + const { EntityCustomTabs } = React.useContext(TabsRegistryContext); + return useGenericCustomTabsNavigation( - EntityCustomTabs, + EntityCustomTabs || [], navigate ); }; const useDatasetCustomTabs = (navigate: NavigateFunction) => { + const { DatasetCustomTabs } = React.useContext(TabsRegistryContext); + return useGenericCustomTabsNavigation( - DatasetCustomTabs, + DatasetCustomTabs || [], navigate ); }; -// Creating Routes -interface InnerComponent { - label: string; - path: string; - Component: (props: T) => JSX.Element; -} -type WrapperComponentType = ({ - Component, -}: { - Component: (props: T) => JSX.Element; -}) => JSX.Element; +// Routes for Each Custom Tab Type +const useRegularFeatureViewCustomTabRoutes = () => { + const { RegularFeatureViewCustomTabs } = + React.useContext(TabsRegistryContext); -const genericCustomTabRoutes = ( - tabs: InnerComponent[], - WrapperComponent: WrapperComponentType -) => { - return tabs.map(({ path, Component }) => { - const WrappedComponent = () => { - return ; - }; - - return ( - } /> - ); - }); -}; - -const regularFeatureViewCustomTabRoutes = () => { return genericCustomTabRoutes( - RegularFeatureViewCustomTabs, + RegularFeatureViewCustomTabs || [], RegularFeatureViewCustomTabLoadingWrapper ); }; -const onDemandFeatureViewCustomTabRoutes = () => { +const useOnDemandFeatureViewCustomTabRoutes = () => { + const { OnDemandFeatureViewCustomTabs } = + React.useContext(TabsRegistryContext); + return genericCustomTabRoutes( - OnDemandFeatureViewCustomTabs, + OnDemandFeatureViewCustomTabs || [], OnDemandFeatureViewCustomTabLoadingWrapper ); }; -const featureServiceCustomTabRoutes = () => { +const useFeatureServiceCustomTabRoutes = () => { + const { FeatureServiceCustomTabs } = React.useContext(TabsRegistryContext); + return genericCustomTabRoutes( - FeatureServiceCustomTabs, + FeatureServiceCustomTabs || [], FeatureServiceCustomTabLoadingWrapper ); }; -const dataSourceCustomTabRoutes = () => { +const useDataSourceCustomTabRoutes = () => { + const { DataSourceCustomTabs } = React.useContext(TabsRegistryContext); + return genericCustomTabRoutes( - DataSourceCustomTabs, + DataSourceCustomTabs || [], DataSourceCustomTabLoadingWrapper ); }; -const entityCustomTabRoutes = () => { +const useEntityCustomTabRoutes = () => { + const { EntityCustomTabs } = React.useContext(TabsRegistryContext); + return genericCustomTabRoutes( - EntityCustomTabs, + EntityCustomTabs || [], EntityCustomTabLoadingWrapper ); }; -const datasetCustomTabRoutes = () => { +const useDatasetCustomTabRoutes = () => { + const { DatasetCustomTabs } = React.useContext(TabsRegistryContext); + return genericCustomTabRoutes( - DatasetCustomTabs, + DatasetCustomTabs || [], DatasetCustomTabLoadingWrapper ); }; +export default TabsRegistryContext; export { + // Navigation useRegularFeatureViewCustomTabs, - regularFeatureViewCustomTabRoutes, useOnDemandFeatureViewCustomTabs, - onDemandFeatureViewCustomTabRoutes, useFeatureServiceCustomTabs, - featureServiceCustomTabRoutes, useDataSourceCustomTabs, - dataSourceCustomTabRoutes, useEntityCustomTabs, - entityCustomTabRoutes, useDatasetCustomTabs, - datasetCustomTabRoutes, + // Routes + useRegularFeatureViewCustomTabRoutes, + useOnDemandFeatureViewCustomTabRoutes, + useFeatureServiceCustomTabRoutes, + useDataSourceCustomTabRoutes, + useEntityCustomTabRoutes, + useDatasetCustomTabRoutes, }; + +export type { FeastTabsRegistryInterface }; diff --git a/ui/src/data-source-icon.svg b/ui/src/data-source-icon.svg deleted file mode 100644 index 51f2f9be9ab..00000000000 --- a/ui/src/data-source-icon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/ui/src/dataset-icon.svg b/ui/src/dataset-icon.svg deleted file mode 100644 index 49bcc990c84..00000000000 --- a/ui/src/dataset-icon.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/ui/src/entity-icon.svg b/ui/src/entity-icon.svg deleted file mode 100644 index 991e1dec758..00000000000 --- a/ui/src/entity-icon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/ui/src/feast-workmark.svg b/ui/src/feast-workmark.svg deleted file mode 100644 index 3257387737f..00000000000 --- a/ui/src/feast-workmark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ui/src/feature-service.svg b/ui/src/feature-service.svg deleted file mode 100644 index 81ec81e74db..00000000000 --- a/ui/src/feature-service.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/ui/src/feature-view.svg b/ui/src/feature-view.svg deleted file mode 100644 index 92102a4af33..00000000000 --- a/ui/src/feature-view.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/ui/src/flags.tsx b/ui/src/flags.tsx deleted file mode 100644 index 5c44beb8542..00000000000 --- a/ui/src/flags.tsx +++ /dev/null @@ -1,3 +0,0 @@ -const enabledFeatureStatistics = false; - -export { enabledFeatureStatistics }; diff --git a/ui/src/graphics/DataSourceIcon.tsx b/ui/src/graphics/DataSourceIcon.tsx new file mode 100644 index 00000000000..fdd92b87736 --- /dev/null +++ b/ui/src/graphics/DataSourceIcon.tsx @@ -0,0 +1,43 @@ +import React from "react"; + +const DataSourceIcon = ({ + size, + className, +}: { + size: number; + className?: string; +}) => { + return ( + + + + + ); +}; + +const DataSourceIcon16 = () => { + return ; +}; + +const DataSourceIcon32 = () => { + return ( + + ); +}; + +export { DataSourceIcon, DataSourceIcon16, DataSourceIcon32 }; diff --git a/ui/src/graphics/DatasetIcon.tsx b/ui/src/graphics/DatasetIcon.tsx new file mode 100644 index 00000000000..5c28f76f1d2 --- /dev/null +++ b/ui/src/graphics/DatasetIcon.tsx @@ -0,0 +1,52 @@ +import React from "react"; + +const DatasetIcon = ({ + size, + className, +}: { + size: number; + className?: string; +}) => { + return ( + + + + + + + + + + ); +}; + +const DatasetIcon16 = () => { + return ; +}; + +const DatasetIcon32 = () => { + return ( + + ); +}; + +export { DatasetIcon, DatasetIcon16, DatasetIcon32 }; diff --git a/ui/src/graphics/EntityIcon.tsx b/ui/src/graphics/EntityIcon.tsx new file mode 100644 index 00000000000..d9daf542a68 --- /dev/null +++ b/ui/src/graphics/EntityIcon.tsx @@ -0,0 +1,46 @@ +import React from "react"; + +const EntityIcon = ({ + size, + className, +}: { + size: number; + className?: string; +}) => { + return ( + + + + + ); +}; + +const EntityIcon16 = () => { + return ; +}; + +const EntityIcon32 = () => { + return ( + + ); +}; + +export { EntityIcon, EntityIcon16, EntityIcon32 }; diff --git a/ui/src/graphics/FeastIconBlue.tsx b/ui/src/graphics/FeastIconBlue.tsx new file mode 100644 index 00000000000..7bd99226eb4 --- /dev/null +++ b/ui/src/graphics/FeastIconBlue.tsx @@ -0,0 +1,18 @@ +import React from "react"; + +const FeastIconBlue = () => { + return ( + + + + + ); +}; + +export default FeastIconBlue; diff --git a/ui/src/graphics/FeastWordMark.tsx b/ui/src/graphics/FeastWordMark.tsx new file mode 100644 index 00000000000..576e416bd65 --- /dev/null +++ b/ui/src/graphics/FeastWordMark.tsx @@ -0,0 +1,26 @@ +import React from "react"; + +const FeastWordMark = () => { + return ( + + + + + + + ); +}; + +export default FeastWordMark; diff --git a/ui/src/graphics/FeatureServiceIcon.tsx b/ui/src/graphics/FeatureServiceIcon.tsx new file mode 100644 index 00000000000..04c4de9cd66 --- /dev/null +++ b/ui/src/graphics/FeatureServiceIcon.tsx @@ -0,0 +1,42 @@ +import React from "react"; + +const FeatureServiceIcon = ({ + size, + className, +}: { + size: number; + className?: string; +}) => { + return ( + + + + ); +}; + +const FeatureServiceIcon16 = () => { + return ( + + ); +}; + +const FeatureServiceIcon32 = () => { + return ( + + ); +}; + +export { FeatureServiceIcon, FeatureServiceIcon16, FeatureServiceIcon32 }; diff --git a/ui/src/graphics/FeatureViewIcon.tsx b/ui/src/graphics/FeatureViewIcon.tsx new file mode 100644 index 00000000000..f536953b11f --- /dev/null +++ b/ui/src/graphics/FeatureViewIcon.tsx @@ -0,0 +1,54 @@ +import React from "react"; + +const FeatureViewIcon = ({ + size, + className, +}: { + size: number; + className?: string; +}) => { + return ( + + + + + + ); +}; + +const FeatureViewIcon16 = () => { + return ; +}; + +const FeatureViewIcon32 = () => { + return ( + + ); +}; + +export { FeatureViewIcon, FeatureViewIcon16, FeatureViewIcon32 }; diff --git a/ui/src/hooks/encodeSearchQueryString.ts b/ui/src/hooks/encodeSearchQueryString.ts new file mode 100644 index 00000000000..547db30d375 --- /dev/null +++ b/ui/src/hooks/encodeSearchQueryString.ts @@ -0,0 +1,18 @@ +import { StringParam } from "use-query-params"; +import { encodeQueryParams } from "serialize-query-params"; +import { stringify } from "query-string"; + +const encodeSearchQueryString = (query: string) => { + return stringify( + encodeQueryParams( + { + tags: StringParam, + }, + { + tags: query, + } + ) + ); +}; + +export { encodeSearchQueryString }; diff --git a/ui/src/hooks/useFCOExploreSuggestions.ts b/ui/src/hooks/useFCOExploreSuggestions.ts index e6a2a1e0eb5..5767f73beda 100644 --- a/ui/src/hooks/useFCOExploreSuggestions.ts +++ b/ui/src/hooks/useFCOExploreSuggestions.ts @@ -1,4 +1,4 @@ -import { encodeSearchQueryString } from "./useSearchInputWithTags"; +import { encodeSearchQueryString } from "./encodeSearchQueryString"; import { FEAST_FCO_TYPES } from "../parsers/types"; import { FeastFeatureViewType } from "../parsers/feastFeatureViews"; diff --git a/ui/src/hooks/useMatchSubpath.ts b/ui/src/hooks/useMatchSubpath.ts index b8a72f9e3d7..4aabf53bc81 100644 --- a/ui/src/hooks/useMatchSubpath.ts +++ b/ui/src/hooks/useMatchSubpath.ts @@ -1,4 +1,4 @@ -import { useResolvedPath, useMatch } from "react-router"; +import { useResolvedPath, useMatch } from "react-router-dom"; const useMatchSubpath = (to: string) => { const resolved = useResolvedPath(to); diff --git a/ui/src/hooks/useSearchInputWithTags.ts b/ui/src/hooks/useSearchInputWithTags.ts index 53d6784a0ce..6683e65e00c 100644 --- a/ui/src/hooks/useSearchInputWithTags.ts +++ b/ui/src/hooks/useSearchInputWithTags.ts @@ -1,8 +1,6 @@ import { useState } from "react"; import { useQueryParam, StringParam } from "use-query-params"; -import { encodeQueryParams } from "serialize-query-params"; -import { stringify } from "query-string"; import { sortTagsByTotalUsage } from "./useFCOExploreSuggestions"; @@ -298,21 +296,7 @@ const useTagsWithSuggestions = ( }; }; -const encodeSearchQueryString = (query: string) => { - return stringify( - encodeQueryParams( - { - tags: StringParam, - }, - { - tags: query, - } - ) - ); -}; - export { useTagsWithSuggestions, useSearchQuery }; -export { encodeSearchQueryString }; export type { filterInputInterface, tagTokenGroupsType, diff --git a/ui/src/index.css b/ui/src/index.css index 60869353c81..46ca3ba295e 100644 --- a/ui/src/index.css +++ b/ui/src/index.css @@ -5,7 +5,7 @@ } html { - background: url("feast-icon-grey.svg") no-repeat -6vh 56vh; + background: url("assets/feast-icon-grey.svg") no-repeat -6vh 56vh; background-size: 50vh; background-attachment: fixed; } diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 21008a1103e..d4f1013503d 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -1,31 +1,82 @@ import React from "react"; import ReactDOM from "react-dom"; -import "./index.css"; -import App from "./App"; -import reportWebVitals from "./reportWebVitals"; -import { BrowserRouter } from "react-router-dom"; -import { QueryClient, QueryClientProvider } from "react-query"; -import { QueryParamProvider } from "use-query-params"; -import RouteAdapter from "./hacks/RouteAdapter"; +import { QueryClient } from "react-query"; +import FeastUI from "./FeastUI"; + +// How to add a Custom Tab +// 1. Pick which object type you want your tab +// to be in. e.g. Feature View, Feature Service, etc. +// +// 2. Write a regular React Component for Tab Content. +// It will be passed props with data about the Feast FCO +// e.g. RegularFeatureViewCustomTabProps, FeatureServiceCustomTabProps +// See: types.ts in this folder +// +// 3. Register the tab in the appropriate array below. Each entry +// is a record with three keys: label, path, and Component. +// Import your component and pass it as Component +import RFVDemoCustomTab from "./custom-tabs/reguar-fv-demo-tab/DemoCustomTab"; +import ODFVDemoCustomTab from "./custom-tabs/ondemand-fv-demo-tab/DemoCustomTab"; +import FSDemoCustomTab from "./custom-tabs/feature-service-demo-tab/DemoCustomTab"; +import DSDemoCustomTab from "./custom-tabs/data-source-demo-tab/DemoCustomTab"; +import EntDemoCustomTab from "./custom-tabs/entity-demo-tab/DemoCustomTab"; +import DatasetDemoCustomTab from "./custom-tabs/dataset-demo-tab/DemoCustomTab"; const queryClient = new QueryClient(); +const tabsRegistry = { + RegularFeatureViewCustomTabs: [ + { + label: "Custom Tab Demo", // Navigation Label for the tab + path: "demo-tab", // Subpath for the tab + Component: RFVDemoCustomTab, + }, + ], + OnDemandFeatureViewCustomTabs: [ + { + label: "Custom Tab Demo", + path: "demo-tab", + Component: ODFVDemoCustomTab, + }, + ], + FeatureServiceCustomTabs: [ + { + label: "Custom Tab Demo", + path: "fs-demo-tab", + Component: FSDemoCustomTab, + }, + ], + DataSourceCustomTabs: [ + { + label: "Custom Tab Demo", + path: "fs-demo-tab", + Component: DSDemoCustomTab, + }, + ], + EntityCustomTabs: [ + { + label: "Custom Tab Demo", + path: "demo-tab", + Component: EntDemoCustomTab, + }, + ], + DatasetCustomTabs: [ + { + label: "Custom Tab Demo", + path: "demo-tab", + Component: DatasetDemoCustomTab, + }, + ], +}; + ReactDOM.render( - - - - - - - + , document.getElementById("root") ); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/ui/src/mocks/handlers.ts b/ui/src/mocks/handlers.ts index f69458717e8..e7b0040f0dc 100644 --- a/ui/src/mocks/handlers.ts +++ b/ui/src/mocks/handlers.ts @@ -26,7 +26,4 @@ const creditHistoryRegistry = rest.get("/registry.json", (req, res, ctx) => { return res(ctx.status(200), ctx.json(registry)); }); -export { - projectsListWithDefaultProject, - creditHistoryRegistry -}; +export { projectsListWithDefaultProject, creditHistoryRegistry }; diff --git a/ui/src/pages/Layout.tsx b/ui/src/pages/Layout.tsx index f4f5efd0e3b..ff56414f354 100644 --- a/ui/src/pages/Layout.tsx +++ b/ui/src/pages/Layout.tsx @@ -8,15 +8,20 @@ import { EuiHorizontalRule, EuiSpacer, } from "@elastic/eui"; -import Sidebar from "./Sidebar"; -import { Outlet } from "react-router"; -import ProjectSelector from "../components/ProjectSelector"; -import { useParams } from "react-router-dom"; +import { Outlet } from "react-router-dom"; + import RegistryPathContext from "../contexts/RegistryPathContext"; -import useLoadProjectsList from "../queries/useLoadProjectsList"; -import feastWorkMark from "../feast-workmark.svg"; +import { useParams } from "react-router-dom"; +import { useLoadProjectsList } from "../contexts/ProjectListContext"; + +import ProjectSelector from "../components/ProjectSelector"; +import Sidebar from "./Sidebar"; +import FeastWordMark from "../graphics/FeastWordMark"; const Layout = () => { + // Registry Path Context has to be inside Layout + // because it has to be under routes + // in order to use useParams let { projectName } = useParams(); const { data } = useLoadProjectsList(); @@ -36,7 +41,7 @@ const Layout = () => { role={"navigation"} aria-label={"Top Level"} > - Feast + {registryPath && ( diff --git a/ui/src/pages/ProjectOverviewPage.tsx b/ui/src/pages/ProjectOverviewPage.tsx index 00e6bf1aa75..854af49375a 100644 --- a/ui/src/pages/ProjectOverviewPage.tsx +++ b/ui/src/pages/ProjectOverviewPage.tsx @@ -51,7 +51,7 @@ const ProjectOverviewPage = () => { body={

There was an error loading the Project Configurations. - Please check that feature_store.json file is + Please check that feature_store.yaml file is available and well-formed.

} @@ -70,7 +70,7 @@ const ProjectOverviewPage = () => { registered in Feast.

- It look like this project already have some objects + It looks like this project already has some objects registered. If you are new to this project, we suggest starting by exploring the Feature Services, as they represent the collection of Feature Views serving a diff --git a/ui/src/pages/RootProjectSelectionPage.tsx b/ui/src/pages/RootProjectSelectionPage.tsx index 115f7ba53b1..424e93c85d9 100644 --- a/ui/src/pages/RootProjectSelectionPage.tsx +++ b/ui/src/pages/RootProjectSelectionPage.tsx @@ -11,9 +11,9 @@ import { EuiTitle, EuiHorizontalRule, } from "@elastic/eui"; -import useLoadProjectsList from "../queries/useLoadProjectsList"; +import { useLoadProjectsList } from "../contexts/ProjectListContext"; import { useNavigate } from "react-router-dom"; -import feastIconBlue from "../feast-icon-blue.svg"; +import FeastIconBlue from "../graphics/FeastIconBlue"; const RootProjectSelectionPage = () => { const { isLoading, isSuccess, data } = useLoadProjectsList(); @@ -35,7 +35,7 @@ const RootProjectSelectionPage = () => { return ( } + icon={} title={`${item.name}`} description={item?.description || ""} onClick={() => { diff --git a/ui/src/pages/Sidebar.tsx b/ui/src/pages/Sidebar.tsx index 50081856e9d..9fc1a532f21 100644 --- a/ui/src/pages/Sidebar.tsx +++ b/ui/src/pages/Sidebar.tsx @@ -6,11 +6,11 @@ import { useMatchSubpath } from "../hooks/useMatchSubpath"; import useLoadRegistry from "../queries/useLoadRegistry"; import RegistryPathContext from "../contexts/RegistryPathContext"; -import DataSourceIcon from "../data-source-icon.svg"; -import EntityIcon from "../entity-icon.svg"; -import FeatureViewIcon from "../feature-view.svg"; -import FeatureServiceIcon from "../feature-service.svg"; -import DatasetIcon from "../dataset-icon.svg"; +import { DataSourceIcon16 } from "../graphics/DataSourceIcon"; +import { EntityIcon16 } from "../graphics/EntityIcon"; +import { FeatureViewIcon16 } from "../graphics/FeatureViewIcon"; +import { FeatureServiceIcon16 } from "../graphics/FeatureServiceIcon"; +import { DatasetIcon16 } from "../graphics/DatasetIcon"; const SideNav = () => { const registryUrl = useContext(RegistryPathContext); @@ -66,7 +66,7 @@ const SideNav = () => { { name: dataSourcesLabel, id: htmlIdGenerator("dataSources")(), - icon: , + icon: , onClick: () => { navigate(`/p/${projectName}/data-source`); }, @@ -75,7 +75,7 @@ const SideNav = () => { { name: entitiesLabel, id: htmlIdGenerator("entities")(), - icon: , + icon: , onClick: () => { navigate(`/p/${projectName}/entity`); }, @@ -84,7 +84,7 @@ const SideNav = () => { { name: featureViewsLabel, id: htmlIdGenerator("featureView")(), - icon: , + icon: , onClick: () => { navigate(`/p/${projectName}/feature-view`); }, @@ -93,7 +93,7 @@ const SideNav = () => { { name: featureServicesLabel, id: htmlIdGenerator("featureService")(), - icon: , + icon: , onClick: () => { navigate(`/p/${projectName}/feature-service`); }, @@ -102,7 +102,7 @@ const SideNav = () => { { name: savedDatasetsLabel, id: htmlIdGenerator("savedDatasets")(), - icon: , + icon: , onClick: () => { navigate(`/p/${projectName}/data-set`); }, diff --git a/ui/src/pages/data-sources/DataSourceDbt.tsx b/ui/src/pages/data-sources/DataSourceDbt.tsx index 43864a135ed..4e61ba80266 100644 --- a/ui/src/pages/data-sources/DataSourceDbt.tsx +++ b/ui/src/pages/data-sources/DataSourceDbt.tsx @@ -1,11 +1,11 @@ import React from "react"; -import { +import { EuiCodeBlock, - EuiPanel, + EuiPanel, EuiHorizontalRule, EuiTitle, - } from "@elastic/eui"; -import { useParams } from "react-router"; +} from "@elastic/eui"; +import { useParams } from "react-router-dom"; import useLoadDataSource from "./useLoadDataSource"; const DataSourceDbt = () => { @@ -26,7 +26,9 @@ const DataSourceDbt = () => { ) : ( - No data so sad + + No data so sad + ); }; diff --git a/ui/src/pages/data-sources/DataSourceIndexEmptyState.tsx b/ui/src/pages/data-sources/DataSourceIndexEmptyState.tsx index 1a925770cc6..9398c105dfe 100644 --- a/ui/src/pages/data-sources/DataSourceIndexEmptyState.tsx +++ b/ui/src/pages/data-sources/DataSourceIndexEmptyState.tsx @@ -1,12 +1,11 @@ import React from "react"; import { EuiEmptyPrompt, EuiTitle, EuiLink, EuiButton } from "@elastic/eui"; - -import feastIconBlue from "../../feast-icon-blue.svg"; +import FeastIconBlue from "../../graphics/FeastIconBlue"; const DataSourceIndexEmptyState = () => { return ( There are no data sources} body={

diff --git a/ui/src/pages/data-sources/DataSourceInstance.tsx b/ui/src/pages/data-sources/DataSourceInstance.tsx index f2ef3c9b9b3..332f51e0235 100644 --- a/ui/src/pages/data-sources/DataSourceInstance.tsx +++ b/ui/src/pages/data-sources/DataSourceInstance.tsx @@ -6,7 +6,7 @@ import { EuiPageContentBody, } from "@elastic/eui"; -import DataSourceIcon from "../../data-source-icon.svg"; +import { DataSourceIcon32 } from "../../graphics/DataSourceIcon"; import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; import { useDocumentTitle } from "../../hooks/useDocumentTitle"; import DataSourceRawData from "./DataSourceRawData"; @@ -16,8 +16,8 @@ import useLoadDataSource from "./useLoadDataSource"; import { useDataSourceCustomTabs, - dataSourceCustomTabRoutes, -} from "../CustomTabUtils"; + useDataSourceCustomTabRoutes, +} from "../../custom-tabs/TabsRegistryContext"; const DataSourceInstance = () => { const navigate = useNavigate(); @@ -51,11 +51,13 @@ const DataSourceInstance = () => { const { customNavigationTabs } = useDataSourceCustomTabs(navigate); tabs = tabs.concat(customNavigationTabs); + const CustomTabRoutes = useDataSourceCustomTabRoutes(); + return ( @@ -71,7 +73,7 @@ const DataSourceInstance = () => { } /> } /> } /> - {dataSourceCustomTabRoutes()} + {CustomTabRoutes} diff --git a/ui/src/pages/data-sources/DataSourceRawData.tsx b/ui/src/pages/data-sources/DataSourceRawData.tsx index 130eae6ba2a..ad4c7484a3c 100644 --- a/ui/src/pages/data-sources/DataSourceRawData.tsx +++ b/ui/src/pages/data-sources/DataSourceRawData.tsx @@ -1,6 +1,6 @@ import React from "react"; import { EuiPanel } from "@elastic/eui"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import useLoadDataSource from "./useLoadDataSource"; const DataSourceRawData = () => { @@ -15,7 +15,9 @@ const DataSourceRawData = () => {

{JSON.stringify(data, null, 2)}
) : ( - No data so sad + + No data so sad + ); }; diff --git a/ui/src/pages/data-sources/Index.tsx b/ui/src/pages/data-sources/Index.tsx index 1e36fca8577..81e3a967022 100644 --- a/ui/src/pages/data-sources/Index.tsx +++ b/ui/src/pages/data-sources/Index.tsx @@ -7,13 +7,12 @@ import { EuiLoadingSpinner, } from "@elastic/eui"; -import DataSourceIcon from "../../data-source-icon.svg"; - import useLoadRegistry from "../../queries/useLoadRegistry"; import DatasourcesListingTable from "./DataSourcesListingTable"; import { useDocumentTitle } from "../../hooks/useDocumentTitle"; import RegistryPathContext from "../../contexts/RegistryPathContext"; import DataSourceIndexEmptyState from "./DataSourceIndexEmptyState"; +import { DataSourceIcon32 } from "../../graphics/DataSourceIcon"; const useLoadDatasources = () => { const registryUrl = useContext(RegistryPathContext); @@ -39,7 +38,7 @@ const Index = () => { { return ( There are no entities} body={

diff --git a/ui/src/pages/entities/EntityInstance.tsx b/ui/src/pages/entities/EntityInstance.tsx index eef81b94098..b44967b1785 100644 --- a/ui/src/pages/entities/EntityInstance.tsx +++ b/ui/src/pages/entities/EntityInstance.tsx @@ -6,18 +6,21 @@ import { EuiPageContentBody, } from "@elastic/eui"; -import EntityIcon from "../../entity-icon.svg"; -import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; -import EntityRawData from "./EntityRawData"; +import { EntityIcon32 } from "../../graphics/EntityIcon"; +import { useMatchExact } from "../../hooks/useMatchSubpath"; import EntityOverviewTab from "./EntityOverviewTab"; import { useDocumentTitle } from "../../hooks/useDocumentTitle"; -import { useEntityCustomTabs, entityCustomTabRoutes } from "../CustomTabUtils"; +import { + useEntityCustomTabs, + useEntityCustomTabRoutes, +} from "../../custom-tabs/TabsRegistryContext"; const EntityInstance = () => { const navigate = useNavigate(); let { entityName } = useParams(); const { customNavigationTabs } = useEntityCustomTabs(navigate); + const CustomTabRoutes = useEntityCustomTabRoutes(); useDocumentTitle(`${entityName} | Entity | Feast`); @@ -25,7 +28,7 @@ const EntityInstance = () => { { } /> - {entityCustomTabRoutes()} + {CustomTabRoutes} diff --git a/ui/src/pages/entities/EntityOverviewTab.tsx b/ui/src/pages/entities/EntityOverviewTab.tsx index ed539ff5eed..dce0c12824d 100644 --- a/ui/src/pages/entities/EntityOverviewTab.tsx +++ b/ui/src/pages/entities/EntityOverviewTab.tsx @@ -9,6 +9,7 @@ import { EuiText, EuiFlexItem, EuiSpacer, + EuiStat, EuiDescriptionList, EuiDescriptionListTitle, EuiDescriptionListDescription, @@ -71,12 +72,20 @@ const EntityOverviewTab = () => { Created - {data.meta.createdTimestamp.toLocaleDateString("en-CA")} + {data.meta.createdTimestamp ? ( + data.meta.createdTimestamp.toLocaleDateString("en-CA") + ) : ( + No createdTimestamp specified on this entity. + )} Updated - {data.meta.lastUpdatedTimestamp.toLocaleDateString("en-CA")} + {data.meta.lastUpdatedTimestamp ? ( + data.meta.lastUpdatedTimestamp.toLocaleDateString("en-CA") + ) : ( + No lastUpdatedTimestamp specified on this entity. + )} diff --git a/ui/src/pages/entities/EntityRawData.tsx b/ui/src/pages/entities/EntityRawData.tsx index cabfbaf88a2..a6433566d75 100644 --- a/ui/src/pages/entities/EntityRawData.tsx +++ b/ui/src/pages/entities/EntityRawData.tsx @@ -1,6 +1,6 @@ import React from "react"; import { EuiPanel } from "@elastic/eui"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import useLoadEntity from "./useLoadEntity"; const EntityRawData = () => { @@ -15,7 +15,9 @@ const EntityRawData = () => {

{JSON.stringify(data, null, 2)}
) : ( - No data so sad + + No data so sad + ); }; diff --git a/ui/src/pages/entities/Index.tsx b/ui/src/pages/entities/Index.tsx index ed427804a93..43360f6866b 100644 --- a/ui/src/pages/entities/Index.tsx +++ b/ui/src/pages/entities/Index.tsx @@ -7,7 +7,7 @@ import { EuiLoadingSpinner, } from "@elastic/eui"; -import EntityIcon from "../../entity-icon.svg"; +import { EntityIcon32 } from "../../graphics/EntityIcon"; import useLoadRegistry from "../../queries/useLoadRegistry"; import EntitiesListingTable from "./EntitiesListingTable"; @@ -37,7 +37,11 @@ const Index = () => { return ( - + { return ( There are no feature services} body={

diff --git a/ui/src/pages/feature-services/FeatureServiceInstance.tsx b/ui/src/pages/feature-services/FeatureServiceInstance.tsx index 10b6130764d..cf0b09a0573 100644 --- a/ui/src/pages/feature-services/FeatureServiceInstance.tsx +++ b/ui/src/pages/feature-services/FeatureServiceInstance.tsx @@ -6,15 +6,15 @@ import { EuiPageContentBody, } from "@elastic/eui"; -import FeatureServiceIcon from "../../feature-service.svg"; +import { FeatureServiceIcon32 } from "../../graphics/FeatureServiceIcon"; import { useMatchExact } from "../../hooks/useMatchSubpath"; import FeatureServiceOverviewTab from "./FeatureServiceOverviewTab"; import { useDocumentTitle } from "../../hooks/useDocumentTitle"; import { useFeatureServiceCustomTabs, - featureServiceCustomTabRoutes, -} from "../CustomTabUtils"; + useFeatureServiceCustomTabRoutes, +} from "../../custom-tabs/TabsRegistryContext"; const FeatureServiceInstance = () => { const navigate = useNavigate(); @@ -23,12 +23,13 @@ const FeatureServiceInstance = () => { useDocumentTitle(`${featureServiceName} | Feature Service | Feast`); const { customNavigationTabs } = useFeatureServiceCustomTabs(navigate); + const CustomTabRoutes = useFeatureServiceCustomTabRoutes(); return ( { } /> - {featureServiceCustomTabRoutes()} + {CustomTabRoutes} diff --git a/ui/src/pages/feature-services/FeatureServiceListingTable.tsx b/ui/src/pages/feature-services/FeatureServiceListingTable.tsx index b452b6e4b63..c6205b020a9 100644 --- a/ui/src/pages/feature-services/FeatureServiceListingTable.tsx +++ b/ui/src/pages/feature-services/FeatureServiceListingTable.tsx @@ -9,7 +9,7 @@ import { FeastFeatureInServiceType, FeastFeatureServiceType, } from "../../parsers/feastFeatureServices"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; interface FeatureServiceListingTableProps { tagKeysSet: Set; diff --git a/ui/src/pages/feature-services/FeatureServiceOverviewTab.tsx b/ui/src/pages/feature-services/FeatureServiceOverviewTab.tsx index 1655a3624bd..a3fc897325b 100644 --- a/ui/src/pages/feature-services/FeatureServiceOverviewTab.tsx +++ b/ui/src/pages/feature-services/FeatureServiceOverviewTab.tsx @@ -12,11 +12,11 @@ import { EuiTitle, } from "@elastic/eui"; import React from "react"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import { useNavigate } from "react-router-dom"; import FeaturesInServiceList from "../../components/FeaturesInServiceDisplay"; import TagsDisplay from "../../components/TagsDisplay"; -import { encodeSearchQueryString } from "../../hooks/useSearchInputWithTags"; +import { encodeSearchQueryString } from "../../hooks/encodeSearchQueryString"; import FeatureViewEdgesList from "../entities/FeatureViewEdgesList"; import useLoadFeatureService from "./useLoadFeatureService"; diff --git a/ui/src/pages/feature-services/FeatureServiceRawData.tsx b/ui/src/pages/feature-services/FeatureServiceRawData.tsx index 0f171a05b6f..7fd8d2534a0 100644 --- a/ui/src/pages/feature-services/FeatureServiceRawData.tsx +++ b/ui/src/pages/feature-services/FeatureServiceRawData.tsx @@ -1,6 +1,6 @@ import React from "react"; import { EuiPanel } from "@elastic/eui"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import useLoadFeatureService from "./useLoadFeatureService"; const FeatureServiceRawData = () => { @@ -15,7 +15,9 @@ const FeatureServiceRawData = () => {

{JSON.stringify(data, null, 2)}
) : ( - No data so sad + + No data so sad + ); }; diff --git a/ui/src/pages/feature-services/Index.tsx b/ui/src/pages/feature-services/Index.tsx index 5f3f2c06335..441f3cf82c9 100644 --- a/ui/src/pages/feature-services/Index.tsx +++ b/ui/src/pages/feature-services/Index.tsx @@ -12,7 +12,7 @@ import { EuiFieldSearch, } from "@elastic/eui"; -import FeatureServiceIcon from "../../feature-service.svg"; +import { FeatureServiceIcon32 } from "../../graphics/FeatureServiceIcon"; import useLoadRegistry from "../../queries/useLoadRegistry"; import FeatureServiceListingTable from "./FeatureServiceListingTable"; @@ -115,7 +115,7 @@ const Index = () => { { return ( There are no feature views} body={

diff --git a/ui/src/pages/feature-views/FeatureViewRawData.tsx b/ui/src/pages/feature-views/FeatureViewRawData.tsx index 1347ef8dcfe..6bb71548137 100644 --- a/ui/src/pages/feature-views/FeatureViewRawData.tsx +++ b/ui/src/pages/feature-views/FeatureViewRawData.tsx @@ -1,6 +1,6 @@ import React from "react"; import { EuiPanel } from "@elastic/eui"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import useLoadFeatureView from "./useLoadFeatureView"; const FeatureViewRawData = () => { @@ -15,7 +15,9 @@ const FeatureViewRawData = () => {

{JSON.stringify(data, null, 2)}
) : ( - No data so sad + + No data so sad + ); }; diff --git a/ui/src/pages/feature-views/Index.tsx b/ui/src/pages/feature-views/Index.tsx index c54bd45b380..3abd42a22b2 100644 --- a/ui/src/pages/feature-views/Index.tsx +++ b/ui/src/pages/feature-views/Index.tsx @@ -12,7 +12,7 @@ import { EuiFlexItem, } from "@elastic/eui"; -import FeatureViewIcon from "../../feature-view.svg"; +import { FeatureViewIcon32 } from "../../graphics/FeatureViewIcon"; import useLoadRegistry from "../../queries/useLoadRegistry"; import FeatureViewListingTable from "./FeatureViewListingTable"; @@ -117,7 +117,7 @@ const Index = () => { { let { featureViewName } = useParams(); const { customNavigationTabs } = useOnDemandFeatureViewCustomTabs(navigate); + const CustomTabRoutes = useOnDemandFeatureViewCustomTabRoutes(); return ( { path="/" element={} /> - {onDemandFeatureViewCustomTabRoutes()} + {CustomTabRoutes} diff --git a/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx b/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx index 05f5c994375..7200163614b 100644 --- a/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx +++ b/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx @@ -1,13 +1,13 @@ -import React from "react"; -import { Route, Routes, useNavigate } from "react-router"; +import React, { useContext } from "react"; +import { Route, Routes, useNavigate } from "react-router-dom"; import { EuiPageHeader, EuiPageContent, EuiPageContentBody, } from "@elastic/eui"; -import FeatureViewIcon from "../../feature-view.svg"; -import { enabledFeatureStatistics } from "../,,/../../flags"; +import { FeatureViewIcon32 } from "../../graphics/FeatureViewIcon"; + import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; import { FeastFeatureViewType } from "../../parsers/feastFeatureViews"; import RegularFeatureViewOverviewTab from "./RegularFeatureViewOverviewTab"; @@ -15,14 +15,16 @@ import FeatureViewSummaryStatisticsTab from "./FeatureViewSummaryStatisticsTab"; import { useRegularFeatureViewCustomTabs, - regularFeatureViewCustomTabRoutes, -} from "../CustomTabUtils"; + useRegularFeatureViewCustomTabRoutes, +} from "../../custom-tabs/TabsRegistryContext"; +import FeatureFlagsContext from "../../contexts/FeatureFlagsContext"; interface RegularFeatureInstanceProps { data: FeastFeatureViewType; } const RegularFeatureInstance = ({ data }: RegularFeatureInstanceProps) => { + const { enabledFeatureStatistics } = useContext(FeatureFlagsContext); const navigate = useNavigate(); const { customNavigationTabs } = useRegularFeatureViewCustomTabs(navigate); @@ -49,11 +51,13 @@ const RegularFeatureInstance = ({ data }: RegularFeatureInstanceProps) => { tabs.push(...customNavigationTabs); + const TabRoutes = useRegularFeatureViewCustomTabRoutes(); + return ( @@ -74,7 +78,7 @@ const RegularFeatureInstance = ({ data }: RegularFeatureInstanceProps) => { path="/statistics" element={} /> - {regularFeatureViewCustomTabRoutes()} + {TabRoutes}
diff --git a/ui/src/pages/feature-views/RegularFeatureViewOverviewTab.tsx b/ui/src/pages/feature-views/RegularFeatureViewOverviewTab.tsx index 70a7fdec173..72ea646c95f 100644 --- a/ui/src/pages/feature-views/RegularFeatureViewOverviewTab.tsx +++ b/ui/src/pages/feature-views/RegularFeatureViewOverviewTab.tsx @@ -11,10 +11,10 @@ import { } from "@elastic/eui"; import React from "react"; -import { useNavigate, useParams } from "react-router"; +import { useNavigate, useParams } from "react-router-dom"; import FeaturesListDisplay from "../../components/FeaturesListDisplay"; import TagsDisplay from "../../components/TagsDisplay"; -import { encodeSearchQueryString } from "../../hooks/useSearchInputWithTags"; +import { encodeSearchQueryString } from "../../hooks/encodeSearchQueryString"; import { FeastFeatureViewType } from "../../parsers/feastFeatureViews"; import { EntityRelation } from "../../parsers/parseEntityRelationships"; import { FEAST_FCO_TYPES } from "../../parsers/types"; @@ -60,7 +60,7 @@ const RegularFeatureViewOverviewTab = ({ - {data.spec.batchSource.meta && ( + {data.spec.batchSource.meta ? ( + ) : ( + No batchSource specified on this feature view. )} - {data.meta.lastUpdatedTimestamp && ( { diff --git a/ui/src/pages/saved-data-sets/DatasetInstance.tsx b/ui/src/pages/saved-data-sets/DatasetInstance.tsx index e2714d42235..26df0b3eb3d 100644 --- a/ui/src/pages/saved-data-sets/DatasetInstance.tsx +++ b/ui/src/pages/saved-data-sets/DatasetInstance.tsx @@ -6,16 +6,16 @@ import { EuiPageContentBody, } from "@elastic/eui"; -import DatasetIcon from "../../dataset-icon.svg"; +import { DatasetIcon32 } from "../../graphics/DatasetIcon"; import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; import DatasetOverviewTab from "./DatasetOverviewTab"; import { useDocumentTitle } from "../../hooks/useDocumentTitle"; import DatasetExpectationsTab from "./DatasetExpectationsTab"; import { - datasetCustomTabRoutes, useDatasetCustomTabs, -} from "../CustomTabUtils"; + useDataSourceCustomTabRoutes, +} from "../../custom-tabs/TabsRegistryContext"; const DatasetInstance = () => { const navigate = useNavigate(); @@ -24,12 +24,13 @@ const DatasetInstance = () => { useDocumentTitle(`${datasetName} | Saved Datasets | Feast`); const { customNavigationTabs } = useDatasetCustomTabs(navigate); + const CustomTabRoutes = useDataSourceCustomTabRoutes(); return ( { } /> } /> - {datasetCustomTabRoutes()} + {CustomTabRoutes}
diff --git a/ui/src/pages/saved-data-sets/DatasetRawData.tsx b/ui/src/pages/saved-data-sets/DatasetRawData.tsx index efd17abcb6d..9f335800e9a 100644 --- a/ui/src/pages/saved-data-sets/DatasetRawData.tsx +++ b/ui/src/pages/saved-data-sets/DatasetRawData.tsx @@ -1,6 +1,6 @@ import React from "react"; import { EuiPanel } from "@elastic/eui"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import useLoadDataset from "./useLoadDataset"; const EntityRawData = () => { diff --git a/ui/src/pages/saved-data-sets/DatasetsIndexEmptyState.tsx b/ui/src/pages/saved-data-sets/DatasetsIndexEmptyState.tsx index 535a5fa1209..44f56ba2ddf 100644 --- a/ui/src/pages/saved-data-sets/DatasetsIndexEmptyState.tsx +++ b/ui/src/pages/saved-data-sets/DatasetsIndexEmptyState.tsx @@ -1,12 +1,11 @@ import React from "react"; import { EuiEmptyPrompt, EuiTitle, EuiLink, EuiButton } from "@elastic/eui"; - -import feastIconBlue from "../../feast-icon-blue.svg"; +import FeastIconBlue from "../../graphics/FeastIconBlue"; const DatasetsIndexEmptyState = () => { return ( There are no saved datasets} body={

diff --git a/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx b/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx index 6b85c86b168..97d11b0b24c 100644 --- a/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx +++ b/ui/src/pages/saved-data-sets/DatasetsListingTable.tsx @@ -1,7 +1,7 @@ import React from "react"; import { EuiBasicTable } from "@elastic/eui"; import EuiCustomLink from "../../components/EuiCustomLink"; -import { useParams } from "react-router"; +import { useParams } from "react-router-dom"; import { FeastSavedDatasetType } from "../../parsers/feastSavedDataset"; interface DatasetsListingTableProps { diff --git a/ui/src/pages/saved-data-sets/Index.tsx b/ui/src/pages/saved-data-sets/Index.tsx index 0d551982794..5f20621bafd 100644 --- a/ui/src/pages/saved-data-sets/Index.tsx +++ b/ui/src/pages/saved-data-sets/Index.tsx @@ -7,7 +7,7 @@ import { EuiLoadingSpinner, } from "@elastic/eui"; -import DatasetIcon from "../../dataset-icon.svg"; +import { DatasetIcon32 } from "../../graphics/DatasetIcon"; import useLoadRegistry from "../../queries/useLoadRegistry"; import { useDocumentTitle } from "../../hooks/useDocumentTitle"; @@ -39,7 +39,7 @@ const Index = () => { new Date(val)), - lastUpdatedTimestamp: z.string().transform((val) => new Date(val)), + createdTimestamp: z.string().transform((val) => new Date(val)).optional(), + lastUpdatedTimestamp: z.string().transform((val) => new Date(val)).optional(), }), }); diff --git a/ui/src/parsers/feastFeatureViews.ts b/ui/src/parsers/feastFeatureViews.ts index 013f70b1fe7..c8cdadd25c3 100644 --- a/ui/src/parsers/feastFeatureViews.ts +++ b/ui/src/parsers/feastFeatureViews.ts @@ -13,7 +13,7 @@ const FeastBatchSourceSchema = z.object({ fileOptions: z.object({ fileUrl: z.string().optional(), }).optional(), - name: z.string(), + name: z.string().optional(), meta: z.object({ earliestEventTimestamp: z.string().transform((val) => new Date(val)), latestEventTimestamp: z.string().transform((val) => new Date(val)), @@ -39,8 +39,8 @@ const FeastFeatureViewSchema = z.object({ tags: z.record(z.string()).optional(), }), meta: z.object({ - createdTimestamp: z.string().transform((val) => new Date(val)), - lastUpdatedTimestamp: z.string().transform((val) => new Date(val)), + createdTimestamp: z.string().transform((val) => new Date(val)).optional(), + lastUpdatedTimestamp: z.string().transform((val) => new Date(val)).optional(), materializationIntervals: z .array( z.object({ diff --git a/ui/src/parsers/parseEntityRelationships.ts b/ui/src/parsers/parseEntityRelationships.ts index f6e1b1af1f7..bf82e86ff9c 100644 --- a/ui/src/parsers/parseEntityRelationships.ts +++ b/ui/src/parsers/parseEntityRelationships.ts @@ -46,7 +46,7 @@ const parseEntityRelationships = (objects: FeastRegistryType) => { links.push({ source: { type: FEAST_FCO_TYPES["dataSource"], - name: fv.spec.batchSource.name + name: fv.spec.batchSource.name || '' }, target: { type: FEAST_FCO_TYPES["featureView"], @@ -77,7 +77,7 @@ const parseEntityRelationships = (objects: FeastRegistryType) => { links.push({ source: { type: FEAST_FCO_TYPES["dataSource"], - name: source_fv?.spec.batchSource.name, + name: source_fv?.spec.batchSource.name || '', }, target: { type: FEAST_FCO_TYPES["featureView"], diff --git a/ui/src/parsers/types.ts b/ui/src/parsers/types.ts index e32d5b102ea..2f88eea4f06 100644 --- a/ui/src/parsers/types.ts +++ b/ui/src/parsers/types.ts @@ -13,7 +13,17 @@ enum FEAST_FEATURE_VALUE_TYPES { BYTES = "BYTES", INT32 = "INT32", DOUBLE = "DOUBLE", - UNIX_TIMESTAMP = "UNIX_TIMESTAMP" + UNIX_TIMESTAMP = "UNIX_TIMESTAMP", + INVALID = "INVALID", + BYTES_LIST = "BYTES_LIST", + STRING_LIST = "STRING_LIST", + INT32_LIST = "INT32_LIST", + INT64_LIST = "INT64_LIST", + DOUBLE_LIST = "DOUBLE_LIST", + FLOAT_LIST = "FLOAT_LIST", + BOOL_LIST = "BOOL_LIST", + UNIX_TIMESTAMP_LIST = "UNIX_TIMESTAMP_LIST", + NULL = "NULL" } export { FEAST_FCO_TYPES, FEAST_FEATURE_VALUE_TYPES }; diff --git a/ui/src/queries/useLoadProjectsList.ts b/ui/src/queries/useLoadProjectsList.ts deleted file mode 100644 index 2383a793192..00000000000 --- a/ui/src/queries/useLoadProjectsList.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useQuery } from "react-query"; -import { z } from "zod"; - -const ProjectEntrySchema = z.object({ - id: z.string(), - name: z.string(), - description: z.string().optional(), - registryPath: z.string(), -}); - -const ProjectsListSchema = z.object({ - default: z.string().optional(), - projects: z.array(ProjectEntrySchema), -}); - -type ProjectsListType = z.infer; - -const useLoadProjectsList = () => { - return useQuery("feast-projects-list", () => { - return fetch("/projects-list.json", { - headers: { - "Content-Type": "application/json", - }, - }) - .then((res) => { - return res.json(); - }) - .then((json) => { - const configs = ProjectsListSchema.parse(json); - - return configs; - }); - }); -}; - -export default useLoadProjectsList; -export type { ProjectsListType }; diff --git a/ui/src/reportWebVitals.ts b/ui/src/reportWebVitals.ts deleted file mode 100644 index 49a2a16e0fb..00000000000 --- a/ui/src/reportWebVitals.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ReportHandler } from 'web-vitals'; - -const reportWebVitals = (onPerfEntry?: ReportHandler) => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals; diff --git a/ui/yarn.lock b/ui/yarn.lock index 2d523de6582..396204ffb4d 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -10,9 +10,9 @@ "@jridgewell/trace-mapping" "^0.3.0" "@apideck/better-ajv-errors@^0.3.1": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.3.tgz#ab0b1e981e1749bf59736cf7ebe25cfc9f949c15" - integrity sha512-9o+HO2MbJhJHjDYZaDxJmSDckvDpiuItEsrIShV0DXeCshXWRHhqYyU/PKHMkuClOmFnZhRd6wzv4vpDu/dRKg== + version "0.3.2" + resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.2.tgz#cd6d3814eda8aee38ee2e3fa6457be43af4f8361" + integrity sha512-JdEazx7qiVqTBzzBl5rolRwl5cmhihjfIcpqRzIZjtT6b18liVmDn/VlWpqW4C/qP2hrFFMLRV1wlex8ZVBPTg== dependencies: json-schema "^0.4.0" jsonpointer "^5.0.0" @@ -25,12 +25,33 @@ dependencies: "@babel/highlight" "^7.16.7" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" + integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== "@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" + integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.16.7" + "@babel/parser" "^7.16.12" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.10" + "@babel/types" "^7.16.8" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/core@^7.17.5": version "7.17.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== @@ -52,15 +73,24 @@ semver "^6.3.0" "@babel/eslint-parser@^7.16.3": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz#eabb24ad9f0afa80e5849f8240d0e5facc2d90d6" - integrity sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA== + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.16.5.tgz#48d3485091d6e36915358e4c0d0b2ebe6da90462" + integrity sha512-mUqYa46lgWqHKQ33Q6LNCGp/wPR3eqOYTUixHFsfrSQqRxH0+WOzca75iEjFr5RDGH1dDz622LaHhLOzOuQRUA== dependencies: eslint-scope "^5.1.1" eslint-visitor-keys "^2.1.0" semver "^6.3.0" -"@babel/generator@^7.17.3", "@babel/generator@^7.7.2": +"@babel/generator@^7.16.8", "@babel/generator@^7.7.2": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== + dependencies: + "@babel/types" "^7.16.8" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.17.3": version "7.17.3" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== @@ -94,10 +124,10 @@ browserslist "^4.17.5" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.1", "@babel/helper-create-class-features-plugin@^7.17.6": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9" - integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg== +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz#8a6959b9cc818a88815ba3c5474619e9c0f2c21c" + integrity sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -108,12 +138,12 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" - integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz#0cb82b9bac358eb73bfbd73985a776bfa6b14d48" + integrity sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^5.0.1" + regexpu-core "^4.7.1" "@babel/helper-define-polyfill-provider@^0.3.1": version "0.3.1" @@ -181,9 +211,9 @@ "@babel/types" "^7.16.7" "@babel/helper-module-transforms@^7.16.7": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz#3c3b03cc6617e33d68ef5a27a67419ac5199ccd0" - integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -191,8 +221,8 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" "@babel/helper-optimise-call-expression@^7.16.7": version "7.16.7" @@ -267,6 +297,15 @@ "@babel/traverse" "^7.16.8" "@babel/types" "^7.16.8" +"@babel/helpers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc" + integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helpers@^7.17.2": version "7.17.2" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" @@ -285,7 +324,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3": +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.10", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6" + integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== + +"@babel/parser@^7.17.3": version "7.17.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== @@ -324,24 +368,22 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz#164e8fd25f0d80fa48c5a4d1438a6629325ad83c" - integrity sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" + integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.17.6" + "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-decorators@^7.16.4": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.2.tgz#c36372ddfe0360cac1ee331a238310bddca11493" - integrity sha512-WH8Z95CwTq/W8rFbMqb9p3hicpt4RX4f0K659ax2VHxgOyT6qQmUaEVEjIh4WR9Eh9NymkVn5vwsrE68fAQNUw== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.16.7.tgz#922907d2e3e327f5b07d2246bcfc0bd438f360d2" + integrity sha512-DoEpnuXK14XV9btI1k8tzNGCutMclpj4yru8aXKoHlVmbO1s+2A+g2+h4JhcjrxkFJqzbymnLG6j/niOf3iFXQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.17.1" + "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/plugin-syntax-decorators" "^7.17.0" - charcodes "^0.2.0" + "@babel/plugin-syntax-decorators" "^7.16.7" "@babel/plugin-proposal-dynamic-import@^7.16.7": version "7.16.7" @@ -392,11 +434,11 @@ "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" - integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8" + integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== dependencies: - "@babel/compat-data" "^7.17.0" + "@babel/compat-data" "^7.16.4" "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" @@ -473,10 +515,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-decorators@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz#a2be3b2c9fe7d78bd4994e790896bc411e2f166d" - integrity sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A== +"@babel/plugin-syntax-decorators@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.7.tgz#f66a0199f16de7c1ef5192160ccf5d069739e3d3" + integrity sha512-vQ+PxL+srA7g6Rx6I1e15m55gftknl2X8GCUW1JTlkTaXZLJOS0UcaY0eK9jYT7IYf4awn6qwyghVHLDz1WyMw== dependencies: "@babel/helper-plugin-utils" "^7.16.7" @@ -515,7 +557,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.16.7": +"@babel/plugin-syntax-jsx@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== @@ -637,9 +679,9 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-destructuring@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" - integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23" + integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== dependencies: "@babel/helper-plugin-utils" "^7.16.7" @@ -779,9 +821,9 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-constant-elements@^7.12.1": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.6.tgz#6cc273c2f612a6a50cb657e63ee1303e5e68d10a" - integrity sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" + integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== dependencies: "@babel/helper-plugin-utils" "^7.16.7" @@ -800,15 +842,15 @@ "@babel/plugin-transform-react-jsx" "^7.16.7" "@babel/plugin-transform-react-jsx@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" - integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz#86a6a220552afd0e4e1f0388a68a372be7add0d4" + integrity sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-jsx" "^7.16.7" - "@babel/types" "^7.17.0" + "@babel/types" "^7.16.7" "@babel/plugin-transform-react-pure-annotations@^7.16.7": version "7.16.7" @@ -833,9 +875,9 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-runtime@^7.16.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" - integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.10.tgz#53d9fd3496daedce1dd99639097fa5d14f4c7c2c" + integrity sha512-9nwTiqETv2G7xI4RvXHNfpGdr8pAA+Q/YtN3yLK7OoK7n9OibVm/xymJ838a9A6E/IciOLPj82lZk0fW6O4O7w== dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" @@ -904,7 +946,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.4": +"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.11", "@babel/preset-env@^7.16.4": version "7.16.11" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== @@ -995,7 +1037,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0": +"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0", "@babel/preset-react@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== @@ -1017,17 +1059,17 @@ "@babel/plugin-transform-typescript" "^7.16.7" "@babel/runtime-corejs3@^7.10.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13" - integrity sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg== + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz#ea533d96eda6fdc76b1812248e9fbd0c11d4a1a7" + integrity sha512-3fKhuICS1lMz0plI5ktOE/yEtBRMVxplzRkdn6mJQ197XiY0JnrzYV0+Mxozq3JZ8SBV9Ecurmw1XsGbwOf+Sg== dependencies: core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" - integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" + integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== dependencies: regenerator-runtime "^0.13.4" @@ -1040,7 +1082,23 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.7.2": +"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.7.2": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f" + integrity sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.16.10" + "@babel/types" "^7.16.8" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": version "7.17.3" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== @@ -1056,7 +1114,15 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" + integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@babel/types@^7.17.0": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== @@ -1064,11 +1130,6 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" -"@base2/pretty-print-object@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" - integrity sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA== - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1079,65 +1140,6 @@ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-12.0.0.tgz#a9583a75c3f150667771f30b60d9f059473e62c4" integrity sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg== -"@csstools/postcss-color-function@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-1.0.2.tgz#0843fe19be08eeb22e5d2242a6ac06f8b87b9ed2" - integrity sha512-uayvFqfa0hITPwVduxRYNL9YBD/anTqula0tu2llalaxblEd7QPuETSN3gB5PvTYxSfd0d8kS4Fypgo5JaUJ6A== - dependencies: - "@csstools/postcss-progressive-custom-properties" "^1.1.0" - postcss-value-parser "^4.2.0" - -"@csstools/postcss-font-format-keywords@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.0.tgz#7e7df948a83a0dfb7eb150a96e2390ac642356a1" - integrity sha512-oO0cZt8do8FdVBX8INftvIA4lUrKUSCcWUf9IwH9IPWOgKT22oAZFXeHLoDK7nhB2SmkNycp5brxfNMRLIhd6Q== - dependencies: - postcss-value-parser "^4.2.0" - -"@csstools/postcss-hwb-function@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.0.tgz#d6785c1c5ba8152d1d392c66f3a6a446c6034f6d" - integrity sha512-VSTd7hGjmde4rTj1rR30sokY3ONJph1reCBTUXqeW1fKwETPy1x4t/XIeaaqbMbC5Xg4SM/lyXZ2S8NELT2TaA== - dependencies: - postcss-value-parser "^4.2.0" - -"@csstools/postcss-ic-unit@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.0.tgz#f484db59fc94f35a21b6d680d23b0ec69b286b7f" - integrity sha512-i4yps1mBp2ijrx7E96RXrQXQQHm6F4ym1TOD0D69/sjDjZvQ22tqiEvaNw7pFZTUO5b9vWRHzbHzP9+UKuw+bA== - dependencies: - "@csstools/postcss-progressive-custom-properties" "^1.1.0" - postcss-value-parser "^4.2.0" - -"@csstools/postcss-is-pseudo-class@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.0.tgz#219a1c1d84de7d9e9b7e662a57fdc194eac38ea7" - integrity sha512-WnfZlyuh/CW4oS530HBbrKq0G8BKl/bsNr5NMFoubBFzJfvFRGJhplCgIJYWUidLuL3WJ/zhMtDIyNFTqhx63Q== - dependencies: - postcss-selector-parser "^6.0.9" - -"@csstools/postcss-normalize-display-values@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.0.tgz#ce698f688c28517447aedf15a9037987e3d2dc97" - integrity sha512-bX+nx5V8XTJEmGtpWTO6kywdS725t71YSLlxWt78XoHUbELWgoCXeOFymRJmL3SU1TLlKSIi7v52EWqe60vJTQ== - dependencies: - postcss-value-parser "^4.2.0" - -"@csstools/postcss-oklab-function@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.0.1.tgz#a12348eae202d4ded908a06aa92cf19a946b6cec" - integrity sha512-Bnly2FWWSTZX20hDJLYHpurhp1ot+ZGvojLOsrHa9frzOVruOv4oPYMZ6wQomi9KsbZZ+Af/CuRYaGReTyGtEg== - dependencies: - "@csstools/postcss-progressive-custom-properties" "^1.1.0" - postcss-value-parser "^4.2.0" - -"@csstools/postcss-progressive-custom-properties@^1.1.0", "@csstools/postcss-progressive-custom-properties@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.2.0.tgz#7d53b773de50874c3885918dcb10cac97bf66ed5" - integrity sha512-YLpFPK5OaLIRKZhUfnrZPT9s9cmtqltIOg7W6jPcxmiDpnZ4lk+odfufZttOAgcg6IHWvNLgcITSLpJxIQB/qQ== - dependencies: - postcss-value-parser "^4.2.0" - "@elastic/datemath@^5.0.3": version "5.0.3" resolved "https://registry.yarnpkg.com/@elastic/datemath/-/datemath-5.0.3.tgz#7baccdab672b9a3ecb7fe8387580670936b58573" @@ -1145,18 +1147,18 @@ dependencies: tslib "^1.9.3" -"@elastic/eui@^50.0.0": - version "50.0.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-50.0.0.tgz#f744ff437c80b48f352fa53d17930e4824b3e0ae" - integrity sha512-wt98SiSX3OAL+5+JD2SnZf4DNzjFSYzLXJJ7e9VYVX2QhE5ucOJXg2sUQ97Tj6J9xLWctpsZT3llkiGeT4yc4Q== +"@elastic/eui@^46.1.0": + version "46.1.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-46.1.0.tgz#b1d77a56d529001858b7fc91f6c2953288549336" + integrity sha512-j65NMzqKluVPtk3b6UYdVVaBha74Y8Y/N6QaHin9MmqUKoAPgevqHWvi0n/OmMpADdRCI0ldxkse6tgAvdaEHQ== dependencies: "@types/chroma-js" "^2.0.0" "@types/lodash" "^4.14.160" "@types/numeral" "^0.0.28" - "@types/react-beautiful-dnd" "^13.1.2" - "@types/react-input-autosize" "^2.2.1" - "@types/react-virtualized-auto-sizer" "^1.0.1" - "@types/react-window" "^1.8.5" + "@types/react-beautiful-dnd" "^13.0.0" + "@types/react-input-autosize" "^2.2.0" + "@types/react-virtualized-auto-sizer" "^1.0.0" + "@types/react-window" "^1.8.2" "@types/refractor" "^3.0.0" "@types/resize-observer-browser" "^0.1.5" "@types/vfile-message" "^2.0.0" @@ -1166,14 +1168,13 @@ mdast-util-to-hast "^10.0.0" numeral "^2.0.6" prop-types "^15.6.0" - react-beautiful-dnd "^13.1.0" - react-dropzone "^11.5.3" - react-element-to-jsx-string "^14.3.4" - react-focus-on "^3.5.4" - react-input-autosize "^3.0.0" - react-is "^17.0.2" - react-virtualized-auto-sizer "^1.0.6" - react-window "^1.8.6" + react-beautiful-dnd "^13.0.0" + react-dropzone "^11.2.0" + react-focus-on "^3.5.0" + react-input-autosize "^2.2.2" + react-is "~16.3.0" + react-virtualized-auto-sizer "^1.0.2" + react-window "^1.8.5" refractor "^3.5.0" rehype-raw "^5.0.0" rehype-react "^6.0.0" @@ -1186,28 +1187,10 @@ text-diff "^1.0.1" unified "^9.2.0" unist-util-visit "^2.0.3" - url-parse "^1.5.10" + url-parse "^1.5.3" uuid "^8.3.0" vfile "^4.2.0" -"@emotion/babel-plugin@^11.7.1": - version "11.7.2" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.7.2.tgz#fec75f38a6ab5b304b0601c74e2a5e77c95e5fa0" - integrity sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ== - dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/plugin-syntax-jsx" "^7.12.13" - "@babel/runtime" "^7.13.10" - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.5" - "@emotion/serialize" "^1.0.2" - babel-plugin-macros "^2.6.1" - convert-source-map "^1.5.0" - escape-string-regexp "^4.0.0" - find-root "^1.1.0" - source-map "^0.5.7" - stylis "4.0.13" - "@emotion/cache@^11.7.1": version "11.7.1" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.7.1.tgz#08d080e396a42e0037848214e8aa7bf879065539" @@ -1224,22 +1207,21 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": +"@emotion/memoize@^0.7.4": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== -"@emotion/react@^11.8.1": - version "11.8.1" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.8.1.tgz#5358b8c78367063881e26423057c030c57ce52eb" - integrity sha512-XGaie4nRxmtP1BZYBXqC5JGqMYF2KRKKI7vjqNvQxyRpekVAZhb6QqrElmZCAYXH1L90lAelADSVZC4PFsrJ8Q== +"@emotion/react@^11.7.1": + version "11.7.1" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.7.1.tgz#3f800ce9b20317c13e77b8489ac4a0b922b2fe07" + integrity sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw== dependencies: "@babel/runtime" "^7.13.10" - "@emotion/babel-plugin" "^11.7.1" "@emotion/cache" "^11.7.1" "@emotion/serialize" "^1.0.2" "@emotion/sheet" "^1.1.0" - "@emotion/utils" "^1.1.0" + "@emotion/utils" "^1.0.0" "@emotion/weak-memoize" "^0.2.5" hoist-non-react-statics "^3.3.1" @@ -1264,24 +1246,24 @@ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@emotion/utils@^1.0.0", "@emotion/utils@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" - integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== +"@emotion/utils@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" + integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA== "@emotion/weak-memoize@^0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== -"@eslint/eslintrc@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a" - integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w== +"@eslint/eslintrc@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" + integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.3.1" + espree "^9.2.0" globals "^13.9.0" ignore "^4.0.6" import-fresh "^3.2.1" @@ -1290,9 +1272,9 @@ strip-json-comments "^3.1.1" "@humanwhocodes/config-array@^0.9.2": - version "0.9.5" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" - integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + version "0.9.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.3.tgz#f2564c744b387775b436418491f15fce6601f63e" + integrity sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -1319,168 +1301,168 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" - integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== +"@jest/console@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.4.6.tgz#0742e6787f682b22bdad56f9db2a8a77f6a86107" + integrity sha512-jauXyacQD33n47A44KrlOVeiXHEXDqapSdfb9kTekOchH/Pd18kBIO1+xxJQRLuG+LUuljFCwTG92ra4NW7SpA== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^27.5.1" - jest-util "^27.5.1" + jest-message-util "^27.4.6" + jest-util "^27.4.2" slash "^3.0.0" -"@jest/core@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" - integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== +"@jest/core@^27.4.7": + version "27.4.7" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.4.7.tgz#84eabdf42a25f1fa138272ed229bcf0a1b5e6913" + integrity sha512-n181PurSJkVMS+kClIFSX/LLvw9ExSb+4IMtD6YnfxZVerw9ANYtW0bPrm0MJu2pfe9SY9FJ9FtQ+MdZkrZwjg== dependencies: - "@jest/console" "^27.5.1" - "@jest/reporters" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/console" "^27.4.6" + "@jest/reporters" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.8.1" exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^27.5.1" - jest-config "^27.5.1" - jest-haste-map "^27.5.1" - jest-message-util "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-resolve-dependencies "^27.5.1" - jest-runner "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" - jest-watcher "^27.5.1" + graceful-fs "^4.2.4" + jest-changed-files "^27.4.2" + jest-config "^27.4.7" + jest-haste-map "^27.4.6" + jest-message-util "^27.4.6" + jest-regex-util "^27.4.0" + jest-resolve "^27.4.6" + jest-resolve-dependencies "^27.4.6" + jest-runner "^27.4.6" + jest-runtime "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" + jest-validate "^27.4.6" + jest-watcher "^27.4.6" micromatch "^4.0.4" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" - integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== +"@jest/environment@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.4.6.tgz#1e92885d64f48c8454df35ed9779fbcf31c56d8b" + integrity sha512-E6t+RXPfATEEGVidr84WngLNWZ8ffCPky8RqqRK6u1Bn0LK92INe0MDttyPl/JOzaq92BmDzOeuqk09TvM22Sg== dependencies: - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/fake-timers" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" - jest-mock "^27.5.1" + jest-mock "^27.4.6" -"@jest/fake-timers@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" - integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== +"@jest/fake-timers@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.4.6.tgz#e026ae1671316dbd04a56945be2fa251204324e8" + integrity sha512-mfaethuYF8scV8ntPpiVGIHQgS0XIALbpY2jt2l7wb/bvq4Q5pDLk4EP4D7SAvYT1QrPOPVZAtbdGAOOyIgs7A== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@sinonjs/fake-timers" "^8.0.1" "@types/node" "*" - jest-message-util "^27.5.1" - jest-mock "^27.5.1" - jest-util "^27.5.1" + jest-message-util "^27.4.6" + jest-mock "^27.4.6" + jest-util "^27.4.2" -"@jest/globals@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" - integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== +"@jest/globals@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.4.6.tgz#3f09bed64b0fd7f5f996920258bd4be8f52f060a" + integrity sha512-kAiwMGZ7UxrgPzu8Yv9uvWmXXxsy0GciNejlHvfPIfWkSxChzv6bgTS3YqBkGuHcis+ouMFI2696n2t+XYIeFw== dependencies: - "@jest/environment" "^27.5.1" - "@jest/types" "^27.5.1" - expect "^27.5.1" + "@jest/environment" "^27.4.6" + "@jest/types" "^27.4.2" + expect "^27.4.6" -"@jest/reporters@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" - integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== +"@jest/reporters@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.4.6.tgz#b53dec3a93baf9b00826abf95b932de919d6d8dd" + integrity sha512-+Zo9gV81R14+PSq4wzee4GC2mhAN9i9a7qgJWL90Gpx7fHYkWpTBvwWNZUXvJByYR9tAVBdc8VxDWqfJyIUrIQ== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/console" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.2" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" istanbul-lib-coverage "^3.0.0" istanbul-lib-instrument "^5.1.0" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-haste-map "^27.5.1" - jest-resolve "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" + jest-haste-map "^27.4.6" + jest-resolve "^27.4.6" + jest-util "^27.4.2" + jest-worker "^27.4.6" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" -"@jest/source-map@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" - integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== +"@jest/source-map@^27.4.0": + version "27.4.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.4.0.tgz#2f0385d0d884fb3e2554e8f71f8fa957af9a74b6" + integrity sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ== dependencies: callsites "^3.0.0" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" - integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== +"@jest/test-result@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.4.6.tgz#b3df94c3d899c040f602cea296979844f61bdf69" + integrity sha512-fi9IGj3fkOrlMmhQqa/t9xum8jaJOOAi/lZlm6JXSc55rJMXKHxNDN1oCP39B0/DhNOa2OMupF9BcKZnNtXMOQ== dependencies: - "@jest/console" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/console" "^27.4.6" + "@jest/types" "^27.4.2" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" - integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== +"@jest/test-sequencer@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.4.6.tgz#447339b8a3d7b5436f50934df30854e442a9d904" + integrity sha512-3GL+nsf6E1PsyNsJuvPyIz+DwFuCtBdtvPpm/LMXVkBJbdFvQYCDpccYT56qq5BGniXWlE81n2qk1sdXfZebnw== dependencies: - "@jest/test-result" "^27.5.1" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-runtime "^27.5.1" + "@jest/test-result" "^27.4.6" + graceful-fs "^4.2.4" + jest-haste-map "^27.4.6" + jest-runtime "^27.4.6" -"@jest/transform@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" - integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== +"@jest/transform@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.4.6.tgz#153621940b1ed500305eacdb31105d415dc30231" + integrity sha512-9MsufmJC8t5JTpWEQJ0OcOOAXaH5ioaIX6uHVBLBMoCZPfKKQF+EqP8kACAvCZ0Y1h2Zr3uOccg8re+Dr5jxyw== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" babel-plugin-istanbul "^6.1.1" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-regex-util "^27.5.1" - jest-util "^27.5.1" + graceful-fs "^4.2.4" + jest-haste-map "^27.4.6" + jest-regex-util "^27.4.0" + jest-util "^27.4.2" micromatch "^4.0.4" pirates "^4.0.4" slash "^3.0.0" source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" - integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== +"@jest/types@^27.4.2": + version "27.4.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.4.2.tgz#96536ebd34da6392c2b7c7737d693885b5dd44a5" + integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -1521,16 +1503,16 @@ "@types/set-cookie-parser" "^2.4.0" set-cookie-parser "^2.4.6" -"@mswjs/interceptors@^0.13.5": - version "0.13.6" - resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.13.6.tgz#db46ba29c9ec118aefcf6ef61ecc38b25837967f" - integrity sha512-28FzF44Q84h9vxQ0XBpEz940KC/q3fzlo+TtaIyfilnJ7+HeIcnVfRM4hkp0/q2Uh466PmgpD4BH7A0F0kCBbQ== +"@mswjs/interceptors@^0.12.7": + version "0.12.7" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.12.7.tgz#0d1cd4cd31a0f663e0455993951201faa09d0909" + integrity sha512-eGjZ3JRAt0Fzi5FgXiV/P3bJGj0NqsN7vBS0J0FO2AQRQ0jCKQS4lEFm4wvlSgKQNfeuc/Vz6d81VtU3Gkx/zg== dependencies: "@open-draft/until" "^1.0.3" - "@xmldom/xmldom" "^0.7.5" - debug "^4.3.3" - headers-polyfill "^3.0.4" - outvariant "^1.2.1" + "@xmldom/xmldom" "^0.7.2" + debug "^4.3.2" + headers-utils "^3.0.2" + outvariant "^1.2.0" strict-event-emitter "^0.2.0" "@nodelib/fs.scandir@2.1.5": @@ -1575,6 +1557,14 @@ source-map "^0.7.3" "@rollup/plugin-babel@^5.2.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879" + integrity sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@rollup/pluginutils" "^3.1.0" + +"@rollup/plugin-babel@^5.3.1": version "5.3.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q== @@ -1582,6 +1572,26 @@ "@babel/helper-module-imports" "^7.10.4" "@rollup/pluginutils" "^3.1.0" +"@rollup/plugin-commonjs@^21.0.2": + version "21.0.2" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.2.tgz#0b9c539aa1837c94abfaf87945838b0fc8564891" + integrity sha512-d/OmjaLVO4j/aQX69bwpWPpbvI3TJkQuxoAk7BH8ew1PyoMBLTOuvJTjzG8oEoW7drIIqB0KCJtfFLu/2GClWg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + commondir "^1.0.1" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" + +"@rollup/plugin-json@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" + integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw== + dependencies: + "@rollup/pluginutils" "^3.0.8" + "@rollup/plugin-node-resolve@^11.2.1": version "11.2.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60" @@ -1594,6 +1604,18 @@ is-module "^1.0.0" resolve "^1.19.0" +"@rollup/plugin-node-resolve@^13.1.3": + version "13.1.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz#2ed277fb3ad98745424c1d2ba152484508a92d79" + integrity sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.19.0" + "@rollup/plugin-replace@^2.4.1": version "2.4.2" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" @@ -1602,7 +1624,15 @@ "@rollup/pluginutils" "^3.1.0" magic-string "^0.25.7" -"@rollup/pluginutils@^3.1.0": +"@rollup/plugin-typescript@^8.3.1": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-8.3.1.tgz#b7dc75ed6b4876e260b9e80624fab23bc98e4ac1" + integrity sha512-84rExe3ICUBXzqNX48WZV2Jp3OddjTMX97O2Py6D1KJaGSwWp0mDHXj+bCGNJqWHIEKDIT2U0sDjhP4czKi6cA== + dependencies: + "@rollup/pluginutils" "^3.1.0" + resolve "^1.17.0" + +"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== @@ -1611,6 +1641,14 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^4.1.1": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.2.tgz#ed5821c15e5e05e32816f5fb9ec607cdf5a75751" + integrity sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + "@rushstack/eslint-patch@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" @@ -1757,10 +1795,10 @@ lz-string "^1.4.4" pretty-format "^27.0.2" -"@testing-library/jest-dom@^5.16.2": - version "5.16.2" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" - integrity sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug== +"@testing-library/jest-dom@^5.14.1": + version "5.16.1" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.1.tgz#3db7df5ae97596264a7da9696fe14695ba02e51f" + integrity sha512-ajUJdfDIuTCadB79ukO+0l8O+QwN0LiSxDaYUTI4LndbbUsGi6rWU1SCexXzBA2NSjlVB9/vbkasQIL3tmPBjw== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" @@ -1772,16 +1810,15 @@ lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^12.1.3": - version "12.1.3" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.3.tgz#ef26c5f122661ea9b6f672b23dc6b328cadbbf26" - integrity sha512-oCULRXWRrBtC9m6G/WohPo1GLcLesH7T4fuKzRAKn1CWVu9BzXtqLXDDTA6KhFNNtRwLtfSMr20HFl+Qrdrvmg== +"@testing-library/react@^12.0.0": + version "12.1.2" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.2.tgz#f1bc9a45943461fa2a598bb4597df1ae044cfc76" + integrity sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g== dependencies: "@babel/runtime" "^7.12.5" "@testing-library/dom" "^8.0.0" - "@types/react-dom" "*" -"@testing-library/user-event@^13.5.0": +"@testing-library/user-event@^13.2.1": version "13.5.0" resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.5.0.tgz#69d77007f1e124d55314a2b73fd204b333b13295" integrity sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg== @@ -2086,7 +2123,7 @@ "@types/d3-transition" "*" "@types/d3-zoom" "*" -"@types/eslint-scope@^3.7.3": +"@types/eslint-scope@^3.7.0": version "3.7.3" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== @@ -2110,10 +2147,10 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@*", "@types/estree@^0.0.50": + version "0.0.50" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" + integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== "@types/estree@0.0.39": version "0.0.39" @@ -2129,7 +2166,7 @@ "@types/qs" "*" "@types/range-parser" "*" -"@types/express@*", "@types/express@^4.17.13": +"@types/express@*": version "4.17.13" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== @@ -2139,11 +2176,26 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/fs-extra@^8.0.1": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f" + integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg== + dependencies: + "@types/node" "*" + "@types/geojson@*": version "7946.0.8" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca" integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA== +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -2178,6 +2230,14 @@ dependencies: "@types/node" "*" +"@types/inquirer@^8.1.3": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-8.2.0.tgz#b9566d048f5ff65159f2ed97aff45fe0f00b35ec" + integrity sha512-BNoMetRf3gmkpAlV5we+kxyZTle7YibdOntIZbU5pyIfMdcwy784KfeZDAcuyMznkh5OLa17RVXZOGA5LTlkgQ== + dependencies: + "@types/through" "*" + rxjs "^7.2.0" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" @@ -2197,15 +2257,15 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@*", "@types/jest@^27.4.1": - version "27.4.1" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d" - integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw== +"@types/jest@*", "@types/jest@^27.0.1": + version "27.4.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed" + integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ== dependencies: - jest-matcher-utils "^27.0.0" + jest-diff "^27.0.0" pretty-format "^27.0.0" -"@types/js-levenshtein@^1.1.1": +"@types/js-levenshtein@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz#ba05426a43f9e4e30b631941e0aa17bf0c890ed5" integrity sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g== @@ -2221,9 +2281,9 @@ integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= "@types/lodash@^4.14.160": - version "4.14.179" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5" - integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w== + version "4.14.178" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" + integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== "@types/mdast@^3.0.0": version "3.0.10" @@ -2237,10 +2297,20 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== -"@types/node@*", "@types/node@^17.0.21": - version "17.0.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" - integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== +"@types/minimatch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/node@*": + version "17.0.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.13.tgz#5ed7ed7c662948335fcad6c412bb42d99ea754e3" + integrity sha512-Y86MAxASe25hNzlDbsviXl8jQHb0RDvKt4c40ZJQ1Don0AAL0STLZSs4N+6gLEO55pedy7r2cLwS+ZDxPm/2Bw== + +"@types/node@^16.7.13": + version "16.11.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.21.tgz#474d7589a30afcf5291f59bd49cca9ad171ffde4" + integrity sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A== "@types/numeral@^0.0.28": version "0.0.28" @@ -2258,9 +2328,9 @@ integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== "@types/prettier@^2.1.5": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17" - integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA== + version "2.4.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" + integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== "@types/prismjs@*": version "1.26.0" @@ -2287,21 +2357,21 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/react-beautiful-dnd@^13.1.2": +"@types/react-beautiful-dnd@^13.0.0": version "13.1.2" resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz#510405abb09f493afdfd898bf83995dc6385c130" integrity sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg== dependencies: "@types/react" "*" -"@types/react-dom@*", "@types/react-dom@^17.0.13": - version "17.0.13" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.13.tgz#a3323b974ee4280070982b3112351bb1952a7809" - integrity sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ== +"@types/react-dom@^17.0.9": + version "17.0.11" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.11.tgz#e1eadc3c5e86bdb5f7684e00274ae228e7bcc466" + integrity sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q== dependencies: "@types/react" "*" -"@types/react-input-autosize@^2.2.1": +"@types/react-input-autosize@^2.2.0": version "2.2.1" resolved "https://registry.yarnpkg.com/@types/react-input-autosize/-/react-input-autosize-2.2.1.tgz#6a335212e7fce1e1a4da56ae2095c8c5c35fbfe6" integrity sha512-RxzEjd4gbLAAdLQ92Q68/AC+TfsAKTc4evsArUH1aIShIMqQMIMjsxoSnwyjtbFTO/AGIW/RQI94XSdvOxCz/w== @@ -2309,33 +2379,33 @@ "@types/react" "*" "@types/react-redux@^7.1.20": - version "7.1.23" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.23.tgz#3c2bb1bcc698ae69d70735f33c5a8e95f41ac528" - integrity sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw== + version "7.1.22" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.22.tgz#0eab76a37ef477cc4b53665aeaf29cb60631b72a" + integrity sha512-GxIA1kM7ClU73I6wg9IRTVwSO9GS+SAKZKe0Enj+82HMU6aoESFU2HNAdNi3+J53IaOHPiUfT3kSG4L828joDQ== dependencies: "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" hoist-non-react-statics "^3.3.0" redux "^4.0.0" -"@types/react-virtualized-auto-sizer@^1.0.1": +"@types/react-virtualized-auto-sizer@^1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4" integrity sha512-GH8sAnBEM5GV9LTeiz56r4ZhMOUSrP43tAQNSRVxNexDjcNKLCEtnxusAItg1owFUFE6k0NslV26gqVClVvong== dependencies: "@types/react" "*" -"@types/react-window@^1.8.5": +"@types/react-window@^1.8.2": version "1.8.5" resolved "https://registry.yarnpkg.com/@types/react-window/-/react-window-1.8.5.tgz#285fcc5cea703eef78d90f499e1457e9b5c02fc1" integrity sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw== dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^17.0.39": - version "17.0.39" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" - integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug== +"@types/react@*", "@types/react@^17.0.20": + version "17.0.38" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.38.tgz#f24249fefd89357d5fa71f739a686b8d7c7202bd" + integrity sha512-SI92X1IA+FMnP3qM5m4QReluXzhcmovhZnLNm3pyeQlooi02qI7sLiepEYqT678uNiyc25XfCqxREFpy3W7YhQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2349,9 +2419,9 @@ "@types/prismjs" "*" "@types/resize-observer-browser@^0.1.5": - version "0.1.7" - resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz#294aaadf24ac6580b8fbd1fe3ab7b59fe85f9ef3" - integrity sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg== + version "0.1.6" + resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.6.tgz#d8e6c2f830e2650dc06fe74464472ff64b54a302" + integrity sha512-61IfTac0s9jvNtBCpyo86QeaN8qqpMGHdK0uGKCCIy2dt5/Yk84VduHIdWAcmkC5QvdkPL0p5eWYgUZtHKKUVg== "@types/resolve@1.17.1": version "1.17.1" @@ -2405,12 +2475,19 @@ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/testing-library__jest-dom@^5.9.1": - version "5.14.3" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz#ee6c7ffe9f8595882ee7bda8af33ae7b8789ef17" - integrity sha512-oKZe+Mf4ioWlMuzVBaXQ9WDnEm1+umLx0InILg+yvZVBBDmzV5KfZyLrCvadtWcx8+916jLmHafcmqqffl+iIw== + version "5.14.2" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.2.tgz#564fb2b2dc827147e937a75b639a05d17ce18b44" + integrity sha512-vehbtyHUShPxIa9SioxDwCvgxukDMH//icJG90sXQBUm5lJOHLT5kNeU9tnivhnA/TkOFMzGIXN2cTc4hY8/kg== dependencies: "@types/jest" "*" +"@types/through@*": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895" + integrity sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg== + dependencies: + "@types/node" "*" + "@types/trusted-types@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" @@ -2429,16 +2506,16 @@ vfile-message "*" "@types/ws@^8.2.2": - version "8.5.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.2.tgz#77e0c2e360e9579da930ffcfa53c5975ea3bdd26" - integrity sha512-VXI82ykONr5tacHEojnErTQk+KQSoYbW1NB6iz6wUwrNd+BqfkfggQNoNdCqhJSzbNumShPERbM+Pc5zpfhlbw== + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" + integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== dependencies: "@types/node" "*" "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== "@types/yargs@^16.0.0": version "16.0.4" @@ -2448,13 +2525,13 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^5.5.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497" - integrity sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ== + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.1.tgz#870195d0f2146b36d11fc71131b75aba52354c69" + integrity sha512-xN3CYqFlyE/qOcy978/L0xLR2HlcAGIyIK5sMOasxaaAPfQRj/MmMV6OC3I7NZO84oEUdWCOju34Z9W8E0pFDQ== dependencies: - "@typescript-eslint/scope-manager" "5.13.0" - "@typescript-eslint/type-utils" "5.13.0" - "@typescript-eslint/utils" "5.13.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/type-utils" "5.10.1" + "@typescript-eslint/utils" "5.10.1" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -2462,76 +2539,76 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@^5.0.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.13.0.tgz#5f9c509998a4b0b5662c23a758ac0e178dc7bb98" - integrity sha512-A0btJxjB9gH6yJsARONe5xd0ykgj1+0fO1TRWoUBn2hT3haWiZeh4f1FILKW0z/9OBchT5zCOz3hiJfRK/vumA== +"@typescript-eslint/experimental-utils@^5.0.0", "@typescript-eslint/experimental-utils@^5.9.0": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.10.1.tgz#49fa5a7800ed08ea70aef14fccb14fbae85116ab" + integrity sha512-Ryeb8nkJa/1zKl8iujNtJC8tgj6PgaY0sDUnrTqbmC70nrKKkZaHfiRDTcqICmCSCEQyLQcJAoh0AukLaIaGTw== dependencies: - "@typescript-eslint/utils" "5.13.0" + "@typescript-eslint/utils" "5.10.1" "@typescript-eslint/parser@^5.5.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c" - integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg== + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.1.tgz#4ce9633cc33fc70bc13786cb793c1a76fe5ad6bd" + integrity sha512-GReo3tjNBwR5RnRO0K2wDIDN31cM3MmDtgyQ85oAxAmC5K3j/g85IjP+cDfcqDsDDBf1HNKQAD0WqOYL8jXqUA== dependencies: - "@typescript-eslint/scope-manager" "5.13.0" - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/typescript-estree" "5.13.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/typescript-estree" "5.10.1" debug "^4.3.2" -"@typescript-eslint/scope-manager@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6" - integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA== +"@typescript-eslint/scope-manager@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.1.tgz#f0539c73804d2423506db2475352a4dec36cd809" + integrity sha512-Lyvi559Gvpn94k7+ElXNMEnXu/iundV5uFmCUNnftbFrUbAJ1WBoaGgkbOBm07jVZa682oaBU37ao/NGGX4ZDg== dependencies: - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/visitor-keys" "5.13.0" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/visitor-keys" "5.10.1" -"@typescript-eslint/type-utils@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz#b0efd45c85b7bab1125c97b752cab3a86c7b615d" - integrity sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg== +"@typescript-eslint/type-utils@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.1.tgz#5e526c00142585e40ab1503e83f1ff608c367405" + integrity sha512-AfVJkV8uck/UIoDqhu+ptEdBoQATON9GXnhOpPLzkQRJcSChkvD//qsz9JVffl2goxX+ybs5klvacE9vmrQyCw== dependencies: - "@typescript-eslint/utils" "5.13.0" + "@typescript-eslint/utils" "5.10.1" debug "^4.3.2" tsutils "^3.21.0" -"@typescript-eslint/types@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5" - integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg== +"@typescript-eslint/types@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.1.tgz#dca9bd4cb8c067fc85304a31f38ec4766ba2d1ea" + integrity sha512-ZvxQ2QMy49bIIBpTqFiOenucqUyjTQ0WNLhBM6X1fh1NNlYAC6Kxsx8bRTY3jdYsYg44a0Z/uEgQkohbR0H87Q== -"@typescript-eslint/typescript-estree@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141" - integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA== +"@typescript-eslint/typescript-estree@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.1.tgz#b268e67be0553f8790ba3fe87113282977adda15" + integrity sha512-PwIGnH7jIueXv4opcwEbVGDATjGPO1dx9RkUl5LlHDSe+FXxPwFL5W/qYd5/NHr7f6lo/vvTrAzd0KlQtRusJQ== dependencies: - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/visitor-keys" "5.13.0" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/visitor-keys" "5.10.1" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.13.0", "@typescript-eslint/utils@^5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.13.0.tgz#2328feca700eb02837298339a2e49c46b41bd0af" - integrity sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ== +"@typescript-eslint/utils@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.1.tgz#fa682a33af47080ba2c4368ee0ad2128213a1196" + integrity sha512-RRmlITiUbLuTRtn/gcPRi4202niF+q7ylFLCKu4c+O/PcpRvZ/nAUwQ2G00bZgpWkhrNLNnvhZLbDn8Ml0qsQw== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.13.0" - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/typescript-estree" "5.13.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/typescript-estree" "5.10.1" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd" - integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g== +"@typescript-eslint/visitor-keys@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz#29102de692f59d7d34ecc457ed59ab5fc558010b" + integrity sha512-NjQ0Xinhy9IL979tpoTRuLKxMc0zJC7QVSdeerXs2/QvOy2yRkzX5dRb10X5woNUdJgU8G3nYRDlI33sq1K4YQ== dependencies: - "@typescript-eslint/types" "5.13.0" + "@typescript-eslint/types" "5.10.1" eslint-visitor-keys "^3.0.0" "@webassemblyjs/ast@1.11.1": @@ -2655,7 +2732,7 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" -"@xmldom/xmldom@^0.7.5": +"@xmldom/xmldom@^0.7.2": version "0.7.5" resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== @@ -2675,13 +2752,13 @@ abab@^2.0.3, abab@^2.0.5: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" + mime-types "~2.1.24" + negotiator "0.6.2" acorn-globals@^6.0.0: version "6.0.0" @@ -2720,7 +2797,7 @@ acorn@^7.0.0, acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0: +acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.0: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== @@ -2783,9 +2860,9 @@ ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: uri-js "^4.2.2" ajv@^8.0.0, ajv@^8.6.0, ajv@^8.8.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" - integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== + version "8.9.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18" + integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -2959,7 +3036,7 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -attr-accept@^2.2.2: +attr-accept@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== @@ -2977,27 +3054,27 @@ autoprefixer@^10.4.2: postcss-value-parser "^4.2.0" axe-core@^4.3.5: - version "4.4.1" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413" - integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw== + version "4.3.5" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" + integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== -babel-jest@^27.4.2, babel-jest@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" - integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== +babel-jest@^27.4.2, babel-jest@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.4.6.tgz#4d024e69e241cdf4f396e453a07100f44f7ce314" + integrity sha512-qZL0JT0HS1L+lOuH+xC2DVASR3nunZi/ozGhpgauJHgmI7f8rudxf6hUjEHympdQ/J64CdKmPkgfJ+A3U6QCrg== dependencies: - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^27.5.1" + babel-preset-jest "^27.4.0" chalk "^4.0.0" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" slash "^3.0.0" babel-loader@^8.2.3: @@ -3028,25 +3105,16 @@ babel-plugin-istanbul@^6.1.1: istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" - integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== +babel-plugin-jest-hoist@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz#d7831fc0f93573788d80dee7e682482da4c730d6" + integrity sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@^2.6.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" - integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== - dependencies: - "@babel/runtime" "^7.7.2" - cosmiconfig "^6.0.0" - resolve "^1.12.0" - babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" @@ -3071,12 +3139,12 @@ babel-plugin-polyfill-corejs2@^0.3.0: semver "^6.1.1" babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" - integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== + version "0.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.1.tgz#d66183bf10976ea677f4149a7fcc4d8df43d4060" + integrity sha512-TihqEe4sQcb/QcPJvxe94/9RZuLQuF1+To4WqQcRvc+3J3gLCPIPgDKzGLG6zmQLfH3nn25heRuDNkS2KR4I8A== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" - core-js-compat "^3.21.0" + core-js-compat "^3.20.0" babel-plugin-polyfill-regenerator@^0.3.0: version "0.3.1" @@ -3108,12 +3176,12 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" - integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== +babel-preset-jest@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz#70d0e676a282ccb200fbabd7f415db5fdf393bca" + integrity sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg== dependencies: - babel-plugin-jest-hoist "^27.5.1" + babel-plugin-jest-hoist "^27.4.0" babel-preset-current-node-syntax "^1.0.0" babel-preset-react-app@^10.0.1: @@ -3197,20 +3265,20 @@ bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -body-parser@1.19.2: - version "1.19.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" - integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== +body-parser@1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" + integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== dependencies: - bytes "3.1.2" + bytes "3.1.1" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" http-errors "1.8.1" iconv-lite "0.4.24" on-finished "~2.3.0" - qs "6.9.7" - raw-body "2.4.3" + qs "6.9.6" + raw-body "2.4.2" type-is "~1.6.18" bonjour@^3.5.0: @@ -3264,15 +3332,15 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1, browserslist@^4.19.3: - version "4.19.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.3.tgz#29b7caad327ecf2859485f696f9604214bedd383" - integrity sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg== +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== dependencies: - caniuse-lite "^1.0.30001312" - electron-to-chromium "^1.4.71" + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" escalade "^3.1.1" - node-releases "^2.0.2" + node-releases "^2.0.1" picocolors "^1.0.0" bser@2.1.1: @@ -3310,10 +3378,10 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +bytes@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" + integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" @@ -3361,10 +3429,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001312: - version "1.0.30001312" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" - integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001299: + version "1.0.30001303" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001303.tgz#9b168e4f43ccfc372b86f4bc5a551d9b909c95c9" + integrity sha512-/Mqc1oESndUNszJP0kx0UaQU9kEv9nNtJ7Kn8AdA0mNnH8eR1cj0kG+NbNuC1Wq/b21eA8prhKRA3bbkjONegQ== case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" @@ -3415,9 +3483,9 @@ char-regex@^1.0.2: integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== char-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e" - integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw== + version "2.0.0" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.0.tgz#16f98f3f874edceddd300fda5d58df380a7641a6" + integrity sha512-oGu2QekBMXgyQNWPDRQ001bjvDnZe4/zBTz37TMbiKz1NbNiyiH5hRkobe7npRN6GfbGbxMYFck/vQ1r9c1VMA== character-entities-html4@^1.0.0: version "1.1.4" @@ -3439,11 +3507,6 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -charcodes@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4" - integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ== - chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -3454,7 +3517,7 @@ check-types@^11.1.1: resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f" integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ== -chokidar@^3.4.2, chokidar@^3.5.3: +chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -3470,9 +3533,9 @@ chokidar@^3.4.2, chokidar@^3.5.3: fsevents "~2.3.2" chroma-js@^2.1.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.4.2.tgz#dffc214ed0c11fa8eefca2c36651d8e57cbfb2b0" - integrity sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A== + version "2.3.0" + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.3.0.tgz#fdf68a18d8f97ce006422338044218ccbffb9ecb" + integrity sha512-dRgAp9FHHy+VfE7e3/I5HHU0+zZlUHBODcjvXUXinsR/NnHCO+kfv68ofzrAqFI80q2IWvDSAmHAqHh93TGgKg== chrome-trace-event@^1.0.2: version "1.0.3" @@ -3590,6 +3653,11 @@ colord@^2.9.1: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== +colorette@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + colorette@^2.0.10: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" @@ -3684,7 +3752,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== @@ -3696,28 +3764,33 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.2, cookie@^0.4.2: +cookie@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +cookie@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" - integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== +core-js-compat@^3.20.0, core-js-compat@^3.20.2: + version "3.20.3" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.20.3.tgz#d71f85f94eb5e4bea3407412e549daa083d23bd6" + integrity sha512-c8M5h0IkNZ+I92QhIpuSijOxGAcj3lgpsWdkCqmUTZNwidujF4r3pi6x1DCN+Vcs5qTS2XWWMfWSuCqyupX8gw== dependencies: browserslist "^4.19.1" semver "7.0.0" core-js-pure@^3.20.2, core-js-pure@^3.8.1: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" - integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== + version "3.20.3" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.20.3.tgz#6cc4f36da06c61d95254efc54024fe4797fd5d02" + integrity sha512-Q2H6tQ5MtPtcC7f3HxJ48i4Q7T9ybPKgvWyuH7JXIoNa2pm0KuBnycsET/qw1SLLZYfbsbrZQNMeIOClb+6WIA== core-js@^3.19.2: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" - integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== + version "3.20.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.3.tgz#c710d0a676e684522f3db4ee84e5e18a9d11d69a" + integrity sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag== core-util-is@~1.0.0: version "1.0.3" @@ -3760,12 +3833,12 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-blank-pseudo@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561" - integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ== +css-blank-pseudo@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.2.tgz#f8660f6a48b17888a9277e53f25cc5abec1f0169" + integrity sha512-hOb1LFjRR+8ocA071xUSmg5VslJ8NGo/I2qpUpdeAYyBVCgupS5O8SEVo4SxEMYyFBNodBkzG3T1iqW9HCXxew== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.8" css-box-model@^1.2.0: version "1.2.1" @@ -3781,25 +3854,25 @@ css-declaration-sorter@^6.0.3: dependencies: timsort "^0.3.0" -css-has-pseudo@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73" - integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw== +css-has-pseudo@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.3.tgz#4824a34cb92dae7e09ea1d3fd19691b653412098" + integrity sha512-0gDYWEKaGacwxCqvQ3Ypg6wGdD1AztbMm5h1JsactG2hP2eiflj808QITmuWBpE7sjSEVrAlZhPTVd/nNMj/hQ== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.8" css-loader@^6.5.1: - version "6.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" - integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== + version "6.5.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.5.1.tgz#0c43d4fbe0d97f699c91e9818cb585759091d1b1" + integrity sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ== dependencies: icss-utils "^5.1.0" - postcss "^8.4.5" + postcss "^8.2.15" postcss-modules-extract-imports "^3.0.0" postcss-modules-local-by-default "^4.0.0" postcss-modules-scope "^3.0.0" postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" + postcss-value-parser "^4.1.0" semver "^7.3.5" css-minimizer-webpack-plugin@^3.2.0: @@ -3814,10 +3887,10 @@ css-minimizer-webpack-plugin@^3.2.0: serialize-javascript "^6.0.0" source-map "^0.6.1" -css-prefers-color-scheme@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349" - integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA== +css-prefers-color-scheme@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.2.tgz#d5c03a980caab92d8beeee176a8795d331e0c727" + integrity sha512-gv0KQBEM+q/XdoKyznovq3KW7ocO7k+FhPP+hQR1MenJdu0uPGS6IZa9PzlbqBeS6XcZJNAoqoFxlAUW461CrA== css-select-base-adapter@^0.1.1: version "0.1.1" @@ -3845,6 +3918,22 @@ css-select@^4.1.3: domutils "^2.8.0" nth-check "^2.0.1" +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha.33: + version "1.0.0-alpha.33" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" + integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== + dependencies: + mdn-data "2.0.4" + source-map "^0.5.3" + css-tree@1.0.0-alpha.37: version "1.0.0-alpha.37" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" @@ -3885,65 +3974,72 @@ css@^3.0.0: source-map "^0.6.1" source-map-resolve "^0.6.0" -cssdb@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-6.4.0.tgz#54899b9042e302be3090b8510ea71fefd08c9e6b" - integrity sha512-8NMWrur/ewSNrRNZndbtOTXc2Xb2b+NCTPHj8VErFYvJUlgsMAiBGaFaxG6hjy9zbCjj2ZLwSQrMM+tormO8qA== +cssdb@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-5.1.0.tgz#ec728d5f5c0811debd0820cbebda505d43003400" + integrity sha512-/vqjXhv1x9eGkE/zO6o8ZOI7dgdZbLVLUGyVRbPgk6YipXbW87YzUCcO+Jrmi5bwJlAH6oD+MNeZyRgXea1GZw== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-default@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.0.tgz#2579d38b9217746f2cf9f938954a91e00418ded6" - integrity sha512-3N5Vcptj2pqVKpHVqH6ezOJvqikR2PdLTbTrsrhF61FbLRQuujAqZ2sKN5rvcMsb7hFjrNnjZT8CGEkxoN/Pwg== +cssnano-preset-default@^5.1.11: + version "5.1.11" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.11.tgz#db10fb1ecee310e8285c5aca45bd8237be206828" + integrity sha512-ETet5hqHxmzQq2ynXMOQofKuLm7VOjMiOB7E2zdtm/hSeCKlD9fabzIUV4GoPcRyJRHi+4kGf0vsfGYbQ4nmPw== dependencies: css-declaration-sorter "^6.0.3" - cssnano-utils "^3.1.0" - postcss-calc "^8.2.3" - postcss-colormin "^5.3.0" - postcss-convert-values "^5.1.0" - postcss-discard-comments "^5.1.0" - postcss-discard-duplicates "^5.1.0" - postcss-discard-empty "^5.1.0" - postcss-discard-overridden "^5.1.0" - postcss-merge-longhand "^5.1.0" - postcss-merge-rules "^5.1.0" - postcss-minify-font-values "^5.1.0" - postcss-minify-gradients "^5.1.0" - postcss-minify-params "^5.1.0" - postcss-minify-selectors "^5.2.0" - postcss-normalize-charset "^5.1.0" - postcss-normalize-display-values "^5.1.0" - postcss-normalize-positions "^5.1.0" - postcss-normalize-repeat-style "^5.1.0" - postcss-normalize-string "^5.1.0" - postcss-normalize-timing-functions "^5.1.0" - postcss-normalize-unicode "^5.1.0" - postcss-normalize-url "^5.1.0" - postcss-normalize-whitespace "^5.1.0" - postcss-ordered-values "^5.1.0" - postcss-reduce-initial "^5.1.0" - postcss-reduce-transforms "^5.1.0" - postcss-svgo "^5.1.0" - postcss-unique-selectors "^5.1.0" - -cssnano-utils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" - integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== + cssnano-utils "^3.0.1" + postcss-calc "^8.2.0" + postcss-colormin "^5.2.4" + postcss-convert-values "^5.0.3" + postcss-discard-comments "^5.0.2" + postcss-discard-duplicates "^5.0.2" + postcss-discard-empty "^5.0.2" + postcss-discard-overridden "^5.0.3" + postcss-merge-longhand "^5.0.5" + postcss-merge-rules "^5.0.5" + postcss-minify-font-values "^5.0.3" + postcss-minify-gradients "^5.0.5" + postcss-minify-params "^5.0.4" + postcss-minify-selectors "^5.1.2" + postcss-normalize-charset "^5.0.2" + postcss-normalize-display-values "^5.0.2" + postcss-normalize-positions "^5.0.3" + postcss-normalize-repeat-style "^5.0.3" + postcss-normalize-string "^5.0.3" + postcss-normalize-timing-functions "^5.0.2" + postcss-normalize-unicode "^5.0.3" + postcss-normalize-url "^5.0.4" + postcss-normalize-whitespace "^5.0.3" + postcss-ordered-values "^5.0.4" + postcss-reduce-initial "^5.0.2" + postcss-reduce-transforms "^5.0.3" + postcss-svgo "^5.0.3" + postcss-unique-selectors "^5.0.3" + +cssnano-utils@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.0.1.tgz#d3cc0a142d3d217f8736837ec0a2ccff6a89c6ea" + integrity sha512-VNCHL364lh++/ono+S3j9NlUK+d97KNkxI77NlqZU2W3xd2/qmyN61dsa47pTpb55zuU4G4lI7qFjAXZJH1OAQ== cssnano@^5.0.6: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.0.tgz#cf977d660a5824d0d5542639ed1d4045afd84cbe" - integrity sha512-wWxave1wMlThGg4ueK98jFKaNqXnQd1nVZpSkQ9XvR+YymlzP1ofWqES1JkHtI250LksP9z5JH+oDcrKDJezAg== + version "5.0.16" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.16.tgz#4ee97d30411693f3de24cef70b36f7ae2a843e04" + integrity sha512-ryhRI9/B9VFCwPbb1z60LLK5/ldoExi7nwdnJzpkLZkm2/r7j2X3jfY+ZvDVJhC/0fPZlrAguYdHNFg0iglPKQ== dependencies: - cssnano-preset-default "^5.2.0" + cssnano-preset-default "^5.1.11" lilconfig "^2.0.3" yaml "^1.10.2" +csso@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== + dependencies: + css-tree "1.0.0-alpha.29" + csso@^4.0.2, csso@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" @@ -3969,9 +4065,9 @@ cssstyle@^2.3.0: cssom "~0.3.6" csstype@^3.0.2: - version "3.0.11" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" - integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== + version "3.0.10" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" + integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== "d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3: version "3.1.1" @@ -4238,7 +4334,7 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== @@ -4393,10 +4489,10 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +diff-sequences@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" + integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== dir-glob@^3.0.1: version "3.0.1" @@ -4445,9 +4541,9 @@ doctrine@^3.0.0: esutils "^2.0.2" dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9: - version "0.5.13" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.13.tgz#102ee5f25eacce09bdf1cfa5a298f86da473be4b" - integrity sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw== + version "0.5.11" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.11.tgz#79d5846c4f90eba3e617d9031e921de9324f84ed" + integrity sha512-7X6GvzjYf4yTdRKuCVScV+aA9Fvh5r8WzWrXBH9w82ZWB/eYDMGCnazoC/YAqAzUJWHzLOnZqr46K3iEyUhUvw== dom-converter@^0.2.0: version "0.2.0" @@ -4549,10 +4645,10 @@ ejs@^3.1.6: dependencies: jake "^10.6.1" -electron-to-chromium@^1.4.71: - version "1.4.75" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz#d1ad9bb46f2f1bf432118c2be21d27ffeae82fdd" - integrity sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q== +electron-to-chromium@^1.4.17: + version "1.4.57" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz#2b2766df76ac8dbc0a1d41249bc5684a31849892" + integrity sha512-FNC+P5K1n6pF+M0zIK+gFCoXcJhhzDViL3DRIGy2Fv5PohuSES1JHR7T+GlwxSxlzx4yYbsuzCZvHxcBSRCIOw== emittery@^0.8.1: version "0.8.1" @@ -4584,10 +4680,10 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -enhanced-resolve@^5.9.2: - version "5.9.2" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9" - integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA== +enhanced-resolve@^5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" + integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -4605,9 +4701,9 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" error-stack-parser@^2.0.6: - version "2.0.7" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.7.tgz#b0c6e2ce27d0495cf78ad98715e0cad1219abb57" - integrity sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== dependencies: stackframe "^1.1.1" @@ -4782,31 +4878,31 @@ eslint-plugin-react-hooks@^4.3.0: integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== eslint-plugin-react@^7.27.1: - version "7.29.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.3.tgz#f4eab757f2756d25d6d4c2a58a9e20b004791f05" - integrity sha512-MzW6TuCnDOcta67CkpDyRfRsEVx9FNMDV8wZsDqe1luHPdGTrQIUaUXD27Ja3gHsdOIs/cXzNchWGlqm+qRVRg== + version "7.28.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf" + integrity sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw== dependencies: array-includes "^3.1.4" array.prototype.flatmap "^1.2.5" doctrine "^2.1.0" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" + minimatch "^3.0.4" object.entries "^1.1.5" object.fromentries "^2.0.5" object.hasown "^1.1.0" object.values "^1.1.5" - prop-types "^15.8.1" + prop-types "^15.7.2" resolve "^2.0.0-next.3" semver "^6.3.0" string.prototype.matchall "^4.0.6" eslint-plugin-testing-library@^5.0.1: - version "5.0.6" - resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.0.6.tgz#86b0aff2ed0c80f63966c2a4894c06bff382b6d5" - integrity sha512-mMU4+slZsWKHNxtxc5TE2+bs9S//e2uFPlcpTapPhVdnctgn0+G/DaUu6VbT0JLiVMcbBjy3IcfddK+abZawbw== + version "5.0.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.0.4.tgz#1f18b6e7d51db8452203bcbc909efbb571e964b8" + integrity sha512-zA/NfAENCsJXujvwwiap5gsqLp2U6X7m2XA5nOksl4zzb6GpUmRNAleCll58rEP0brFVj7DZBprlIlMGIhoC7Q== dependencies: - "@typescript-eslint/utils" "^5.13.0" + "@typescript-eslint/experimental-utils" "^5.9.0" eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" @@ -4816,10 +4912,10 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== +eslint-scope@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" + integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -4836,10 +4932,10 @@ eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" + integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== eslint-webpack-plugin@^3.1.1: version "3.1.1" @@ -4853,11 +4949,11 @@ eslint-webpack-plugin@^3.1.1: schema-utils "^3.1.1" eslint@^8.3.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d" - integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw== + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.8.0.tgz#9762b49abad0cb4952539ffdb0a046392e571a2d" + integrity sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ== dependencies: - "@eslint/eslintrc" "^1.2.0" + "@eslint/eslintrc" "^1.0.5" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" @@ -4865,10 +4961,10 @@ eslint@^8.3.0: debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" + eslint-scope "^7.1.0" eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.3.1" + eslint-visitor-keys "^3.2.0" + espree "^9.3.0" esquery "^1.4.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -4893,14 +4989,14 @@ eslint@^8.3.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^9.3.1: - version "9.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" - integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== +espree@^9.2.0, espree@^9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8" + integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ== dependencies: acorn "^8.7.0" acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.1.0" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" @@ -4931,11 +5027,21 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" + integrity sha1-va/oCVOD2EFNXcLs9MkXO225QS4= + estree-walker@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -4976,27 +5082,27 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expect@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" - integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== +expect@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.4.6.tgz#f335e128b0335b6ceb4fcab67ece7cbd14c942e6" + integrity sha512-1M/0kAALIaj5LaG66sFJTbRsWTADnylly82cu4bspI0nl+pgP4E6Bh/aqdHlTUjul06K7xQnnrAoqfxVU0+/ag== dependencies: - "@jest/types" "^27.5.1" - jest-get-type "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" + "@jest/types" "^27.4.2" + jest-get-type "^27.4.0" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" express@^4.17.1: - version "4.17.3" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" - integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== + version "4.17.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" + integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== dependencies: - accepts "~1.3.8" + accepts "~1.3.7" array-flatten "1.1.1" - body-parser "1.19.2" + body-parser "1.19.1" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.2" + cookie "0.4.1" cookie-signature "1.0.6" debug "2.6.9" depd "~1.1.2" @@ -5011,7 +5117,7 @@ express@^4.17.1: parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.9.7" + qs "6.9.6" range-parser "~1.2.1" safe-buffer "5.2.1" send "0.17.2" @@ -5041,7 +5147,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.11, fast-glob@^3.2.9: +fast-glob@^3.0.3, fast-glob@^3.2.11, fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== @@ -5105,10 +5211,10 @@ file-loader@^6.2.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -file-selector@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.4.0.tgz#59ec4f27aa5baf0841e9c6385c8386bef4d18b17" - integrity sha512-iACCiXeMYOvZqlF1kTiYINzgepRBymz1wwjiuup9u9nayhb6g4fSwiyJ/6adli+EPwrWtpgQAh2PoS7HukEGEg== +file-selector@^0.2.2: + version "0.2.4" + resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.2.4.tgz#7b98286f9dbb9925f420130ea5ed0a69238d4d80" + integrity sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA== dependencies: tslib "^2.0.3" @@ -5158,11 +5264,6 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-root@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== - find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -5206,17 +5307,17 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -focus-lock@^0.10.2: - version "0.10.2" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.10.2.tgz#561c62bae8387ecba1dd8e58a6df5ec29835c644" - integrity sha512-DSaI/UHZ/02sg1P616aIWgToQcrKKBmcCvomDZ1PZvcJFj350PnWhSJxJ76T3e5/GbtQEARIACtbrdlrF9C5kA== +focus-lock@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.10.1.tgz#5f46fa74fefb87144479c2f8e276f0eedd8081b2" + integrity sha512-b9yUklCi4fTu2GXn7dnaVf4hiLVVBp7xTiZarAHMODV2To6Bitf6F/UI67RmKbdgJQeVwI1UO0d9HYNbXt3GkA== dependencies: tslib "^2.0.3" follow-redirects@^1.0.0: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== + version "1.14.7" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" + integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== fork-ts-checker-webpack-plugin@^6.5.0: version "6.5.0" @@ -5252,9 +5353,9 @@ forwarded@0.2.0: integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fraction.js@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.3.tgz#be65b0f20762ef27e1e793860bc2dfb716e99e65" - integrity sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg== + version "4.1.2" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8" + integrity sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA== fresh@0.5.2: version "0.5.2" @@ -5262,14 +5363,23 @@ fresh@0.5.2: integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs-extra@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" - integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== + version "10.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" + integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^9.0.0, fs-extra@^9.0.1: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -5405,12 +5515,26 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.6.0, globals@^13.9.0: - version "13.12.1" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" - integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== + version "13.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" + integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== dependencies: type-fest "^0.20.2" +globby@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" + integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@^11.0.1, globby@^11.0.4: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -5428,10 +5552,10 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== -graphql@^16.3.0: - version "16.3.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05" - integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A== +graphql@^15.5.1: + version "15.8.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" + integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== gzip-size@^6.0.0: version "6.0.0" @@ -5466,9 +5590,9 @@ has-flag@^4.0.0: integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== has-tostringtag@^1.0.0: version "1.0.0" @@ -5584,15 +5708,15 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -headers-polyfill@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.0.4.tgz#cd70c815a441dd882372fcd6eda212ce997c9b18" - integrity sha512-I1DOM1EdWYntdrnCvqQtcKwSSuiTzoqOExy4v1mdcFixFZABlWP4IPHdmoLtPda0abMHqDOY4H9svhQ10DFR4w== +headers-utils@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/headers-utils/-/headers-utils-3.0.2.tgz#dfc65feae4b0e34357308aefbcafa99c895e59ef" + integrity sha512-xAxZkM1dRyGV2Ou5bzMxBPNLoRCjcX+ya7KSWybQD2KwLphxsapUVK6x/02o7f4VU6GPSXch9vNY2+gkU8tYWQ== history@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" - integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== + version "5.2.0" + resolved "https://registry.yarnpkg.com/history/-/history-5.2.0.tgz#7cdd31cf9bac3c5d31f09c231c9928fad0007b7c" + integrity sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig== dependencies: "@babel/runtime" "^7.7.6" @@ -5715,9 +5839,9 @@ http-proxy-agent@^4.0.1: debug "4" http-proxy-middleware@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" - integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.2.tgz#94d7593790aad6b3de48164f13792262f656c332" + integrity sha512-XtmDN5w+vdFTBZaYhdJAbMqn0DP/EhkUaAeo963mojwpKMMbw6nivtFKw07D7DDOH745L5k0VL0P8KRYNEVF/g== dependencies: "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" @@ -5788,7 +5912,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -6079,16 +6203,23 @@ is-plain-obj@^3.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== -is-plain-object@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== +is-plain-object@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" + integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + is-regex@^1.0.4, is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -6210,9 +6341,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + version "3.1.3" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.3.tgz#4bcae3103b94518117930d51283690960b50d3c2" + integrity sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -6227,228 +6358,226 @@ jake@^10.6.1: filelist "^1.0.1" minimatch "^3.0.4" -jest-changed-files@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" - integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== +jest-changed-files@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.4.2.tgz#da2547ea47c6e6a5f6ed336151bd2075736eb4a5" + integrity sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" execa "^5.0.0" throat "^6.0.1" -jest-circus@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" - integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== +jest-circus@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.4.6.tgz#d3af34c0eb742a967b1919fbb351430727bcea6c" + integrity sha512-UA7AI5HZrW4wRM72Ro80uRR2Fg+7nR0GESbSI/2M+ambbzVuA63mn5T1p3Z/wlhntzGpIG1xx78GP2YIkf6PhQ== dependencies: - "@jest/environment" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/environment" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" - expect "^27.5.1" + expect "^27.4.6" is-generator-fn "^2.0.0" - jest-each "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" + jest-each "^27.4.6" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + jest-runtime "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" + pretty-format "^27.4.6" slash "^3.0.0" stack-utils "^2.0.3" throat "^6.0.1" -jest-cli@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" - integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== +jest-cli@^27.4.7: + version "27.4.7" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.4.7.tgz#d00e759e55d77b3bcfea0715f527c394ca314e5a" + integrity sha512-zREYhvjjqe1KsGV15mdnxjThKNDgza1fhDT+iUsXWLCq3sxe9w5xnvyctcYVT5PcdLSjv7Y5dCwTS3FCF1tiuw== dependencies: - "@jest/core" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/core" "^27.4.7" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" chalk "^4.0.0" exit "^0.1.2" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" import-local "^3.0.2" - jest-config "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" + jest-config "^27.4.7" + jest-util "^27.4.2" + jest-validate "^27.4.6" prompts "^2.0.1" yargs "^16.2.0" -jest-config@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" - integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== +jest-config@^27.4.7: + version "27.4.7" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.4.7.tgz#4f084b2acbd172c8b43aa4cdffe75d89378d3972" + integrity sha512-xz/o/KJJEedHMrIY9v2ParIoYSrSVY6IVeE4z5Z3i101GoA5XgfbJz+1C8EYPsv7u7f39dS8F9v46BHDhn0vlw== dependencies: "@babel/core" "^7.8.0" - "@jest/test-sequencer" "^27.5.1" - "@jest/types" "^27.5.1" - babel-jest "^27.5.1" + "@jest/test-sequencer" "^27.4.6" + "@jest/types" "^27.4.2" + babel-jest "^27.4.6" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.1" - graceful-fs "^4.2.9" - jest-circus "^27.5.1" - jest-environment-jsdom "^27.5.1" - jest-environment-node "^27.5.1" - jest-get-type "^27.5.1" - jest-jasmine2 "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-runner "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" + graceful-fs "^4.2.4" + jest-circus "^27.4.6" + jest-environment-jsdom "^27.4.6" + jest-environment-node "^27.4.6" + jest-get-type "^27.4.0" + jest-jasmine2 "^27.4.6" + jest-regex-util "^27.4.0" + jest-resolve "^27.4.6" + jest-runner "^27.4.6" + jest-util "^27.4.2" + jest-validate "^27.4.6" micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^27.5.1" + pretty-format "^27.4.6" slash "^3.0.0" - strip-json-comments "^3.1.1" -jest-diff@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== +jest-diff@^27.0.0, jest-diff@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.6.tgz#93815774d2012a2cbb6cf23f84d48c7a2618f98d" + integrity sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w== dependencies: chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" + diff-sequences "^27.4.0" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" -jest-docblock@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" - integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== +jest-docblock@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.4.0.tgz#06c78035ca93cbbb84faf8fce64deae79a59f69f" + integrity sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg== dependencies: detect-newline "^3.0.0" -jest-each@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" - integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== +jest-each@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.4.6.tgz#e7e8561be61d8cc6dbf04296688747ab186c40ff" + integrity sha512-n6QDq8y2Hsmn22tRkgAk+z6MCX7MeVlAzxmZDshfS2jLcaBlyhpF3tZSJLR+kXmh23GEvS0ojMR8i6ZeRvpQcA== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" chalk "^4.0.0" - jest-get-type "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" - -jest-environment-jsdom@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" - integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" + jest-get-type "^27.4.0" + jest-util "^27.4.2" + pretty-format "^27.4.6" + +jest-environment-jsdom@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.4.6.tgz#c23a394eb445b33621dfae9c09e4c8021dea7b36" + integrity sha512-o3dx5p/kHPbUlRvSNjypEcEtgs6LmvESMzgRFQE6c+Prwl2JLA4RZ7qAnxc5VM8kutsGRTB15jXeeSbJsKN9iA== + dependencies: + "@jest/environment" "^27.4.6" + "@jest/fake-timers" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" - jest-mock "^27.5.1" - jest-util "^27.5.1" + jest-mock "^27.4.6" + jest-util "^27.4.2" jsdom "^16.6.0" -jest-environment-node@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" - integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== +jest-environment-node@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.4.6.tgz#ee8cd4ef458a0ef09d087c8cd52ca5856df90242" + integrity sha512-yfHlZ9m+kzTKZV0hVfhVu6GuDxKAYeFHrfulmy7Jxwsq4V7+ZK7f+c0XP/tbVDMQW7E4neG2u147hFkuVz0MlQ== dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/environment" "^27.4.6" + "@jest/fake-timers" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" - jest-mock "^27.5.1" - jest-util "^27.5.1" + jest-mock "^27.4.6" + jest-util "^27.4.2" -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== +jest-get-type@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" + integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== -jest-haste-map@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" - integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== +jest-haste-map@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.4.6.tgz#c60b5233a34ca0520f325b7e2cc0a0140ad0862a" + integrity sha512-0tNpgxg7BKurZeFkIOvGCkbmOHbLFf4LUQOxrQSMjvrQaQe3l6E8x6jYC1NuWkGo5WDdbr8FEzUxV2+LWNawKQ== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^27.5.1" - jest-serializer "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" + graceful-fs "^4.2.4" + jest-regex-util "^27.4.0" + jest-serializer "^27.4.0" + jest-util "^27.4.2" + jest-worker "^27.4.6" micromatch "^4.0.4" walker "^1.0.7" optionalDependencies: fsevents "^2.3.2" -jest-jasmine2@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" - integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== +jest-jasmine2@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.4.6.tgz#109e8bc036cb455950ae28a018f983f2abe50127" + integrity sha512-uAGNXF644I/whzhsf7/qf74gqy9OuhvJ0XYp8SDecX2ooGeaPnmJMjXjKt0mqh1Rl5dtRGxJgNrHlBQIBfS5Nw== dependencies: - "@jest/environment" "^27.5.1" - "@jest/source-map" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/environment" "^27.4.6" + "@jest/source-map" "^27.4.0" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^27.5.1" + expect "^27.4.6" is-generator-fn "^2.0.0" - jest-each "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" + jest-each "^27.4.6" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + jest-runtime "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" + pretty-format "^27.4.6" throat "^6.0.1" -jest-leak-detector@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" - integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== +jest-leak-detector@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.4.6.tgz#ed9bc3ce514b4c582637088d9faf58a33bd59bf4" + integrity sha512-kkaGixDf9R7CjHm2pOzfTxZTQQQ2gHTIWKY/JZSiYTc90bZp8kSZnUMS3uLAfwTZwc0tcMRoEX74e14LG1WapA== dependencies: - jest-get-type "^27.5.1" - pretty-format "^27.5.1" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" -jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" - integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== +jest-matcher-utils@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.4.6.tgz#53ca7f7b58170638590e946f5363b988775509b8" + integrity sha512-XD4PKT3Wn1LQnRAq7ZsTI0VRuEc9OrCPFiO1XL7bftTGmfNF0DcEwMHRgqiu7NGf8ZoZDREpGrCniDkjt79WbA== dependencies: chalk "^4.0.0" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" + jest-diff "^27.4.6" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" -jest-message-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" - integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== +jest-message-util@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.4.6.tgz#9fdde41a33820ded3127465e1a5896061524da31" + integrity sha512-0p5szriFU0U74czRSFjH6RyS7UYIAkn/ntwMuOwTGWrQIOh5NzXXrq72LOqIkJKKvFbPq+byZKuBz78fjBERBA== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" micromatch "^4.0.4" - pretty-format "^27.5.1" + pretty-format "^27.4.6" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" - integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== +jest-mock@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.4.6.tgz#77d1ba87fbd33ccb8ef1f061697e7341b7635195" + integrity sha512-kvojdYRkst8iVSZ1EJ+vc1RRD9llueBjKzXzeCytH3dMM7zvPV/ULcfI2nr0v0VUgm3Bjt3hBCQvOeaBz+ZTHw== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -6456,150 +6585,151 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== -jest-regex-util@^27.0.0, jest-regex-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" - integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== +jest-regex-util@^27.0.0, jest-regex-util@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.4.0.tgz#e4c45b52653128843d07ad94aec34393ea14fbca" + integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== -jest-resolve-dependencies@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" - integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== +jest-resolve-dependencies@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.6.tgz#fc50ee56a67d2c2183063f6a500cc4042b5e2327" + integrity sha512-W85uJZcFXEVZ7+MZqIPCscdjuctruNGXUZ3OHSXOfXR9ITgbUKeHj+uGcies+0SsvI5GtUfTw4dY7u9qjTvQOw== dependencies: - "@jest/types" "^27.5.1" - jest-regex-util "^27.5.1" - jest-snapshot "^27.5.1" + "@jest/types" "^27.4.2" + jest-regex-util "^27.4.0" + jest-snapshot "^27.4.6" -jest-resolve@^27.4.2, jest-resolve@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" - integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== +jest-resolve@^27.4.2, jest-resolve@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.4.6.tgz#2ec3110655e86d5bfcfa992e404e22f96b0b5977" + integrity sha512-SFfITVApqtirbITKFAO7jOVN45UgFzcRdQanOFzjnbd+CACDoyeX7206JyU92l4cRr73+Qy/TlW51+4vHGt+zw== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" + graceful-fs "^4.2.4" + jest-haste-map "^27.4.6" jest-pnp-resolver "^1.2.2" - jest-util "^27.5.1" - jest-validate "^27.5.1" + jest-util "^27.4.2" + jest-validate "^27.4.6" resolve "^1.20.0" resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" - integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== +jest-runner@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.4.6.tgz#1d390d276ec417e9b4d0d081783584cbc3e24773" + integrity sha512-IDeFt2SG4DzqalYBZRgbbPmpwV3X0DcntjezPBERvnhwKGWTW7C5pbbA5lVkmvgteeNfdd/23gwqv3aiilpYPg== dependencies: - "@jest/console" "^27.5.1" - "@jest/environment" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/console" "^27.4.6" + "@jest/environment" "^27.4.6" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" emittery "^0.8.1" - graceful-fs "^4.2.9" - jest-docblock "^27.5.1" - jest-environment-jsdom "^27.5.1" - jest-environment-node "^27.5.1" - jest-haste-map "^27.5.1" - jest-leak-detector "^27.5.1" - jest-message-util "^27.5.1" - jest-resolve "^27.5.1" - jest-runtime "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-docblock "^27.4.0" + jest-environment-jsdom "^27.4.6" + jest-environment-node "^27.4.6" + jest-haste-map "^27.4.6" + jest-leak-detector "^27.4.6" + jest-message-util "^27.4.6" + jest-resolve "^27.4.6" + jest-runtime "^27.4.6" + jest-util "^27.4.2" + jest-worker "^27.4.6" source-map-support "^0.5.6" throat "^6.0.1" -jest-runtime@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" - integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/globals" "^27.5.1" - "@jest/source-map" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" +jest-runtime@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.4.6.tgz#83ae923818e3ea04463b22f3597f017bb5a1cffa" + integrity sha512-eXYeoR/MbIpVDrjqy5d6cGCFOYBFFDeKaNWqTp0h6E74dK0zLHzASQXJpl5a2/40euBmKnprNLJ0Kh0LCndnWQ== + dependencies: + "@jest/environment" "^27.4.6" + "@jest/fake-timers" "^27.4.6" + "@jest/globals" "^27.4.6" + "@jest/source-map" "^27.4.0" + "@jest/test-result" "^27.4.6" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" execa "^5.0.0" glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-message-util "^27.5.1" - jest-mock "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" + graceful-fs "^4.2.4" + jest-haste-map "^27.4.6" + jest-message-util "^27.4.6" + jest-mock "^27.4.6" + jest-regex-util "^27.4.0" + jest-resolve "^27.4.6" + jest-snapshot "^27.4.6" + jest-util "^27.4.2" slash "^3.0.0" strip-bom "^4.0.0" -jest-serializer@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" - integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== +jest-serializer@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.4.0.tgz#34866586e1cae2388b7d12ffa2c7819edef5958a" + integrity sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ== dependencies: "@types/node" "*" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" -jest-snapshot@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" - integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== +jest-snapshot@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.4.6.tgz#e2a3b4fff8bdce3033f2373b2e525d8b6871f616" + integrity sha512-fafUCDLQfzuNP9IRcEqaFAMzEe7u5BF7mude51wyWv7VRex60WznZIC7DfKTgSIlJa8aFzYmXclmN328aqSDmQ== dependencies: "@babel/core" "^7.7.2" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.0.0" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^27.5.1" - graceful-fs "^4.2.9" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - jest-haste-map "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-util "^27.5.1" + expect "^27.4.6" + graceful-fs "^4.2.4" + jest-diff "^27.4.6" + jest-get-type "^27.4.0" + jest-haste-map "^27.4.6" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + jest-util "^27.4.2" natural-compare "^1.4.0" - pretty-format "^27.5.1" + pretty-format "^27.4.6" semver "^7.3.2" -jest-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" - integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== +jest-util@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.4.2.tgz#ed95b05b1adfd761e2cda47e0144c6a58e05a621" + integrity sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" picomatch "^2.2.3" -jest-validate@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" - integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== +jest-validate@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.4.6.tgz#efc000acc4697b6cf4fa68c7f3f324c92d0c4f1f" + integrity sha512-872mEmCPVlBqbA5dToC57vA3yJaMRfIdpCoD3cyHWJOMx+SJwLNw0I71EkWs41oza/Er9Zno9XuTkRYCPDUJXQ== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^27.5.1" + jest-get-type "^27.4.0" leven "^3.1.0" - pretty-format "^27.5.1" + pretty-format "^27.4.6" jest-watch-typeahead@^1.0.0: version "1.0.0" @@ -6614,17 +6744,17 @@ jest-watch-typeahead@^1.0.0: string-length "^5.0.1" strip-ansi "^7.0.1" -jest-watcher@^27.0.0, jest-watcher@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" - integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== +jest-watcher@^27.0.0, jest-watcher@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.4.6.tgz#673679ebeffdd3f94338c24f399b85efc932272d" + integrity sha512-yKQ20OMBiCDigbD0quhQKLkBO+ObGN79MO4nT7YaCuQ5SM+dkBNWE8cZX0FjU6czwMvWw6StWbe+Wv4jJPJ+fw== dependencies: - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" + "@jest/test-result" "^27.4.6" + "@jest/types" "^27.4.2" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^27.5.1" + jest-util "^27.4.2" string-length "^4.0.1" jest-worker@^26.2.1: @@ -6636,23 +6766,23 @@ jest-worker@^26.2.1: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^27.0.2, jest-worker@^27.3.1, jest-worker@^27.4.5, jest-worker@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== +jest-worker@^27.0.2, jest-worker@^27.3.1, jest-worker@^27.4.1, jest-worker@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" + integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^8.0.0" jest@^27.4.3: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" - integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ== + version "27.4.7" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.4.7.tgz#87f74b9026a1592f2da05b4d258e57505f28eca4" + integrity sha512-8heYvsx7nV/m8m24Vk26Y87g73Ba6ueUd0MWed/NXMhSZIm62U/llVbS0PJe1SHunbyXjJ/BqG1z9bFjGUIvTg== dependencies: - "@jest/core" "^27.5.1" + "@jest/core" "^27.4.7" import-local "^3.0.2" - jest-cli "^27.5.1" + jest-cli "^27.4.7" js-levenshtein@^1.1.6: version "1.1.6" @@ -6771,6 +6901,13 @@ json5@^2.1.2, json5@^2.2.0: dependencies: minimist "^1.2.5" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -6974,11 +7111,11 @@ lz-string@^1.4.4: integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= magic-string@^0.25.0, magic-string@^0.25.7: - version "0.25.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" - integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== dependencies: - sourcemap-codec "^1.4.8" + sourcemap-codec "^1.4.4" make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" @@ -7038,6 +7175,11 @@ mdn-data@2.0.4: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== +mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== + mdurl@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" @@ -7048,7 +7190,7 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -memfs@^3.1.2, memfs@^3.4.1: +memfs@^3.1.2, memfs@^3.2.2: version "3.4.1" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== @@ -7070,7 +7212,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0, merge2@^1.4.1: +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -7093,17 +7235,12 @@ microseconds@0.2.0: resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== -mime-db@1.51.0: +mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": version "1.51.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== -"mime-db@>= 1.43.0 < 2": - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== @@ -7126,9 +7263,9 @@ min-indent@^1.0.0: integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== mini-css-extract-plugin@^2.4.5: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz#578aebc7fc14d32c0ad304c2c34f08af44673f5e" - integrity sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w== + version "2.5.3" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9" + integrity sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw== dependencies: schema-utils "^4.0.0" @@ -7137,14 +7274,14 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.4, minimatch@^3.1.2: +minimatch@^3.0.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -7152,9 +7289,9 @@ minimatch@^3.0.4, minimatch@^3.1.2: brace-expansion "^1.1.7" minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" @@ -7164,9 +7301,9 @@ mkdirp@^0.5.5, mkdirp@~0.5.1: minimist "^1.2.5" moment@^2.29.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + version "2.29.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.2.tgz#00910c60b20843bcba52d37d58c628b47b1f20e4" + integrity sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg== ms@2.0.0: version "2.0.0" @@ -7183,21 +7320,22 @@ ms@2.1.3, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -msw@^0.38.2: - version "0.38.2" - resolved "https://registry.yarnpkg.com/msw/-/msw-0.38.2.tgz#0c3637b392b65d5cc781468036c4be5965382c58" - integrity sha512-gD2vkV/ol3+zaC6AHKlPxB4zvl5mTV1uzhcv+0H6kwlbaiTZe/vVwiEGPeE9mQroAFvh0c8uJmltDebEys28qA== +msw@^0.36.8: + version "0.36.8" + resolved "https://registry.yarnpkg.com/msw/-/msw-0.36.8.tgz#33ff8bfb0299626a95f43d0e4c3dc2c73c17f1ba" + integrity sha512-K7lOQoYqhGhTSChsmHMQbf/SDCsxh/m0uhN6Ipt206lGoe81fpTmaGD0KLh4jUxCONMOUnwCSj0jtX2CM4pEdw== dependencies: "@mswjs/cookies" "^0.1.7" - "@mswjs/interceptors" "^0.13.5" + "@mswjs/interceptors" "^0.12.7" "@open-draft/until" "^1.0.3" "@types/cookie" "^0.4.1" - "@types/js-levenshtein" "^1.1.1" + "@types/inquirer" "^8.1.3" + "@types/js-levenshtein" "^1.1.0" chalk "4.1.1" chokidar "^3.4.2" - cookie "^0.4.2" - graphql "^16.3.0" - headers-polyfill "^3.0.4" + cookie "^0.4.1" + graphql "^15.5.1" + headers-utils "^3.0.2" inquirer "^8.2.0" is-node-process "^1.0.1" js-levenshtein "^1.1.6" @@ -7206,7 +7344,7 @@ msw@^0.38.2: statuses "^2.0.0" strict-event-emitter "^0.2.0" type-fest "^1.2.2" - yargs "^17.3.1" + yargs "^17.3.0" multicast-dns-service-types@^1.1.0: version "1.1.0" @@ -7233,20 +7371,20 @@ nano-time@1.0.0: dependencies: big-integer "^1.6.16" -nanoid@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +nanoid@^3.1.30: + version "3.2.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" + integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== neo-async@^2.6.2: version "2.6.2" @@ -7276,19 +7414,19 @@ node-fetch@^2.6.7: whatwg-url "^5.0.0" node-forge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" - integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== + version "1.3.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" + integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-releases@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== +node-releases@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" + integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -7507,7 +7645,7 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -outvariant@^1.2.1: +outvariant@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.2.1.tgz#e630f6cdc1dbf398ed857e36f219de4a005ccd35" integrity sha512-bcILvFkvpMXh66+Ubax/inxbKRyWTUiiFIW2DWkiS79wakrLGn3Ydy+GvukadiyfZjaL6C7YhIem4EZSM282wA== @@ -7613,7 +7751,7 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse-json@^5.0.0, parse-json@^5.2.0: +parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -7741,25 +7879,25 @@ postcss-browser-comments@^4: resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz#bcfc86134df5807f5d3c0eefa191d42136b5e72a" integrity sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg== -postcss-calc@^8.2.3: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== +postcss-calc@^8.2.0: + version "8.2.3" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.3.tgz#53b95ce93de19213c2a5fdd71277a81690ef41d0" + integrity sha512-EGM2EBBWqP57N0E7N7WOLT116PJ39dwHVU01WO4XPPQLJfkL2xVgkMZ+TZvCfapj/uJH07UEfKHQNPHzSw/14Q== dependencies: - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" -postcss-color-functional-notation@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.2.tgz#f59ccaeb4ee78f1b32987d43df146109cc743073" - integrity sha512-DXVtwUhIk4f49KK5EGuEdgx4Gnyj6+t2jBSEmxvpIK9QI40tWrpS2Pua8Q7iIZWBrki2QOaeUdEaLPPa91K0RQ== +postcss-color-functional-notation@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.1.tgz#a25e9e1855e14d04319222a689f120b3240d39e0" + integrity sha512-62OBIXCjRXpQZcFOYIXwXBlpAVWrYk8ek1rcjvMING4Q2cf0ipyN9qT+BhHA6HmftGSEnFQu2qgKO3gMscl3Rw== dependencies: postcss-value-parser "^4.2.0" -postcss-color-hex-alpha@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz#61a0fd151d28b128aa6a8a21a2dad24eebb34d52" - integrity sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw== +postcss-color-hex-alpha@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.2.tgz#7a248b006dd47bd83063f662352d31fd982f74ec" + integrity sha512-gyx8RgqSmGVK156NAdKcsfkY3KPGHhKqvHTL3hhveFrBBToguKFzhyiuk3cljH6L4fJ0Kv+JENuPXs1Wij27Zw== dependencies: postcss-value-parser "^4.2.0" @@ -7770,20 +7908,20 @@ postcss-color-rebeccapurple@^7.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-colormin@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" - integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== +postcss-colormin@^5.2.4: + version "5.2.4" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.4.tgz#7726d3f3d24f111d39faff50a6500688225d5324" + integrity sha512-rYlC5015aNqVQt/B6Cy156g7sH5tRUJGmT9xeagYthtKehetbKx7jHxhyLpulP4bs4vbp8u/B2rac0J7S7qPQg== dependencies: browserslist "^4.16.6" caniuse-api "^3.0.0" colord "^2.9.1" postcss-value-parser "^4.2.0" -postcss-convert-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.0.tgz#f8d3abe40b4ce4b1470702a0706343eac17e7c10" - integrity sha512-GkyPbZEYJiWtQB0KZ0X6qusqFHUepguBCNFi9t5JJc7I2OTXG7C0twbTLvCfaKOLl3rSXmpAwV7W5txd91V84g== +postcss-convert-values@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.3.tgz#492db08a28af84d57651f10edc8f6c8fb2f6df40" + integrity sha512-fVkjHm2T0PSMqXUCIhHNWVGjhB9mHEWX2GboVs7j3iCgr6FpIl9c/IdXy0PHWZSQ9LFTRgmj98amxJE6KOnlsA== dependencies: postcss-value-parser "^4.2.0" @@ -7792,10 +7930,10 @@ postcss-custom-media@^8.0.0: resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz#1be6aff8be7dc9bf1fe014bde3b71b92bb4552f1" integrity sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g== -postcss-custom-properties@^12.1.4: - version "12.1.4" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.4.tgz#e3d8a8000f28094453b836dff5132385f2862285" - integrity sha512-i6AytuTCoDLJkWN/MtAIGriJz3j7UX6bV7Z5t+KgFz+dwZS15/mlTJY1S0kRizlk6ba0V8u8hN50Fz5Nm7tdZw== +postcss-custom-properties@^12.1.2: + version "12.1.3" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.3.tgz#8e37651c7188e72e6762eeae8db39755e84d3a64" + integrity sha512-rtu3otIeY532PnEuuBrIIe+N+pcdbX/7JMZfrcL09wc78YayrHw5E8UkDfvnlOhEUrI4ptCuzXQfj+Or6spbGA== dependencies: postcss-value-parser "^4.2.0" @@ -7806,45 +7944,44 @@ postcss-custom-selectors@^6.0.0: dependencies: postcss-selector-parser "^6.0.4" -postcss-dir-pseudo-class@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz#9afe49ea631f0cb36fa0076e7c2feb4e7e3f049c" - integrity sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw== +postcss-dir-pseudo-class@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.3.tgz#febfe305e75267913a53bf5094c7679f5cfa9b55" + integrity sha512-qiPm+CNAlgXiMf0J5IbBBEXA9l/Q5HGsNGkL3znIwT2ZFRLGY9U2fTUpa4lqCUXQOxaLimpacHeQC80BD2qbDw== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.8" -postcss-discard-comments@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.0.tgz#87be4e0953bf599935837b940c701f8d4eca7d0b" - integrity sha512-L0IKF4jAshRyn03SkEO6ar/Ipz2oLywVbg2THf2EqqdNkBwmVMxuTR/RoAltOw4piiaLt3gCAdrbAqmTBInmhg== +postcss-discard-comments@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.2.tgz#811ed34e2b6c40713daab0beb4d7a04125927dcd" + integrity sha512-6VQ3pYTsJHEsN2Bic88Aa7J/Brn4Bv8j/rqaFQZkH+pcVkKYwxCIvoMQkykEW7fBjmofdTnQgcivt5CCBJhtrg== -postcss-discard-duplicates@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" - integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== +postcss-discard-duplicates@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.2.tgz#61076f3d256351bdaac8e20aade730fef0609f44" + integrity sha512-LKY81YjUjc78p6rbXIsnppsaFo8XzCoMZkXVILJU//sK0DgPkPSpuq/cZvHss3EtdKvWNYgWzQL+wiJFtEET4g== -postcss-discard-empty@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.0.tgz#7f51b16cd1b89f8180bbc7cee34d6cbabf2ef810" - integrity sha512-782T/buGgb3HOuHOJAHpdyKzAAKsv/BxWqsutnZ+QsiHEcDkY7v+6WWdturuBiSal6XMOO1p1aJvwXdqLD5vhA== +postcss-discard-empty@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.2.tgz#0676a9bcfc44bb00d338352a45ab80845a31d8f0" + integrity sha512-SxBsbTjlsKUvZLL+dMrdWauuNZU8TBq5IOL/DHa6jBUSXFEwmDqeXRfTIK/FQpPTa8MJMxEHjSV3UbiuyLARPQ== -postcss-discard-overridden@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" - integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== +postcss-discard-overridden@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.3.tgz#004b9818cabb407e60616509267567150b327a3f" + integrity sha512-yRTXknIZA4k8Yo4FiF1xbsLj/VBxfXEWxJNIrtIy6HC9KQ4xJxcPtoaaskh6QptCGrrcGnhKsTsENTRPZOBu4g== -postcss-double-position-gradients@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.0.tgz#a8614fb3a2a4b8877bffb8961b770e00322bbad1" - integrity sha512-oz73I08yMN3oxjj0s8mED1rG+uOYoK3H8N9RjQofyg52KBRNmePJKg3fVwTpL2U5ZFbCzXoZBsUD/CvZdlqE4Q== +postcss-double-position-gradients@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.0.4.tgz#2484b9785ef3ba81b0f03a279c52ec58fc5344c2" + integrity sha512-qz+s5vhKJlsHw8HjSs+HVk2QGFdRyC68KGRQGX3i+GcnUjhWhXQEmCXW6siOJkZ1giu0ddPwSO6I6JdVVVPoog== dependencies: - "@csstools/postcss-progressive-custom-properties" "^1.1.0" postcss-value-parser "^4.2.0" -postcss-env-function@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.5.tgz#b9614d50abd91e4c88a114644a9766880dabe393" - integrity sha512-gPUJc71ji9XKyl0WSzAalBeEA/89kU+XpffpPxSaaaZ1c48OL36r1Ep5R6+9XAPkIiDlSvVAwP4io12q/vTcvA== +postcss-env-function@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.4.tgz#4e85359ca4fcdde4ec4b73752a41de818dbe91cc" + integrity sha512-0ltahRTPtXSIlEZFv7zIvdEib7HN0ZbUQxrxIKn8KbiRyhALo854I/CggU5lyZe6ZBvSTJ6Al2vkZecI2OhneQ== dependencies: postcss-value-parser "^4.2.0" @@ -7853,34 +7990,34 @@ postcss-flexbugs-fixes@^5.0.2: resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d" integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ== -postcss-focus-visible@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e" - integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw== +postcss-focus-visible@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.3.tgz#14635b71a6b9140f488f11f26cbc9965a13f6843" + integrity sha512-ozOsg+L1U8S+rxSHnJJiET6dNLyADcPHhEarhhtCI9DBLGOPG/2i4ddVoFch9LzrBgb8uDaaRI4nuid2OM82ZA== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.8" -postcss-focus-within@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20" - integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ== +postcss-focus-within@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.3.tgz#0b0bf425f14a646bbfd973b463e2d20d85a3a841" + integrity sha512-fk9y2uFS6/Kpp7/A9Hz9Z4rlFQ8+tzgBcQCXAFSrXFGAbKx+4ZZOmmfHuYjCOMegPWoz0pnC6fNzi8j7Xyqp5Q== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.8" postcss-font-variant@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66" integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA== -postcss-gap-properties@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz#6401bb2f67d9cf255d677042928a70a915e6ba60" - integrity sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ== +postcss-gap-properties@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.2.tgz#562fbf43a6a721565b3ca0e01008690991d2f726" + integrity sha512-EaMy/pbxtQnKDsnbEjdqlkCkROTQZzolcLKgIE+3b7EuJfJydH55cZeHfm+MtIezXRqhR80VKgaztO/vHq94Fw== -postcss-image-set-function@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz#bcff2794efae778c09441498f40e0c77374870a9" - integrity sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A== +postcss-image-set-function@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.4.tgz#ce91579ab2c1386d412ff5cd5e733c474b1f75ee" + integrity sha512-BlEo9gSTj66lXjRNByvkMK9dEdEGFXRfGjKRi9fo8s0/P3oEk74cAoonl/utiM50E2OPVb/XSu+lWvdW4KtE/Q== dependencies: postcss-value-parser "^4.2.0" @@ -7896,18 +8033,17 @@ postcss-js@^4.0.0: dependencies: camelcase-css "^2.0.1" -postcss-lab-function@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.1.1.tgz#8b37dfcb9ca4ff82bbe7192c7ba3cc2bccbc0ef1" - integrity sha512-j3Z0WQCimY2tMle++YcmygnnVbt6XdnrCV1FO2IpzaCSmtTF2oO8h4ZYUA1Q+QHYroIiaWPvNHt9uBR4riCksQ== +postcss-lab-function@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.0.3.tgz#633745b324afbcd5881da85fe2cef58b17487536" + integrity sha512-MH4tymWmefdZQ7uVG/4icfLjAQmH6o2NRYyVh2mKoB4RXJp9PjsyhZwhH4ouaCQHvg+qJVj3RzeAR1EQpIlXZA== dependencies: - "@csstools/postcss-progressive-custom-properties" "^1.1.0" postcss-value-parser "^4.2.0" postcss-load-config@^3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.3.tgz#21935b2c43b9a86e6581a576ca7ee1bde2bd1d23" - integrity sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw== + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.1.tgz#2f53a17f2f543d9e63864460af42efdac0d41f87" + integrity sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg== dependencies: lilconfig "^2.0.4" yaml "^1.10.2" @@ -7921,63 +8057,63 @@ postcss-loader@^6.2.1: klona "^2.0.5" semver "^7.3.5" -postcss-logical@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73" - integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g== +postcss-logical@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.3.tgz#9934e0fb16af70adbd94217b24d2f315ceb5c2f0" + integrity sha512-P5NcHWYrif0vK8rgOy/T87vg0WRIj3HSknrvp1wzDbiBeoDPVmiVRmkown2eSQdpPveat/MC1ess5uhzZFVnqQ== postcss-media-minmax@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== -postcss-merge-longhand@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.0.tgz#f716bffbf0bdfbde6ea78c36088e21559f8a0a95" - integrity sha512-Gr46srN2tsLD8fudKYoHO56RG0BLQ2nsBRnSZGY04eNBPwTeWa9KeHrbL3tOLAHyB2aliikycPH2TMJG1U+W6g== +postcss-merge-longhand@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.5.tgz#cbc217ca22fb5a3e6ee22a6a1aa6920ec1f3c628" + integrity sha512-R2BCPJJ/U2oh1uTWEYn9CcJ7MMcQ1iIbj9wfr2s/zHu5om5MP/ewKdaunpfJqR1WYzqCsgnXuRoVXPAzxdqy8g== dependencies: postcss-value-parser "^4.2.0" - stylehacks "^5.1.0" + stylehacks "^5.0.2" -postcss-merge-rules@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.0.tgz#a2d5117eba09c8686a5471d97bd9afcf30d1b41f" - integrity sha512-NecukEJovQ0mG7h7xV8wbYAkXGTO3MPKnXvuiXzOKcxoOodfTTKYjeo8TMhAswlSkjcPIBlnKbSFcTuVSDaPyQ== +postcss-merge-rules@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.5.tgz#2a18669ec214019884a60f0a0d356803a8138366" + integrity sha512-3Oa26/Pb9VOFVksJjFG45SNoe4nhGvJ2Uc6TlRimqF8uhfOCEhVCaJ3rvEat5UFOn2UZqTY5Da8dFgCh3Iq0Ug== dependencies: browserslist "^4.16.6" caniuse-api "^3.0.0" - cssnano-utils "^3.1.0" + cssnano-utils "^3.0.1" postcss-selector-parser "^6.0.5" -postcss-minify-font-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" - integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== +postcss-minify-font-values@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.3.tgz#48c455c4cd980ecd07ac9bf3fc58e9d8a2ae4168" + integrity sha512-bC45rVzEwsLhv/cL1eCjoo2OOjbSk9I7HKFBYnBvtyuIZlf7uMipMATXtA0Fc3jwPo3wuPIW1jRJWKzflMh1sA== dependencies: postcss-value-parser "^4.2.0" -postcss-minify-gradients@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.0.tgz#de0260a67a13b7b321a8adc3150725f2c6612377" - integrity sha512-J/TMLklkONn3LuL8wCwfwU8zKC1hpS6VcxFkNUNjmVt53uKqrrykR3ov11mdUYyqVMEx67slMce0tE14cE4DTg== +postcss-minify-gradients@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.5.tgz#a5572b9c98ed52cbd7414db24b873f8b9e418290" + integrity sha512-/YjvXs8PepsoiZAIpjstOO4IHKwFAqYNqbA1yVdqklM84tbUUneh6omJxGlRlF3mi6K5Pa067Mg6IwqEnYC8Zg== dependencies: colord "^2.9.1" - cssnano-utils "^3.1.0" + cssnano-utils "^3.0.1" postcss-value-parser "^4.2.0" -postcss-minify-params@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.0.tgz#e0b1f4e05cfd396682f612856485907e4064f25e" - integrity sha512-q67dcts4Hct6x8+JmhBgctHkbvUsqGIg2IItenjE63iZXMbhjr7AlVZkNnKtIGt/1Wsv7p/7YzeSII6Q+KPXRg== +postcss-minify-params@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.4.tgz#230a4d04456609e614db1d48c2eebc21f6490a45" + integrity sha512-Z0vjod9lRZEmEPfEmA2sCfjbfEEFKefMD3RDIQSUfXK4LpCyWkX1CniUgyNvnjJFLDPSxtgKzozhHhPHKoeGkg== dependencies: browserslist "^4.16.6" - cssnano-utils "^3.1.0" + cssnano-utils "^3.0.1" postcss-value-parser "^4.2.0" -postcss-minify-selectors@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.0.tgz#17c2be233e12b28ffa8a421a02fc8b839825536c" - integrity sha512-vYxvHkW+iULstA+ctVNx0VoRAR4THQQRkG77o0oa4/mBS0OzGvvzLIvHDv/nNEM0crzN2WIyFU5X7wZhaUK3RA== +postcss-minify-selectors@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.2.tgz#bc9698f713b9dab7f44f1ec30643fcbad9a043c0" + integrity sha512-gpn1nJDMCf3g32y/7kl+jsdamhiYT+/zmEt57RoT9GmzlixBNRPohI7k8UIHelLABhdLf3MSZhtM33xuH5eQOQ== dependencies: postcss-selector-parser "^6.0.5" @@ -8023,66 +8159,66 @@ postcss-nesting@^10.1.2: dependencies: postcss-selector-parser "^6.0.8" -postcss-normalize-charset@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" - integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== +postcss-normalize-charset@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.2.tgz#eb6130c8a8e950ce25f9ea512de1d9d6a6f81439" + integrity sha512-fEMhYXzO8My+gC009qDc/3bgnFP8Fv1Ic8uw4ec4YTlhIOw63tGPk1YFd7fk9bZUf1DAbkhiL/QPWs9JLqdF2g== -postcss-normalize-display-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" - integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== +postcss-normalize-display-values@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.2.tgz#8b5273c6c7d0a445e6ef226b8a5bb3204a55fb99" + integrity sha512-RxXoJPUR0shSjkMMzgEZDjGPrgXUVYyWA/YwQRicb48H15OClPuaDR7tYokLAlGZ2tCSENEN5WxjgxSD5m4cUw== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz#902a7cb97cf0b9e8b1b654d4a43d451e48966458" - integrity sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ== +postcss-normalize-positions@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.3.tgz#b63fcc4ff5fbf65934fafaf83270b2da214711d1" + integrity sha512-U+rmhjrNBvIGYqr/1tD4wXPFFMKUbXsYXvlUCzLi0tOCUS6LoeEAnmVXXJY/MEB/1CKZZwBSs2tmzGawcygVBA== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz#f6d6fd5a54f51a741cc84a37f7459e60ef7a6398" - integrity sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw== +postcss-normalize-repeat-style@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.3.tgz#488c0ad8aac0fa4f66ef56cc8d604b3fd9bf705f" + integrity sha512-uk1+xYx0AMbA3nLSNhbDrqbf/rx+Iuq5tVad2VNyaxxJzx79oGieJ6D9F6AfOL2GtiIbP7vTYlpYHtG+ERFXTg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" - integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== +postcss-normalize-string@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.3.tgz#49e0a1d58a119d5435ef21893ad03136a6e8f0e6" + integrity sha512-Mf2V4JbIDboNGQhW6xW0YREDiYXoX3WrD3EjKkjvnpAJ6W4qqjLnK/c9aioyVFaWWHVdP5zVRw/9DI5S3oLDFw== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" - integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== +postcss-normalize-timing-functions@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.2.tgz#db4f4f49721f47667afd1fdc5edb032f8d9cdb2e" + integrity sha512-Ao0PP6MoYsRU1LxeVUW740ioknvdIUmfr6uAA3xWlQJ9s69/Tupy8qwhuKG3xWfl+KvLMAP9p2WXF9cwuk/7Bg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz#3d23aede35e160089a285e27bf715de11dc9db75" - integrity sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ== +postcss-normalize-unicode@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.3.tgz#10f0d30093598a58c48a616491cc7fa53256dd43" + integrity sha512-uNC7BmS/7h6to2UWa4RFH8sOTzu2O9dVWPE/F9Vm9GdhONiD/c1kNaCLbmsFHlKWcEx7alNUChQ+jH/QAlqsQw== dependencies: browserslist "^4.16.6" postcss-value-parser "^4.2.0" -postcss-normalize-url@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" - integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== +postcss-normalize-url@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.4.tgz#3b0322c425e31dd275174d0d5db0e466f50810fb" + integrity sha512-cNj3RzK2pgQQyNp7dzq0dqpUpQ/wYtdDZM3DepPmFjCmYIfceuD9VIAcOdvrNetjIU65g1B4uwdP/Krf6AFdXg== dependencies: normalize-url "^6.0.1" postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.0.tgz#aed8b4580c9ad6e8eac034177291187ea16a059c" - integrity sha512-7O1FanKaJkpWFyCghFzIkLhehujV/frGkdofGLwhg5upbLyGsSfiTcZAdSzoPsSUgyPCkBkNMeWR8yVgPdQybg== +postcss-normalize-whitespace@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.3.tgz#fb6bcc9ff2f834448b802657c7acd0956f4591d1" + integrity sha512-333JWRnX655fSoUbufJ10HJop3c8mrpKkCCUnEmgz/Cb/QEtW+/TMZwDAUt4lnwqP6tCCk0x0b58jqvDgiQm/A== dependencies: postcss-value-parser "^4.2.0" @@ -8095,103 +8231,89 @@ postcss-normalize@^10.0.1: postcss-browser-comments "^4" sanitize.css "*" -postcss-opacity-percentage@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz#bd698bb3670a0a27f6d657cc16744b3ebf3b1145" - integrity sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w== - -postcss-ordered-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.0.tgz#04ef429e0991b0292bc918b135cd4c038f7b889f" - integrity sha512-wU4Z4D4uOIH+BUKkYid36gGDJNQtkVJT7Twv8qH6UyfttbbJWyw4/xIPuVEkkCtQLAJ0EdsNSh8dlvqkXb49TA== +postcss-ordered-values@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.4.tgz#f799dca87a7f17526d31a20085e61768d0b00534" + integrity sha512-taKtGDZtyYUMVYkg+MuJeBUiTF6cGHZmo/qcW7ibvW79UlyKuSHbo6dpCIiqI+j9oJsXWzP+ovIxoyLDOeQFdw== dependencies: - cssnano-utils "^3.1.0" + cssnano-utils "^3.0.1" postcss-value-parser "^4.2.0" -postcss-overflow-shorthand@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz#ebcfc0483a15bbf1b27fdd9b3c10125372f4cbc2" - integrity sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg== +postcss-overflow-shorthand@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.2.tgz#b4e9c89728cd1e4918173dfb95936b75f78d4148" + integrity sha512-odBMVt6PTX7jOE9UNvmnLrFzA9pXS44Jd5shFGGtSHY80QCuJF+14McSy0iavZggRZ9Oj//C9vOKQmexvyEJMg== postcss-page-break@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f" integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ== -postcss-place@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.4.tgz#eb026650b7f769ae57ca4f938c1addd6be2f62c9" - integrity sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg== +postcss-place@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.3.tgz#ca8040dfd937c7769a233a3bd6e66e139cf89e62" + integrity sha512-tDQ3m+GYoOar+KoQgj+pwPAvGHAp/Sby6vrFiyrELrMKQJ4AejL0NcS0mm296OKKYA2SRg9ism/hlT/OLhBrdQ== dependencies: postcss-value-parser "^4.2.0" postcss-preset-env@^7.0.1: - version "7.4.2" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.4.2.tgz#2ff3e4787bd9d89710659535855d6ce85ce6110b" - integrity sha512-AmOkb8AeNNQwE/z2fHl1iwOIt8J50V8WR0rmLagcgIDoqlJZWjV3NdtOPnLGco1oN8DZe+Ss5B9ULbBeS6HfeA== - dependencies: - "@csstools/postcss-color-function" "^1.0.2" - "@csstools/postcss-font-format-keywords" "^1.0.0" - "@csstools/postcss-hwb-function" "^1.0.0" - "@csstools/postcss-ic-unit" "^1.0.0" - "@csstools/postcss-is-pseudo-class" "^2.0.0" - "@csstools/postcss-normalize-display-values" "^1.0.0" - "@csstools/postcss-oklab-function" "^1.0.1" - "@csstools/postcss-progressive-custom-properties" "^1.2.0" + version "7.2.3" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.2.3.tgz#01b9b6eea0ff16c27a3d514f10105d56363428a6" + integrity sha512-Ok0DhLfwrcNGrBn8sNdy1uZqWRk/9FId0GiQ39W4ILop5GHtjJs8bu1MY9isPwHInpVEPWjb4CEcEaSbBLpfwA== + dependencies: autoprefixer "^10.4.2" - browserslist "^4.19.3" - css-blank-pseudo "^3.0.3" - css-has-pseudo "^3.0.4" - css-prefers-color-scheme "^6.0.3" - cssdb "^6.4.0" + browserslist "^4.19.1" + caniuse-lite "^1.0.30001299" + css-blank-pseudo "^3.0.2" + css-has-pseudo "^3.0.3" + css-prefers-color-scheme "^6.0.2" + cssdb "^5.0.0" postcss-attribute-case-insensitive "^5.0.0" - postcss-color-functional-notation "^4.2.2" - postcss-color-hex-alpha "^8.0.3" + postcss-color-functional-notation "^4.2.1" + postcss-color-hex-alpha "^8.0.2" postcss-color-rebeccapurple "^7.0.2" postcss-custom-media "^8.0.0" - postcss-custom-properties "^12.1.4" + postcss-custom-properties "^12.1.2" postcss-custom-selectors "^6.0.0" - postcss-dir-pseudo-class "^6.0.4" - postcss-double-position-gradients "^3.1.0" - postcss-env-function "^4.0.5" - postcss-focus-visible "^6.0.4" - postcss-focus-within "^5.0.4" + postcss-dir-pseudo-class "^6.0.3" + postcss-double-position-gradients "^3.0.4" + postcss-env-function "^4.0.4" + postcss-focus-visible "^6.0.3" + postcss-focus-within "^5.0.3" postcss-font-variant "^5.0.0" - postcss-gap-properties "^3.0.3" - postcss-image-set-function "^4.0.6" + postcss-gap-properties "^3.0.2" + postcss-image-set-function "^4.0.4" postcss-initial "^4.0.1" - postcss-lab-function "^4.1.1" - postcss-logical "^5.0.4" + postcss-lab-function "^4.0.3" + postcss-logical "^5.0.3" postcss-media-minmax "^5.0.0" postcss-nesting "^10.1.2" - postcss-opacity-percentage "^1.1.2" - postcss-overflow-shorthand "^3.0.3" + postcss-overflow-shorthand "^3.0.2" postcss-page-break "^3.0.4" - postcss-place "^7.0.4" - postcss-pseudo-class-any-link "^7.1.1" + postcss-place "^7.0.3" + postcss-pseudo-class-any-link "^7.0.2" postcss-replace-overflow-wrap "^4.0.0" postcss-selector-not "^5.0.0" - postcss-value-parser "^4.2.0" -postcss-pseudo-class-any-link@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz#534eb1dadd9945eb07830dbcc06fb4d5d865b8e0" - integrity sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg== +postcss-pseudo-class-any-link@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.0.2.tgz#6284c2f970715c78fe992d2fac1130e9991585c9" + integrity sha512-CG35J1COUH7OOBgpw5O+0koOLUd5N4vUGKUqSAuIe4GiuLHWU96Pqp+UPC8QITTd12zYAFx76pV7qWT/0Aj/TA== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.8" -postcss-reduce-initial@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz#fc31659ea6e85c492fb2a7b545370c215822c5d6" - integrity sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw== +postcss-reduce-initial@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.2.tgz#fa424ce8aa88a89bc0b6d0f94871b24abe94c048" + integrity sha512-v/kbAAQ+S1V5v9TJvbGkV98V2ERPdU6XvMcKMjqAlYiJ2NtsHGlKYLPjWWcXlaTKNxooId7BGxeraK8qXvzKtw== dependencies: browserslist "^4.16.6" caniuse-api "^3.0.0" -postcss-reduce-transforms@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" - integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== +postcss-reduce-transforms@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.3.tgz#df60fab34698a43073e8b87938c71df7a3b040ac" + integrity sha512-yDnTUab5i7auHiNwdcL1f+pBnqQFf+7eC4cbC7D8Lc1FkvNZhtpkdad+9U4wDdFb84haupMf0rA/Zc5LcTe/3A== dependencies: postcss-value-parser "^4.2.0" @@ -8215,22 +8337,22 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-svgo@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" - integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== +postcss-svgo@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.3.tgz#d945185756e5dfaae07f9edb0d3cae7ff79f9b30" + integrity sha512-41XZUA1wNDAZrQ3XgWREL/M2zSw8LJPvb5ZWivljBsUQAGoEKMYm6okHsTjJxKYI4M75RQEH4KYlEM52VwdXVA== dependencies: - postcss-value-parser "^4.2.0" + postcss-value-parser "^4.1.0" svgo "^2.7.0" -postcss-unique-selectors@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.0.tgz#70a945da1b0599d00f617222a44ba1d82a676694" - integrity sha512-LmUhgGobtpeVJJHuogzjLRwJlN7VH+BL5c9GKMVJSS/ejoyePZkXvNsYUtk//F6vKOGK86gfRS0xH7fXQSDtvA== +postcss-unique-selectors@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.3.tgz#07fd116a8fbd9202e7030f7c4952e7b52c26c63d" + integrity sha512-V5tX2hadSSn+miVCluuK1IDGy+7jAXSOfRZ2DQ+s/4uQZb/orDYBjH0CHgFrXsRw78p4QTuEFA9kI6C956UnHQ== dependencies: postcss-selector-parser "^6.0.5" -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -8243,14 +8365,14 @@ postcss@^7.0.35: picocolors "^0.2.1" source-map "^0.6.1" -postcss@^8.3.5, postcss@^8.4.4, postcss@^8.4.5, postcss@^8.4.6: - version "8.4.7" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.7.tgz#f99862069ec4541de386bf57f5660a6c7a0875a8" - integrity sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A== +postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.4: + version "8.4.5" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" + integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== dependencies: - nanoid "^3.3.1" + nanoid "^3.1.30" picocolors "^1.0.0" - source-map-js "^1.0.2" + source-map-js "^1.0.1" prelude-ls@^1.2.1: version "1.2.1" @@ -8275,19 +8397,19 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" -pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== +pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.6.tgz#1b784d2f53c68db31797b2348fa39b49e31846b7" + integrity sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g== dependencies: ansi-regex "^5.0.1" ansi-styles "^5.0.0" react-is "^17.0.1" -prismjs@~1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" - integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== +prismjs@~1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756" + integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg== process-nextick-args@~2.0.0: version "2.0.1" @@ -8348,10 +8470,10 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@6.9.7: - version "6.9.7" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" - integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== +qs@6.9.6: + version "6.9.6" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" + integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== query-string@^7.1.1: version "7.1.1" @@ -8402,12 +8524,12 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" - integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== +raw-body@2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" + integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== dependencies: - bytes "3.1.2" + bytes "3.1.1" http-errors "1.8.1" iconv-lite "0.4.24" unpipe "1.0.0" @@ -8424,7 +8546,7 @@ react-app-polyfill@^3.0.0: regenerator-runtime "^0.13.9" whatwg-fetch "^3.6.2" -react-beautiful-dnd@^13.1.0: +react-beautiful-dnd@^13.0.0: version "13.1.0" resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz#ec97c81093593526454b0de69852ae433783844d" integrity sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA== @@ -8483,23 +8605,14 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-dropzone@^11.5.3: - version "11.7.1" - resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.7.1.tgz#3851bb75b26af0bf1b17ce1449fd980e643b9356" - integrity sha512-zxCMwhfPy1olUEbw3FLNPLhAm/HnaYH5aELIEglRbqabizKAdHs0h+WuyOpmA+v1JXn0++fpQDdNfUagWt5hJQ== - dependencies: - attr-accept "^2.2.2" - file-selector "^0.4.0" - prop-types "^15.8.1" - -react-element-to-jsx-string@^14.3.4: - version "14.3.4" - resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz#709125bc72f06800b68f9f4db485f2c7d31218a8" - integrity sha512-t4ZwvV6vwNxzujDQ+37bspnLwA4JlgUPWhLjBJWsNIDceAf6ZKUTCjdm08cN6WeZ5pTMKiCJkmAYnpmR4Bm+dg== +react-dropzone@^11.2.0: + version "11.5.3" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.5.3.tgz#757d4980fcae839896a894e41d3e72df04981f86" + integrity sha512-68+T6sWW5L89qJnn3SD1aRazhuRBhTT9JOI1W8vI5YWsfegM4C7tlGbPH1AgEbmZY5s8E8L0QhX0e3VdAa0KWA== dependencies: - "@base2/pretty-print-object" "1.0.1" - is-plain-object "5.0.0" - react-is "17.0.2" + attr-accept "^2.2.1" + file-selector "^0.2.2" + prop-types "^15.7.2" react-error-overlay@^6.0.10: version "6.0.10" @@ -8507,18 +8620,18 @@ react-error-overlay@^6.0.10: integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== react-focus-lock@^2.6.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.8.1.tgz#a28f06a4ef5eab7d4ef0d859512772ec1331d529" - integrity sha512-4kb9I7JIiBm0EJ+CsIBQ+T1t5qtmwPRbFGYFQ0t2q2qIpbFbYTHDjnjJVFB7oMBtXityEOQehblJPjqSIf3Amg== + version "2.7.1" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.7.1.tgz#a9fbb3fa4efaee32162406e5eb96ae658964193b" + integrity sha512-ImSeVmcrLKNMqzUsIdqOkXwTVltj79OPu43oT8tVun7eIckA4VdM7UmYUFo3H/UC2nRVgagMZGFnAOQEDiDYcA== dependencies: "@babel/runtime" "^7.0.0" - focus-lock "^0.10.2" + focus-lock "^0.10.1" prop-types "^15.6.2" react-clientside-effect "^1.2.5" use-callback-ref "^1.2.5" use-sidecar "^1.0.5" -react-focus-on@^3.5.4: +react-focus-on@^3.5.0: version "3.5.4" resolved "https://registry.yarnpkg.com/react-focus-on/-/react-focus-on-3.5.4.tgz#be45a9d0495f3bb6f5249704c85362df94980ecf" integrity sha512-HnU0YGKhNSUsC4k6K8L+2wk8mC/qdg+CsS7A1bWLMgK7UuBphdECs2esnS6cLmBoVNjsFnCm/vMypeezKOdK3A== @@ -8531,27 +8644,32 @@ react-focus-on@^3.5.4: use-callback-ref "^1.2.5" use-sidecar "^1.0.5" -react-input-autosize@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" - integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== +react-input-autosize@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" + integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== dependencies: prop-types "^15.5.8" -react-is@17.0.2, react-is@^17.0.1, react-is@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-query@^3.34.16: - version "3.34.16" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.34.16.tgz#279ea180bcaeaec49c7864b29d1711ee9f152594" - integrity sha512-7FvBvjgEM4YQ8nPfmAr+lJfbW95uyW/TVjFoi2GwCkF33/S8ajx45tuPHPFGWs4qYwPy1mzwxD4IQfpUDrefNQ== +react-is@^17.0.1, react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@~16.3.0: + version "16.3.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.3.2.tgz#f4d3d0e2f5fbb6ac46450641eb2e25bf05d36b22" + integrity sha512-ybEM7YOr4yBgFd6w8dJqwxegqZGJNBZl6U27HnGKuTZmDvVrD5quWOK/wAnMywiZzW+Qsk+l4X2c70+thp/A8Q== + +react-query@^3.34.12: + version "3.34.12" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.34.12.tgz#dcaaf7b629f0868aae8afef9fb7692f6ea7643bf" + integrity sha512-flDdudQVH4CqE+kNYYYyo4g2Yjek3H/36G3b9bK5oe26jD5gFnx+PPwnq0gayq5z2dcSfr2z4+drvuyeZ3A5QQ== dependencies: "@babel/runtime" "^7.5.5" broadcast-channel "^3.4.1" @@ -8583,9 +8701,9 @@ react-remove-scroll-bar@^2.1.0: tslib "^1.0.0" react-remove-scroll@^2.4.1: - version "2.4.4" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.4.tgz#2dfff377cf17efc00de39dad51c143fc7a1b9e3e" - integrity sha512-EyC5ohYhaeKbThMSQxuN2i+QC5HqV3AJvNZKEdiATITexu0gHm00+5ko0ltNS1ajYJVeDgVG2baRSCei0AUWlQ== + version "2.4.3" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.3.tgz#83d19b02503b04bd8141ed6e0b9e6691a2e935a6" + integrity sha512-lGWYXfV6jykJwbFpsuPdexKKzp96f3RbvGapDSIdcyGvHb7/eqyn46C7/6h+rUzYar1j5mdU+XECITHXCKBk9Q== dependencies: react-remove-scroll-bar "^2.1.0" react-style-singleton "^2.1.0" @@ -8594,21 +8712,21 @@ react-remove-scroll@^2.4.1: use-sidecar "^1.0.1" react-router-dom@6: - version "6.2.2" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.2.tgz#f1a2c88365593c76b9612ae80154a13fcb72e442" - integrity sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ== + version "6.2.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.1.tgz#32ec81829152fbb8a7b045bf593a22eadf019bec" + integrity sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA== dependencies: history "^5.2.0" - react-router "6.2.2" + react-router "6.2.1" -react-router@6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.2.tgz#495e683a0c04461eeb3d705fe445d6cf42f0c249" - integrity sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ== +react-router@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.1.tgz#be2a97a6006ce1d9123c28934e604faef51448a3" + integrity sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg== dependencies: history "^5.2.0" -react-scripts@5.0.0: +react-scripts@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.0.tgz#6547a6d7f8b64364ef95273767466cc577cb4b60" integrity sha512-3i0L2CyIlROz7mxETEdfif6Sfhh9Lfpzi10CtcGs1emDQStmZfWjJbAIMtRD0opVUjQuFWqHZyRZ9PPzKCFxWg== @@ -8672,12 +8790,12 @@ react-style-singleton@^2.1.0, react-style-singleton@^2.1.1: invariant "^2.2.4" tslib "^1.0.0" -react-virtualized-auto-sizer@^1.0.6: +react-virtualized-auto-sizer@^1.0.2: version "1.0.6" resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca" integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ== -react-window@^1.8.6: +react-window@^1.8.5: version "1.8.6" resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112" integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg== @@ -8745,18 +8863,18 @@ redux@^4.0.0, redux@^4.0.4: "@babel/runtime" "^7.9.2" refractor@^3.5.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" - integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + version "3.5.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.5.0.tgz#334586f352dda4beaf354099b48c2d18e0819aec" + integrity sha512-QwPJd3ferTZ4cSPPjdP5bsYHMytwWYnAN5EEnLtGvkqp/FCCnGsBgxrm9EuIDnjUC3Uc/kETtvVi7fSIVC74Dg== dependencies: hastscript "^6.0.0" parse-entities "^2.0.0" - prismjs "~1.27.0" + prismjs "~1.25.0" -regenerate-unicode-properties@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" - integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== +regenerate-unicode-properties@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" + integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== dependencies: regenerate "^1.4.2" @@ -8795,27 +8913,27 @@ regexpp@^3.2.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -regexpu-core@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" - integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== +regexpu-core@^4.7.1: + version "4.8.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" + integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== dependencies: regenerate "^1.4.2" - regenerate-unicode-properties "^10.0.1" - regjsgen "^0.6.0" - regjsparser "^0.8.2" + regenerate-unicode-properties "^9.0.0" + regjsgen "^0.5.2" + regjsparser "^0.7.0" unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.0.0" -regjsgen@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" - integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== +regjsgen@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== -regjsparser@^0.8.2: - version "0.8.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" - integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== +regjsparser@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" + integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== dependencies: jsesc "~0.5.0" @@ -8960,7 +9078,7 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0: +resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.21.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -9007,7 +9125,39 @@ robust-predicates@^3.0.0: resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a" integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g== -rollup-plugin-terser@^7.0.0: +rollup-plugin-copy@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz#f1228a3ffb66ffad8606e2f3fb7ff23141ed3286" + integrity sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ== + dependencies: + "@types/fs-extra" "^8.0.1" + colorette "^1.1.0" + fs-extra "^8.1.0" + globby "10.0.1" + is-plain-object "^3.0.0" + +rollup-plugin-import-css@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-import-css/-/rollup-plugin-import-css-3.0.2.tgz#7b718aba264b08cff1f171a83fbf0a1b36ad47ca" + integrity sha512-4Y/U5EMQHomMlYSF0OBOo/XJSgfou+iHMfBOqneaX5Cp5BCyQn1YrUtXC6KYEPHPxTadC+oXhrTCr9yzRN2DyA== + dependencies: + "@rollup/pluginutils" "^4.1.1" + +rollup-plugin-svg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-svg/-/rollup-plugin-svg-2.0.0.tgz#ce11b55e915d5b2190328c4e6632bd6b4fe12ee9" + integrity sha512-DmE7dSQHo1SC5L2uH2qul3Mjyd5oV6U1aVVkyvTLX/mUsRink7f1b1zaIm+32GEBA6EHu8H/JJi3DdWqM53ySQ== + dependencies: + rollup-pluginutils "^1.3.1" + +rollup-plugin-svgo@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-svgo/-/rollup-plugin-svgo-1.1.0.tgz#092faa52753aa0ede52f2405bc58286f945614ae" + integrity sha512-wcOKsBXBErjmCQJZmmnLlAjcVQAUApfzsp/k8fx7u/5vKm0sUFk+IiBT2ylGUX6jUap3PNASAhiew88TJrH6Qg== + dependencies: + svgo "1.3.0" + +rollup-plugin-terser@^7.0.0, rollup-plugin-terser@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== @@ -9017,10 +9167,25 @@ rollup-plugin-terser@^7.0.0: serialize-javascript "^4.0.0" terser "^5.0.0" +rollup-pluginutils@^1.3.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" + integrity sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg= + dependencies: + estree-walker "^0.2.1" + minimatch "^3.0.2" + rollup@^2.43.1: - version "2.69.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.69.0.tgz#82aa86682a45e9760146b736c1643bf435506156" - integrity sha512-kjER91tHyek8gAkuz7+558vSnTQ+pITEok1P0aNOS45ZXyngaqPsXJmSel4QPQnJo7EJMjXUU1/GErWkWiKORg== + version "2.66.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.66.1.tgz#366b0404de353c4331d538c3ad2963934fcb4937" + integrity sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w== + optionalDependencies: + fsevents "~2.3.2" + +rollup@^2.68.0: + version "2.68.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.68.0.tgz#6ccabfd649447f8f21d62bf41662e5caece3bd66" + integrity sha512-XrMKOYK7oQcTio4wyTz466mucnd8LzkiZLozZ4Rz0zQD+HeX4nUK4B8GrTX/2EvN2/vBF/i2WnaXboPxo0JylA== optionalDependencies: fsevents "~2.3.2" @@ -9069,9 +9234,9 @@ sanitize.css@*: integrity sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA== sass-loader@^12.3.0: - version "12.6.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.6.0.tgz#5148362c8e2cdd4b950f3c63ac5d16dbfed37bcb" - integrity sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA== + version "12.4.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.4.0.tgz#260b0d51a8a373bb8e88efc11f6ba5583fea0bcf" + integrity sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg== dependencies: klona "^2.0.4" neo-async "^2.6.2" @@ -9265,9 +9430,9 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== sisteransi@^1.0.5: version "1.0.5" @@ -9298,7 +9463,7 @@ source-list-map@^2.0.0, source-list-map@^2.0.1: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-js@^1.0.1, source-map-js@^1.0.2: +source-map-js@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -9328,12 +9493,17 @@ source-map-support@^0.5.6, source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.5.0, source-map@^0.5.7: +source-map@^0.5.0, source-map@^0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -9350,7 +9520,7 @@ source-map@^0.8.0-beta.0: dependencies: whatwg-url "^7.0.0" -sourcemap-codec@^1.4.8: +sourcemap-codec@^1.4.4: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== @@ -9406,9 +9576,9 @@ stack-utils@^2.0.3: escape-string-regexp "^2.0.0" stackframe@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.1.tgz#1033a3473ee67f08e2f2fc8eba6aef4f845124e1" - integrity sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" + integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== state-toggle@^1.0.0: version "1.0.3" @@ -9587,10 +9757,10 @@ style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -stylehacks@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.0.tgz#a40066490ca0caca04e96c6b02153ddc39913520" - integrity sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q== +stylehacks@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.2.tgz#fa10e5181c6e8dc0bddb4a3fb372e9ac42bba2ad" + integrity sha512-114zeJdOpTrbQYRD4OU5UWJ99LKUaqCPJTU1HQ/n3q3BwmllFN8kHENaLnOeqVq6AhXrWfxHNZTl33iJ4oy3cQ== dependencies: browserslist "^4.16.6" postcss-selector-parser "^6.0.4" @@ -9639,6 +9809,25 @@ svg-parser@^2.0.2: resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== +svgo@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" + integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.33" + csso "^3.5.1" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + svgo@^1.2.2: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" @@ -9682,9 +9871,9 @@ tabbable@^3.0.0: integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ== tailwindcss@^3.0.2: - version "3.0.23" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10" - integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA== + version "3.0.18" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.18.tgz#ea4825e6496d77dc21877b6b61c7cc56cda3add5" + integrity sha512-ihPTpEyA5ANgZbwKlgrbfnzOp9R5vDHFWmqxB1PT8NwOGCOFVVMl+Ps1cQQ369acaqqf1BEF77roCwK0lvNmTw== dependencies: arg "^5.0.1" chalk "^4.1.2" @@ -9699,14 +9888,13 @@ tailwindcss@^3.0.2: is-glob "^4.0.3" normalize-path "^3.0.0" object-hash "^2.2.0" - postcss "^8.4.6" postcss-js "^4.0.0" postcss-load-config "^3.1.0" postcss-nested "5.0.6" postcss-selector-parser "^6.0.9" postcss-value-parser "^4.2.0" quick-lru "^5.1.1" - resolve "^1.22.0" + resolve "^1.21.0" tapable@^1.0.0: version "1.1.3" @@ -9742,22 +9930,21 @@ terminal-link@^2.0.0: supports-hyperlinks "^2.0.0" terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5: - version "5.3.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" - integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== + version "5.3.0" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz#21641326486ecf91d8054161c816e464435bae9f" + integrity sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ== dependencies: - jest-worker "^27.4.5" + jest-worker "^27.4.1" schema-utils "^3.1.1" serialize-javascript "^6.0.0" source-map "^0.6.1" terser "^5.7.2" terser@^5.0.0, terser@^5.10.0, terser@^5.7.2: - version "5.12.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.12.0.tgz#728c6bff05f7d1dcb687d8eace0644802a9dae8a" - integrity sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A== + version "5.10.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" + integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== dependencies: - acorn "^8.5.0" commander "^2.20.0" source-map "~0.7.2" source-map-support "~0.5.20" @@ -9884,9 +10071,9 @@ tryer@^1.0.1: integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== tsconfig-paths@^3.12.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7" - integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw== + version "3.12.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" + integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.1" @@ -9964,10 +10151,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" - integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== +typescript@^4.4.2: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== unbox-primitive@^1.0.1: version "1.0.1" @@ -10069,9 +10256,9 @@ unist-util-stringify-position@^2.0.0: "@types/unist" "^2.0.2" unist-util-stringify-position@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" - integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.0.tgz#d517d2883d74d0daa0b565adc3d10a02b4a8cde9" + integrity sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA== dependencies: "@types/unist" "^2.0.0" @@ -10106,7 +10293,7 @@ unist-util-visit@^2.0.0, unist-util-visit@^2.0.3: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" -universalify@^0.1.2: +universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== @@ -10146,10 +10333,10 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse@^1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== +url-parse@^1.5.3: + version "1.5.4" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.4.tgz#e4f645a7e2a0852cc8a66b14b292a3e9a11a97fd" + integrity sha512-ITeAByWWoqutFClc/lRZnFplgXgEZr3WJ6XngMM/N9DMIm4K8zXPCZ1Jdu0rERwO84w1WC5wkle2ubwTA4NTBg== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" @@ -10234,9 +10421,9 @@ vfile-location@^3.0.0, vfile-location@^3.2.0: integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== vfile-message@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.2.tgz#a2908f64d9e557315ec9d7ea3a910f658ac05f7d" - integrity sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.0.tgz#5437035aa43185ff4b9210d32fada6c640e59143" + integrity sha512-4QJbBk+DkPEhBXq3f260xSaWtjE4gPKOfulzfMFF8ZNwaPZieWsg3iVlcmF04+eebzpcpeXOOFMfrYzJHVYg+g== dependencies: "@types/unist" "^2.0.0" unist-util-stringify-position "^3.0.0" @@ -10307,11 +10494,6 @@ web-namespaces@^1.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== -web-vitals@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.4.tgz#76563175a475a5e835264d373704f9dde718290c" - integrity sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg== - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -10332,31 +10514,30 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== -webpack-dev-middleware@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" - integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== +webpack-dev-middleware@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.0.tgz#8fc02dba6e72e1d373eca361623d84610f27be7c" + integrity sha512-MouJz+rXAm9B1OTOYaJnn6rtD/lWZPy2ufQCH3BPs8Rloh/Du6Jze4p7AeLYHkVi0giJnYLaSGDC7S+GM9arhg== dependencies: colorette "^2.0.10" - memfs "^3.4.1" + memfs "^3.2.2" mime-types "^2.1.31" range-parser "^1.2.1" schema-utils "^4.0.0" webpack-dev-server@^4.6.0: - version "4.7.4" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" - integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A== + version "4.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz#4e995b141ff51fa499906eebc7906f6925d0beaa" + integrity sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" "@types/serve-index" "^1.9.1" "@types/sockjs" "^0.3.33" "@types/ws" "^8.2.2" ansi-html-community "^0.0.8" bonjour "^3.5.0" - chokidar "^3.5.3" + chokidar "^3.5.2" colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^1.6.0" @@ -10376,8 +10557,8 @@ webpack-dev-server@^4.6.0: sockjs "^0.3.21" spdy "^4.0.2" strip-ansi "^7.0.0" - webpack-dev-middleware "^5.3.1" - ws "^8.4.2" + webpack-dev-middleware "^5.3.0" + ws "^8.1.0" webpack-manifest-plugin@^4.0.2: version "4.1.1" @@ -10409,12 +10590,12 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.64.4: - version "5.70.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d" - integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw== + version "5.67.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.67.0.tgz#cb43ca2aad5f7cc81c4cd36b626e6b819805dbfd" + integrity sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw== dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" + "@types/eslint-scope" "^3.7.0" + "@types/estree" "^0.0.50" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" @@ -10422,7 +10603,7 @@ webpack@^5.64.4: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.9.2" + enhanced-resolve "^5.8.3" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" @@ -10525,25 +10706,25 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -workbox-background-sync@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.5.1.tgz#df79c6a4a22945d8a44493a4947a6ed0f720ef86" - integrity sha512-T5a35fagLXQvV8Dr4+bDU+XYsP90jJ3eBLjZMKuCNELMQZNj+VekCODz1QK44jgoBeQk+vp94pkZV6G+e41pgg== +workbox-background-sync@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.4.2.tgz#bb31b95928d376abcb9bde0de3a0cef9bae46cf7" + integrity sha512-P7c8uG5X2k+DMICH9xeSA9eUlCOjHHYoB42Rq+RtUpuwBxUOflAXR1zdsMWj81LopE4gjKXlTw7BFd1BDAHo7g== dependencies: idb "^6.1.4" - workbox-core "6.5.1" + workbox-core "6.4.2" -workbox-broadcast-update@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.5.1.tgz#9aecb116979b0709480b84cfd1beca7a901d01d4" - integrity sha512-mb/oyblyEpDbw167cCTyHnC3RqCnCQHtFYuYZd+QTpuExxM60qZuBH1AuQCgvLtDcztBKdEYK2VFD9SZYgRbaQ== +workbox-broadcast-update@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.4.2.tgz#5094c4767dfb590532ac03ee07e9e82b2ac206bc" + integrity sha512-qnBwQyE0+PWFFc/n4ISXINE49m44gbEreJUYt2ldGH3+CNrLmJ1egJOOyUqqu9R4Eb7QrXcmB34ClXG7S37LbA== dependencies: - workbox-core "6.5.1" + workbox-core "6.4.2" -workbox-build@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.5.1.tgz#6b5e8f090bb608267868540d3072b44b8531b3bc" - integrity sha512-coDUDzHvFZ1ADOl3wKCsCSyOBvkPKlPgcQDb6LMMShN1zgF31Mev/1HzN3+9T2cjjWAgFwZKkuRyExqc1v21Zw== +workbox-build@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.4.2.tgz#47f9baa946c3491533cd5ccb1f194a7160e8a6e3" + integrity sha512-WMdYLhDIsuzViOTXDH+tJ1GijkFp5khSYolnxR/11zmfhNDtuo7jof72xPGFy+KRpsz6tug39RhivCj77qqO0w== dependencies: "@apideck/better-ajv-errors" "^0.3.1" "@babel/core" "^7.11.1" @@ -10563,136 +10744,138 @@ workbox-build@6.5.1: rollup "^2.43.1" rollup-plugin-terser "^7.0.0" source-map "^0.8.0-beta.0" + source-map-url "^0.4.0" stringify-object "^3.3.0" strip-comments "^2.0.1" tempy "^0.6.0" upath "^1.2.0" - workbox-background-sync "6.5.1" - workbox-broadcast-update "6.5.1" - workbox-cacheable-response "6.5.1" - workbox-core "6.5.1" - workbox-expiration "6.5.1" - workbox-google-analytics "6.5.1" - workbox-navigation-preload "6.5.1" - workbox-precaching "6.5.1" - workbox-range-requests "6.5.1" - workbox-recipes "6.5.1" - workbox-routing "6.5.1" - workbox-strategies "6.5.1" - workbox-streams "6.5.1" - workbox-sw "6.5.1" - workbox-window "6.5.1" - -workbox-cacheable-response@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.5.1.tgz#f71d0a75b3d6846e39594955e99ac42fd26f8693" - integrity sha512-3TdtH/luDiytmM+Cn72HCBLZXmbeRNJqZx2yaVOfUZhj0IVwZqQXhNarlGE9/k6U5Jelb+TtpH2mLVhnzfiSMg== - dependencies: - workbox-core "6.5.1" - -workbox-core@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.5.1.tgz#0dba3bccf883a46dfa61cc412eaa3cb09bb549e6" - integrity sha512-qObXZ39aFJ2N8X7IUbGrJHKWguliCuU1jOXM/I4MTT84u9BiKD2rHMkIzgeRP1Ixu9+cXU4/XHJq3Cy0Qqc5hw== - -workbox-expiration@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.5.1.tgz#9f105fcf3362852754884ad153888070ce98b692" - integrity sha512-iY/cTADAQATMmPkUBRmQdacqq0TJd2wMHimBQz+tRnPGHSMH+/BoLPABPnu7O7rT/g/s59CUYYRGxe3mEgoJCA== + workbox-background-sync "6.4.2" + workbox-broadcast-update "6.4.2" + workbox-cacheable-response "6.4.2" + workbox-core "6.4.2" + workbox-expiration "6.4.2" + workbox-google-analytics "6.4.2" + workbox-navigation-preload "6.4.2" + workbox-precaching "6.4.2" + workbox-range-requests "6.4.2" + workbox-recipes "6.4.2" + workbox-routing "6.4.2" + workbox-strategies "6.4.2" + workbox-streams "6.4.2" + workbox-sw "6.4.2" + workbox-window "6.4.2" + +workbox-cacheable-response@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.4.2.tgz#ebcabb3667019da232e986a9927af97871e37ccb" + integrity sha512-9FE1W/cKffk1AJzImxgEN0ceWpyz1tqNjZVtA3/LAvYL3AC5SbIkhc7ZCO82WmO9IjTfu8Vut2X/C7ViMSF7TA== + dependencies: + workbox-core "6.4.2" + +workbox-core@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.4.2.tgz#f99fd36a211cc01dce90aa7d5f2c255e8fe9d6bc" + integrity sha512-1U6cdEYPcajRXiboSlpJx6U7TvhIKbxRRerfepAJu2hniKwJ3DHILjpU/zx3yvzSBCWcNJDoFalf7Vgd7ey/rw== + +workbox-expiration@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.4.2.tgz#61613459fd6ddd1362730767618d444c6b9c9139" + integrity sha512-0hbpBj0tDnW+DZOUmwZqntB/8xrXOgO34i7s00Si/VlFJvvpRKg1leXdHHU8ykoSBd6+F2KDcMP3swoCi5guLw== dependencies: idb "^6.1.4" - workbox-core "6.5.1" + workbox-core "6.4.2" -workbox-google-analytics@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.5.1.tgz#685224d439c1e7a943f8241d65e2a34ee95a4ba0" - integrity sha512-qZU46/h4dbionYT6Yk6iBkUwpiEzAfnO1W7KkI+AMmY7G9/gA03dQQ7rpTw8F4vWrG7ahTUGWDFv6fERtaw1BQ== +workbox-google-analytics@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.4.2.tgz#eea7d511b3078665a726dc2ee9f11c6b7a897530" + integrity sha512-u+gxs3jXovPb1oul4CTBOb+T9fS1oZG+ZE6AzS7l40vnyfJV79DaLBvlpEZfXGv3CjMdV1sT/ltdOrKzo7HcGw== dependencies: - workbox-background-sync "6.5.1" - workbox-core "6.5.1" - workbox-routing "6.5.1" - workbox-strategies "6.5.1" + workbox-background-sync "6.4.2" + workbox-core "6.4.2" + workbox-routing "6.4.2" + workbox-strategies "6.4.2" -workbox-navigation-preload@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.5.1.tgz#a244e3bdf99ce86da7210315ca1ba5aef3710825" - integrity sha512-aKrgAbn2IMgzTowTi/ZyKdQUcES2m++9aGtpxqsX7Gn9ovCY8zcssaMEAMMwrIeveij5HiWNBrmj6MWDHi+0rg== +workbox-navigation-preload@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.4.2.tgz#35cd4ba416a530796af135410ca07db5bee11668" + integrity sha512-viyejlCtlKsbJCBHwhSBbWc57MwPXvUrc8P7d+87AxBGPU+JuWkT6nvBANgVgFz6FUhCvRC8aYt+B1helo166g== dependencies: - workbox-core "6.5.1" + workbox-core "6.4.2" -workbox-precaching@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.5.1.tgz#177b6424f1e71e601b9c3d6864decad2655f9ff9" - integrity sha512-EzlPBxvmjGfE56YZzsT/vpVkpLG1XJhoplgXa5RPyVWLUL1LbwEAxhkrENElSS/R9tgiTw80IFwysidfUqLihg== +workbox-precaching@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.4.2.tgz#8d87c05d54f32ac140f549faebf3b4d42d63621e" + integrity sha512-CZ6uwFN/2wb4noHVlALL7UqPFbLfez/9S2GAzGAb0Sk876ul9ukRKPJJ6gtsxfE2HSTwqwuyNVa6xWyeyJ1XSA== dependencies: - workbox-core "6.5.1" - workbox-routing "6.5.1" - workbox-strategies "6.5.1" + workbox-core "6.4.2" + workbox-routing "6.4.2" + workbox-strategies "6.4.2" -workbox-range-requests@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.5.1.tgz#f40f84aa8765940543eba16131d02f12b38e2fdc" - integrity sha512-57Da/qRbd9v33YlHX0rlSUVFmE4THCjKqwkmfhY3tNLnSKN2L5YBS3qhWeDO0IrMNgUj+rGve2moKYXeUqQt4A== +workbox-range-requests@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.4.2.tgz#050f0dfbb61cd1231e609ed91298b6c2442ae41b" + integrity sha512-SowF3z69hr3Po/w7+xarWfzxJX/3Fo0uSG72Zg4g5FWWnHpq2zPvgbWerBZIa81zpJVUdYpMa3akJJsv+LaO1Q== dependencies: - workbox-core "6.5.1" + workbox-core "6.4.2" -workbox-recipes@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.5.1.tgz#d2fb21743677cc3ca9e1fc9e3b68f0d1587df205" - integrity sha512-DGsyKygHggcGPQpWafC/Nmbm1Ny3sB2vE9r//3UbeidXiQ+pLF14KEG1/0NNGRaY+lfOXOagq6d1H7SC8KA+rA== +workbox-recipes@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.4.2.tgz#68de41fa3a77b444b0f93c9c01a76ba1d41fd2bf" + integrity sha512-/oVxlZFpAjFVbY+3PoGEXe8qyvtmqMrTdWhbOfbwokNFtUZ/JCtanDKgwDv9x3AebqGAoJRvQNSru0F4nG+gWA== dependencies: - workbox-cacheable-response "6.5.1" - workbox-core "6.5.1" - workbox-expiration "6.5.1" - workbox-precaching "6.5.1" - workbox-routing "6.5.1" - workbox-strategies "6.5.1" + workbox-cacheable-response "6.4.2" + workbox-core "6.4.2" + workbox-expiration "6.4.2" + workbox-precaching "6.4.2" + workbox-routing "6.4.2" + workbox-strategies "6.4.2" -workbox-routing@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.5.1.tgz#5488795ae850fe3ae435241143b54ff25ab0db70" - integrity sha512-yAAncdTwanvlR8KPjubyvFKeAok8ZcIws6UKxvIAg0I+wsf7UYi93DXNuZr6RBSQrByrN6HkCyjuhmk8P63+PA== +workbox-routing@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.4.2.tgz#65b1c61e8ca79bb9152f93263c26b1f248d09dcc" + integrity sha512-0ss/n9PAcHjTy4Ad7l2puuod4WtsnRYu9BrmHcu6Dk4PgWeJo1t5VnGufPxNtcuyPGQ3OdnMdlmhMJ57sSrrSw== dependencies: - workbox-core "6.5.1" + workbox-core "6.4.2" -workbox-strategies@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.5.1.tgz#51cabbddad5a1956eb9d51cf6ce01ab0a6372756" - integrity sha512-JNaTXPy8wXzKkr+6za7/eJX9opoZk7UgY261I2kPxl80XQD8lMjz0vo9EOcBwvD72v3ZhGJbW84ZaDwFEhFvWA== +workbox-strategies@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.4.2.tgz#50c02bf2d116918e1a8052df5f2c1e4103c62d5d" + integrity sha512-YXh9E9dZGEO1EiPC3jPe2CbztO5WT8Ruj8wiYZM56XqEJp5YlGTtqRjghV+JovWOqkWdR+amJpV31KPWQUvn1Q== dependencies: - workbox-core "6.5.1" + workbox-core "6.4.2" -workbox-streams@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.5.1.tgz#12036817385fa4449a86a3ef77fce1cb00ecad9f" - integrity sha512-7jaTWm6HRGJ/ewECnhb+UgjTT50R42E0/uNCC4eTKQwnLO/NzNGjoXTdQgFjo4zteR+L/K6AtFAiYKH3ZJbAYw== +workbox-streams@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.4.2.tgz#3bc615cccebfd62dedf28315afb7d9ee177912a5" + integrity sha512-ROEGlZHGVEgpa5bOZefiJEVsi5PsFjJG9Xd+wnDbApsCO9xq9rYFopF+IRq9tChyYzhBnyk2hJxbQVWphz3sog== dependencies: - workbox-core "6.5.1" - workbox-routing "6.5.1" + workbox-core "6.4.2" + workbox-routing "6.4.2" -workbox-sw@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.5.1.tgz#f9256b40f0a7e94656ccd06f127ba19a92cd23c5" - integrity sha512-hVrQa19yo9wzN1fQQ/h2JlkzFpkuH2qzYT2/rk7CLaWt6tLnTJVFCNHlGRRPhytZSf++LoIy7zThT714sowT/Q== +workbox-sw@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.4.2.tgz#9a6db5f74580915dc2f0dbd47d2ffe057c94a795" + integrity sha512-A2qdu9TLktfIM5NE/8+yYwfWu+JgDaCkbo5ikrky2c7r9v2X6DcJ+zSLphNHHLwM/0eVk5XVf1mC5HGhYpMhhg== workbox-webpack-plugin@^6.4.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.1.tgz#da88b4b6d8eff855958f0e7ebb7aa3eea50a8282" - integrity sha512-SHtlQBpKruI16CAYhICDMkgjXE2fH5Yp+D+1UmBfRVhByZYzusVOykvnPm8ObJb9d/tXgn9yoppoxafFS7D4vQ== + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-6.4.2.tgz#aad9f11b028786d5b781420e68f4e8f570ea9936" + integrity sha512-CiEwM6kaJRkx1cP5xHksn13abTzUqMHiMMlp5Eh/v4wRcedgDTyv6Uo8+Hg9MurRbHDosO5suaPyF9uwVr4/CQ== dependencies: fast-json-stable-stringify "^2.1.0" pretty-bytes "^5.4.1" + source-map-url "^0.4.0" upath "^1.2.0" webpack-sources "^1.4.3" - workbox-build "6.5.1" + workbox-build "6.4.2" -workbox-window@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.5.1.tgz#7b5ca29467b1da45dc9e2b5a1b89159d3eb9957a" - integrity sha512-oRlun9u7b7YEjo2fIDBqJkU2hXtrEljXcOytRhfeQRbqXxjUOpFgXSGRSAkmDx1MlKUNOSbr+zfi8h5n7In3yA== +workbox-window@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.4.2.tgz#5319a3e343fa1e4bd15a1f53a07b58999d064c8a" + integrity sha512-KVyRKmrJg7iB+uym/B/CnEUEFG9CvnTU1Bq5xpXHbtgD9l+ShDekSl1wYpqw/O0JfeeQVOFb8CiNfvnwWwqnWQ== dependencies: "@types/trusted-types" "^2.0.2" - workbox-core "6.5.1" + workbox-core "6.4.2" wrap-ansi@^7.0.0: version "7.0.0" @@ -10719,14 +10902,14 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.4.6: - version "7.5.7" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" - integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + version "7.5.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== -ws@^8.4.2: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== +ws@^8.1.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" + integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== xml-name-validator@^3.0.0: version "3.0.0" @@ -10764,9 +10947,9 @@ yargs-parser@^20.2.2: integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== yargs-parser@^21.0.0: - version "21.0.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" - integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== + version "21.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55" + integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== yargs@^16.2.0: version "16.2.0" @@ -10781,7 +10964,7 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.3.1: +yargs@^17.3.0: version "17.3.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== @@ -10799,10 +10982,10 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod@^3.13.4: - version "3.13.4" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.13.4.tgz#5d6fe03ef4824a637d7ef50b5441cf6ab3acede0" - integrity sha512-LZRucWt4j/ru5azOkJxCfpR87IyFDn8h2UODdqvXzZLb3K7bb9chUrUIGTy3BPsr8XnbQYfQ5Md5Hu2OYIo1mg== +zod@^3.11.6: + version "3.11.6" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.11.6.tgz#e43a5e0c213ae2e02aefe7cb2b1a6fa3d7f1f483" + integrity sha512-daZ80A81I3/9lIydI44motWe6n59kRBfNzTuS2bfzVh1nAXi667TOTWWtatxyG+fwgNUiagSj/CWZwRRbevJIg== zwitch@^1.0.0: version "1.0.5"