fix: Bump decommissioned Snowflake Python UDF runtime from 3.9 to 3.10 (#6606) - #6608
Conversation
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #6608 +/- ##
==========================================
+ Coverage 45.64% 45.86% +0.22%
==========================================
Files 412 412
Lines 48761 48763 +2
Branches 6913 6913
==========================================
+ Hits 22256 22367 +111
+ Misses 24957 24849 -108
+ Partials 1548 1547 -1
... and 2 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
|
@zerafachris is it possible to make it user configurable ? |
Addresses maintainer feedback from @ntkathole on feast-dev#6608 ("is it possible to make it user configurable?") following the RUNTIME_VERSION 3.9 -> 3.10 bump for decommissioned Snowflake Python UDF runtimes (feast-dev#6606). Adds `python_udf_runtime_version` (default "3.10") to SnowflakeComputeEngineConfig, validated as a Python version string, and plumbs it through SnowflakeComputeEngine.update() via a new RUNTIME_VERSION_HOLDER placeholder in snowflake_python_udfs_creation.sql, following the same substitution pattern already used for STAGE_HOLDER and PROJECT_NAME. This way, the next time Snowflake decommissions a Python runtime, users can override the config instead of waiting on a Feast release with another hardcoded bump. Also updates snowflake_udfs.py with a note clarifying its RUNTIME_VERSION docstrings are static reference documentation of the default (not the templated value actually deployed), documents the new field in docs/reference/compute-engine/snowflake.md, and adds/updates tests covering the config default, custom override, validation, and the rendered SQL template. Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io>
|
@ntkathole Good call — done. Pushed a follow-up commit (c5ae39b) that makes the Python UDF runtime version user-configurable instead of hardcoded. Added a new field batch_engine:
type: snowflake.engine
...
python_udf_runtime_version: "3.10" # optional, defaults to "3.10"
So the next time Snowflake decommissions a runtime, it's a one-line config change (e.g. |
feast-dev#6606) Snowflake decommissioned the Python 3.9 UDF runtime, so any Snowflake offline store `feast apply` that deploys the Feast materialization UDFs now fails with "Python runtime version 3.9 is decommissioned". The RUNTIME_VERSION = '3.9' value was hardcoded in the executed UDF creation SQL template (snowflake_python_udfs_creation.sql) and mirrored in the reference docstrings of snowflake_udfs.py. Both are bumped to '3.10', matching Feast's own minimum supported Python version (requires-python = ">=3.10.0" in pyproject.toml). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io>
Addresses maintainer feedback from @ntkathole on feast-dev#6608 ("is it possible to make it user configurable?") following the RUNTIME_VERSION 3.9 -> 3.10 bump for decommissioned Snowflake Python UDF runtimes (feast-dev#6606). Adds `python_udf_runtime_version` (default "3.10") to SnowflakeComputeEngineConfig, validated as a Python version string, and plumbs it through SnowflakeComputeEngine.update() via a new RUNTIME_VERSION_HOLDER placeholder in snowflake_python_udfs_creation.sql, following the same substitution pattern already used for STAGE_HOLDER and PROJECT_NAME. This way, the next time Snowflake decommissions a Python runtime, users can override the config instead of waiting on a Feast release with another hardcoded bump. Also updates snowflake_udfs.py with a note clarifying its RUNTIME_VERSION docstrings are static reference documentation of the default (not the templated value actually deployed), documents the new field in docs/reference/compute-engine/snowflake.md, and adds/updates tests covering the config default, custom override, validation, and the rendered SQL template. Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io>
c5ae39b to
a327346
Compare
…s take effect Addresses maintainer feedback from @ntkathole on feast-dev#6608 (feast-dev#6608 (comment)): once materialization UDFs were deployed for a project, SnowflakeComputeEngine.update() short-circuited on a `SHOW USER FUNCTIONS` check, and the SQL template used `CREATE FUNCTION IF NOT EXISTS`. Together, this meant an already-deployed project's UDFs were never redeployed, so changing `python_udf_runtime_version` (e.g. after Snowflake decommissions a runtime, as in feast-dev#6606) silently left the stale runtime version in place. Removes the early-return guard and switches every UDF creation statement in snowflake_python_udfs_creation.sql from `CREATE FUNCTION IF NOT EXISTS` to `CREATE OR REPLACE FUNCTION`, so `update()` always (re)deploys the UDFs using whatever runtime version is currently configured. Adds unit tests covering that update() no longer short-circuits and that a redeploy always uses the current python_udf_runtime_version. Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io>
# [0.65.0](v0.64.0...v0.65.0) (2026-07-20) ### Bug Fixes * add debug logging for FIPS mode detection fallback ([6c1b24e](6c1b24e)) * Build embedded UI from local source ([#6525](#6525)) ([3500349](3500349)) * Bump decommissioned Snowflake Python UDF runtime from 3.9 to 3.10 ([#6606](#6606)) ([#6608](#6608)) ([10341e4](10341e4)) * configure FIPS-compliant gRPC cipher suites for offline server ([6bc80a2](6bc80a2)) * Correct Flink PyArrow dependency constraints ([#6604](#6604)) ([70a9751](70a9751)) * Fix ValueError in signal handling for Trino worker threads ([#6428](#6428)) ([506d919](506d919)) * Fixed monitoring page issues ([7946018](7946018)) * Make pytest config compatible with newer pytest ([#5779](#5779)) ([a57ea33](a57ea33)) * Replace comma with space in DynamoDB-incompatible label tag value ([51e3a16](51e3a16)) * Resolve UI build warnings ([#6529](#6529)) ([abe92af](abe92af)) * Unblock nightly UI build ([#6570](#6570)) ([f296d4b](f296d4b)) * Use LONGBLOB for SQL registry proto columns on MySQL ([#6566](#6566)) ([7e4beb2](7e4beb2)) ### Features * Add click-to-zoom lightbox for blog post images ([#6575](#6575)) ([1cb23fd](1cb23fd)) * Add dark mode support to website and blog ([#6589](#6589)) ([7358fb8](7358fb8)) * Add OnlineStore for Aerospike ([#6532](#6532)) ([9cd35e1](9cd35e1)) * Add OpenLineage Consumer to Feast - receive, store, and visualize cross-producer lineage ([#6549](#6549)) ([a834126](a834126)) * Add registry list feature views by updated since ([#6092](#6092)) ([#6093](#6093)) ([006c606](006c606)) * Add ScyllaDB online store with vector search ([#6508](#6508)) ([1669661](1669661)) * Added compute and jobs UI ([ba2c05c](ba2c05c)) * Added Iceberg REST Catalog data source support ([e0a8573](e0a8573)) * Bring Your Own Spark - SparkApplication ([#6550](#6550)) ([dcd496f](dcd496f)) * **cassandra:** Add multi-DC support via per-datacenter execution profiles ([#6434](#6434)) ([0de9196](0de9196)) * Enhanced data source creation as a visual catalog with type-specific forms ([#6557](#6557)) ([d6acbba](d6acbba)) * Enhanced datasets UI functionality ([de11152](de11152)) * Implement RegistryServer.Proto RPC with RBAC-filtered response ([#6558](#6558)) ([#6552](#6552)) ([0d02614](0d02614)) * New zoned timestamp feature type ([#6536](#6536)) ([#6537](#6537)) ([eb042f0](eb042f0)) * **operator:** Auto-create RBAC for spark_application batch engine ([#6597](#6597)) ([f487b37](f487b37)) * **operator:** integrate cluster TLS profile for OCP 5.0 compliance ([43263a6](43263a6)) * Permissions CRUD UI and OIDC auth integration in UI ([6511da1](6511da1)) * Retrieve historical features from BigQuery without entity_df ([#6569](#6569)) ([cd5f6bb](cd5f6bb)), closes [#6558](#6558) [#6552](#6552) * **spark:** SparkSource query+path and pre-computed offline read for BatchFeatureView ([#6440](#6440)) ([4dc8757](4dc8757)) ### BREAKING CHANGES * total_timeout_ms is renamed to batch_total_timeout_ms. Config files using the old name must be updated. No default value change. Docs updated (reference + perf-tuning guide) with a short explainer on the per-attempt vs total deadline distinction. Two new unit tests pin the policy wiring: socket_timeout_ms propagates to all three scopes, and is omitted (not injected as None) when unset. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * refactor(aerospike): use MAP_KEY_ORDERED, KEY_DIGEST, and instance-scoped client Cheap-win cleanups flagged in review, all touching the same small patch of write-path and lifecycle code. * Map CDTs are now created with MAP_KEY_ORDERED. map_get_by_key / map_remove_by_key on an ordered map are O(log N) in the map size instead of O(N); matters on reads of wide feature views and on the update() background scan (which walks every record in the project's set). * Writes drop POLICY_KEY_SEND and rely on the client default (POLICY_KEY_DIGEST). The serialized entity key is no longer stored alongside each record, saving per-record storage the read path never consumes (batch_operate preserves request order; results are paired back by zip in online_read). * _client moves from a class attribute to an instance attribute (set in __init__). Previously two AerospikeOnlineStore instances could share the cached client through class state until one wrote self._client. With the instance attribute the state is always per-instance from construction. * Drop MongoDB references from class docstrings and comments (they referred to how the storage layout was derived rather than documenting current behavior). Also rewrite the _build_batch_writes docstring to describe the policies applied on the write path. Unit test assertions for the write-path record are updated: bw.policy is now None (client default applies) and map ops carry map_policy={'map_order': MAP_KEY_ORDERED}. All three docker-backed integration tests still pass end-to-end (cross-FV upsert, update() background scan, full feature-store round-trip), so the read/write shape survives the ordering and policy changes against a real server. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * feat(aerospike): add per-FV namespace/set overrides and prewriting hook Adds three configuration knobs to AerospikeOnlineStoreConfig: - namespace_overrides: pin individual feature views to a different Aerospike namespace (e.g. RAM-only vs. SSD-backed) without splitting the project across stores. - set_overrides: place a feature view in its own set so admin ops on it (truncate, scan-based deletes during `feast apply`) do not touch records of other views. - prewriting_hook: import-string-resolved callable invoked once per online_write_batch with the rows about to be written, returning the rows that actually go on the wire. Resolved and cached on first use; returning [] short-circuits the wire call. Read, write, update and teardown paths all honour the per-FV ns/set resolution. update() groups dropped feature views by their resolved (ns, set) pair and issues one background scan per group. teardown() truncates every unique (ns, set) pair the project may have written to, including the store-level default. Adds 22 unit tests for the new behaviour and updates 3 existing call sites of _build_batch_writes for the new namespace= parameter. Adds a sample hook module under examples/online_store/aerospike_overrides_and_hooks/ and corresponding sections in docs/reference/online-stores/aerospike.md. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * test: update aerospike image tag Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: sync README template and secrets baseline after master merge Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: fix secrets baseline line number for v1 operator types Adding aerospike to the feast-operator enum shifted the allowlisted SecretRef entry in api/v1/featurestore_types.go by one line. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * docs: update aerospike docs Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): wire batch max_retries and fix empty projection handling Copilot review feedback on PR #6532: - Add max_retries to the batch client policy (batch_operate/batch_write path) - Treat empty projected feature maps as present FV slots (is not None) - Return {} from _normalize_projected_features([]) instead of None - Fix projection unit test mock/assertions - Correct prewriting_hook config docstring Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * style(aerospike): format online_read docs assignment for ruff Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: update pixi.lock for aerospike optional extra Regenerate the v6 lockfile with Pixi v0.63.1 after adding the aerospike extra to pyproject.toml. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): add client init lock and batch chunking Guard lazy client creation with a lock to avoid connection leaks under concurrent first use, and chunk batch reads/writes by batch_max_records so large materializations stay under Aerospike server batch limits. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
feast-dev#6606) (feast-dev#6608) * fix: Bump decommissioned Snowflake Python UDF runtime from 3.9 to 3.10 (feast-dev#6606) Snowflake decommissioned the Python 3.9 UDF runtime, so any Snowflake offline store `feast apply` that deploys the Feast materialization UDFs now fails with "Python runtime version 3.9 is decommissioned". The RUNTIME_VERSION = '3.9' value was hardcoded in the executed UDF creation SQL template (snowflake_python_udfs_creation.sql) and mirrored in the reference docstrings of snowflake_udfs.py. Both are bumped to '3.10', matching Feast's own minimum supported Python version (requires-python = ">=3.10.0" in pyproject.toml). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io> * feat: Make Snowflake Python UDF runtime version user-configurable Addresses maintainer feedback from @ntkathole on feast-dev#6608 ("is it possible to make it user configurable?") following the RUNTIME_VERSION 3.9 -> 3.10 bump for decommissioned Snowflake Python UDF runtimes (feast-dev#6606). Adds `python_udf_runtime_version` (default "3.10") to SnowflakeComputeEngineConfig, validated as a Python version string, and plumbs it through SnowflakeComputeEngine.update() via a new RUNTIME_VERSION_HOLDER placeholder in snowflake_python_udfs_creation.sql, following the same substitution pattern already used for STAGE_HOLDER and PROJECT_NAME. This way, the next time Snowflake decommissions a Python runtime, users can override the config instead of waiting on a Feast release with another hardcoded bump. Also updates snowflake_udfs.py with a note clarifying its RUNTIME_VERSION docstrings are static reference documentation of the default (not the templated value actually deployed), documents the new field in docs/reference/compute-engine/snowflake.md, and adds/updates tests covering the config default, custom override, validation, and the rendered SQL template. Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io> * fix: Redeploy Snowflake UDFs on every apply so runtime version changes take effect Addresses maintainer feedback from @ntkathole on feast-dev#6608 (feast-dev#6608 (comment)): once materialization UDFs were deployed for a project, SnowflakeComputeEngine.update() short-circuited on a `SHOW USER FUNCTIONS` check, and the SQL template used `CREATE FUNCTION IF NOT EXISTS`. Together, this meant an already-deployed project's UDFs were never redeployed, so changing `python_udf_runtime_version` (e.g. after Snowflake decommissions a runtime, as in feast-dev#6606) silently left the stale runtime version in place. Removes the early-return guard and switches every UDF creation statement in snowflake_python_udfs_creation.sql from `CREATE FUNCTION IF NOT EXISTS` to `CREATE OR REPLACE FUNCTION`, so `update()` always (re)deploys the UDFs using whatever runtime version is currently configured. Adds unit tests covering that update() no longer short-circuits and that a redeploy always uses the current python_udf_runtime_version. Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io> --------- Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
# [0.65.0](feast-dev/feast@v0.64.0...v0.65.0) (2026-07-20) ### Bug Fixes * add debug logging for FIPS mode detection fallback ([6c1b24e](feast-dev@6c1b24e)) * Build embedded UI from local source ([feast-dev#6525](feast-dev#6525)) ([3500349](feast-dev@3500349)) * Bump decommissioned Snowflake Python UDF runtime from 3.9 to 3.10 ([feast-dev#6606](feast-dev#6606)) ([feast-dev#6608](feast-dev#6608)) ([10341e4](feast-dev@10341e4)) * configure FIPS-compliant gRPC cipher suites for offline server ([6bc80a2](feast-dev@6bc80a2)) * Correct Flink PyArrow dependency constraints ([feast-dev#6604](feast-dev#6604)) ([70a9751](feast-dev@70a9751)) * Fix ValueError in signal handling for Trino worker threads ([feast-dev#6428](feast-dev#6428)) ([506d919](feast-dev@506d919)) * Fixed monitoring page issues ([7946018](feast-dev@7946018)) * Make pytest config compatible with newer pytest ([feast-dev#5779](feast-dev#5779)) ([a57ea33](feast-dev@a57ea33)) * Replace comma with space in DynamoDB-incompatible label tag value ([51e3a16](feast-dev@51e3a16)) * Resolve UI build warnings ([feast-dev#6529](feast-dev#6529)) ([abe92af](feast-dev@abe92af)) * Unblock nightly UI build ([feast-dev#6570](feast-dev#6570)) ([f296d4b](feast-dev@f296d4b)) * Use LONGBLOB for SQL registry proto columns on MySQL ([feast-dev#6566](feast-dev#6566)) ([7e4beb2](feast-dev@7e4beb2)) ### Features * Add click-to-zoom lightbox for blog post images ([feast-dev#6575](feast-dev#6575)) ([1cb23fd](feast-dev@1cb23fd)) * Add dark mode support to website and blog ([feast-dev#6589](feast-dev#6589)) ([7358fb8](feast-dev@7358fb8)) * Add OnlineStore for Aerospike ([feast-dev#6532](feast-dev#6532)) ([9cd35e1](feast-dev@9cd35e1)) * Add OpenLineage Consumer to Feast - receive, store, and visualize cross-producer lineage ([feast-dev#6549](feast-dev#6549)) ([a834126](feast-dev@a834126)) * Add registry list feature views by updated since ([feast-dev#6092](feast-dev#6092)) ([feast-dev#6093](feast-dev#6093)) ([006c606](feast-dev@006c606)) * Add ScyllaDB online store with vector search ([feast-dev#6508](feast-dev#6508)) ([1669661](feast-dev@1669661)) * Added compute and jobs UI ([ba2c05c](feast-dev@ba2c05c)) * Added Iceberg REST Catalog data source support ([e0a8573](feast-dev@e0a8573)) * Bring Your Own Spark - SparkApplication ([feast-dev#6550](feast-dev#6550)) ([dcd496f](feast-dev@dcd496f)) * **cassandra:** Add multi-DC support via per-datacenter execution profiles ([feast-dev#6434](feast-dev#6434)) ([0de9196](feast-dev@0de9196)) * Enhanced data source creation as a visual catalog with type-specific forms ([feast-dev#6557](feast-dev#6557)) ([d6acbba](feast-dev@d6acbba)) * Enhanced datasets UI functionality ([de11152](feast-dev@de11152)) * Implement RegistryServer.Proto RPC with RBAC-filtered response ([feast-dev#6558](feast-dev#6558)) ([feast-dev#6552](feast-dev#6552)) ([0d02614](feast-dev@0d02614)) * New zoned timestamp feature type ([feast-dev#6536](feast-dev#6536)) ([feast-dev#6537](feast-dev#6537)) ([eb042f0](feast-dev@eb042f0)) * **operator:** Auto-create RBAC for spark_application batch engine ([feast-dev#6597](feast-dev#6597)) ([f487b37](feast-dev@f487b37)) * **operator:** integrate cluster TLS profile for OCP 5.0 compliance ([43263a6](feast-dev@43263a6)) * Permissions CRUD UI and OIDC auth integration in UI ([6511da1](feast-dev@6511da1)) * Retrieve historical features from BigQuery without entity_df ([feast-dev#6569](feast-dev#6569)) ([cd5f6bb](feast-dev@cd5f6bb)), closes [feast-dev#6558](feast-dev#6558) [feast-dev#6552](feast-dev#6552) * **spark:** SparkSource query+path and pre-computed offline read for BatchFeatureView ([feast-dev#6440](feast-dev#6440)) ([4dc8757](feast-dev@4dc8757)) ### BREAKING CHANGES * total_timeout_ms is renamed to batch_total_timeout_ms. Config files using the old name must be updated. No default value change. Docs updated (reference + perf-tuning guide) with a short explainer on the per-attempt vs total deadline distinction. Two new unit tests pin the policy wiring: socket_timeout_ms propagates to all three scopes, and is omitted (not injected as None) when unset. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * refactor(aerospike): use MAP_KEY_ORDERED, KEY_DIGEST, and instance-scoped client Cheap-win cleanups flagged in review, all touching the same small patch of write-path and lifecycle code. * Map CDTs are now created with MAP_KEY_ORDERED. map_get_by_key / map_remove_by_key on an ordered map are O(log N) in the map size instead of O(N); matters on reads of wide feature views and on the update() background scan (which walks every record in the project's set). * Writes drop POLICY_KEY_SEND and rely on the client default (POLICY_KEY_DIGEST). The serialized entity key is no longer stored alongside each record, saving per-record storage the read path never consumes (batch_operate preserves request order; results are paired back by zip in online_read). * _client moves from a class attribute to an instance attribute (set in __init__). Previously two AerospikeOnlineStore instances could share the cached client through class state until one wrote self._client. With the instance attribute the state is always per-instance from construction. * Drop MongoDB references from class docstrings and comments (they referred to how the storage layout was derived rather than documenting current behavior). Also rewrite the _build_batch_writes docstring to describe the policies applied on the write path. Unit test assertions for the write-path record are updated: bw.policy is now None (client default applies) and map ops carry map_policy={'map_order': MAP_KEY_ORDERED}. All three docker-backed integration tests still pass end-to-end (cross-FV upsert, update() background scan, full feature-store round-trip), so the read/write shape survives the ordering and policy changes against a real server. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * feat(aerospike): add per-FV namespace/set overrides and prewriting hook Adds three configuration knobs to AerospikeOnlineStoreConfig: - namespace_overrides: pin individual feature views to a different Aerospike namespace (e.g. RAM-only vs. SSD-backed) without splitting the project across stores. - set_overrides: place a feature view in its own set so admin ops on it (truncate, scan-based deletes during `feast apply`) do not touch records of other views. - prewriting_hook: import-string-resolved callable invoked once per online_write_batch with the rows about to be written, returning the rows that actually go on the wire. Resolved and cached on first use; returning [] short-circuits the wire call. Read, write, update and teardown paths all honour the per-FV ns/set resolution. update() groups dropped feature views by their resolved (ns, set) pair and issues one background scan per group. teardown() truncates every unique (ns, set) pair the project may have written to, including the store-level default. Adds 22 unit tests for the new behaviour and updates 3 existing call sites of _build_batch_writes for the new namespace= parameter. Adds a sample hook module under examples/online_store/aerospike_overrides_and_hooks/ and corresponding sections in docs/reference/online-stores/aerospike.md. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * test: update aerospike image tag Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: sync README template and secrets baseline after master merge Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: fix secrets baseline line number for v1 operator types Adding aerospike to the feast-operator enum shifted the allowlisted SecretRef entry in api/v1/featurestore_types.go by one line. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * docs: update aerospike docs Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): wire batch max_retries and fix empty projection handling Copilot review feedback on PR feast-dev#6532: - Add max_retries to the batch client policy (batch_operate/batch_write path) - Treat empty projected feature maps as present FV slots (is not None) - Return {} from _normalize_projected_features([]) instead of None - Fix projection unit test mock/assertions - Correct prewriting_hook config docstring Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * style(aerospike): format online_read docs assignment for ruff Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * chore: update pixi.lock for aerospike optional extra Regenerate the v6 lockfile with Pixi v0.63.1 after adding the aerospike extra to pyproject.toml. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com> * fix(aerospike): add client init lock and batch chunking Guard lazy client creation with a lock to avoid connection leaks under concurrent first use, and chunk batch reads/writes by batch_max_records so large materializations stay under Aerospike server batch limits. Signed-off-by: Valentyn Kahamlyk <valentin.kagamlyk@gmail.com>
Fixes #6606
Snowflake decommissioned the Python 3.9 UDF runtime environment as of
April 30, 2026, so any
feast applyagainst a Snowflake offline storethat deploys Feast's materialization UDFs now fails with:
Python runtime version 3.9 is decommissioned. Please update your code to Python runtime version 3.10 or later.What changed
RUNTIME_VERSION = '3.9'was hardcoded 16 times insnowflake_python_udfs_creation.sql(the SQL template actually executedagainst Snowflake by
SnowflakeComputeEngine.deploy_infra) and mirroredin the reference docstrings of
snowflake_udfs.py. Both are bumped to'3.10', matching Feast's own minimum supported Python version(
requires-python = ">=3.10.0"in pyproject.toml) and a runtimeSnowflake still supports.
Test evidence
Added
sdk/python/tests/unit/infra/utils/snowflake/test_snowflake_udfs.py,which statically asserts neither file references the decommissioned
runtime version.
Before fix:
After fix:
Full snowflake unit suite: 28 passed. Broader
sdk/python/tests/unit/infrasuite: 397 passed (1 pre-existing, unrelated environment failure due to
missing pip in the test venv).
ruff check/formatandmypyclean ontouched files.
Prepared with AI assistance (Claude, agent: claude-sonnet-5), reviewed for correctness before submission.