Package: @firebaseextensions/firestore-bigquery-change-tracker, src/bigquery/initializeLatestMaterializedView.ts on next.
With VIEW_TYPE=materialized_incremental, both REFRESH_INTERVAL_MINUTES and MAX_STALENESS are silently ignored. The incremental branch does not forward them to the query builder, while the non-incremental branch does:
const { query, source } = config.useIncrementalMaterializedView
? buildMaterializedViewQuery({
projectId: bq.projectId,
datasetId: config.datasetId,
tableName: rawChangeLogTableName,
rawLatestViewName,
schema,
// maxStaleness and refreshIntervalMinutes are never passed
})
: buildNonIncrementalMaterializedViewQuery({
...
maxStaleness: config.maxStaleness,
refreshIntervalMinutes: config.refreshIntervalMinutes,
enableRefresh: true,
...
});
buildMaterializedViewQuery accepts both and is written to emit them (src/bigquery/snapshot.ts), but receives undefined for each, so its options array stays empty and optionsString collapses to "". The emitted DDL therefore carries no OPTIONS clause at all and BigQuery applies its own defaults (refresh_interval_minutes = 30, enable_refresh = true).
Reproduction
Deployed live to a test project with VIEW_TYPE=materialized_incremental and REFRESH_INTERVAL_MINUTES=60, as both the extension and the kit:
|
refreshIntervalMs |
expected |
firebase/firestore-bigquery-export@0.3.3 |
1800000 |
3600000 |
@firebase-function-kits/firestore-bigquery-export@0.0.2-rc.14 |
1800000 |
3600000 |
REFRESH_INTERVAL_MINUTES=60 was confirmed present on the deployed resources themselves (the Cloud Run container env of the task that builds the DDL, and the Extensions API record of the installed instance), so neither is falling back to the param default.
The DDL logged by the task confirms no options are emitted:
CREATE MATERIALIZED VIEW `<project>.<dataset>.<table>_raw_latest` AS (
BigQuery's reconstructed DDL from INFORMATION_SCHEMA.TABLES agrees, and contrasts with a non-incremental instance configured with MAX_STALENESS, which does get an OPTIONS( clause.
Secondary effect
shouldRecreateMaterializedView decides whether to recreate by comparing formatted query text plus the incremental/non-incremental flag. Because these options never reach the query text, changing REFRESH_INTERVAL_MINUTES or MAX_STALENESS on an existing incremental view produces a byte-identical query and the view is left alone with Materialized view requested, but a view with matching configuration exists. Skipping creation. So the values cannot be corrected by reconfiguring either; the view has to be dropped manually.
Fix
Pass both arguments in the incremental branch. Note the non-incremental branch also passes enableRefresh: true explicitly while the incremental branch sets nothing — today both land on true because that is BigQuery's default, so a fix that adds only refresh_interval_minutes would leave that asymmetry in place.
Worth a test asserting the generated DDL contains refresh_interval_minutes and max_staleness for the incremental path, since the current tests only cover the non-incremental one.
This is pre-existing extension behaviour, not a kit-migration regression; the kit inherits it via the shared tracker dependency (the extension's ^2.0.4 and the kit's ^2.2.1 both resolve to 2.2.1, and the bug is present in the 2.0.4 source too).
Package:
@firebaseextensions/firestore-bigquery-change-tracker,src/bigquery/initializeLatestMaterializedView.tsonnext.With
VIEW_TYPE=materialized_incremental, bothREFRESH_INTERVAL_MINUTESandMAX_STALENESSare silently ignored. The incremental branch does not forward them to the query builder, while the non-incremental branch does:buildMaterializedViewQueryaccepts both and is written to emit them (src/bigquery/snapshot.ts), but receivesundefinedfor each, so itsoptionsarray stays empty andoptionsStringcollapses to"". The emitted DDL therefore carries noOPTIONSclause at all and BigQuery applies its own defaults (refresh_interval_minutes = 30,enable_refresh = true).Reproduction
Deployed live to a test project with
VIEW_TYPE=materialized_incrementalandREFRESH_INTERVAL_MINUTES=60, as both the extension and the kit:refreshIntervalMsfirebase/firestore-bigquery-export@0.3.3@firebase-function-kits/firestore-bigquery-export@0.0.2-rc.14REFRESH_INTERVAL_MINUTES=60was confirmed present on the deployed resources themselves (the Cloud Run container env of the task that builds the DDL, and the Extensions API record of the installed instance), so neither is falling back to the param default.The DDL logged by the task confirms no options are emitted:
BigQuery's reconstructed DDL from
INFORMATION_SCHEMA.TABLESagrees, and contrasts with a non-incremental instance configured withMAX_STALENESS, which does get anOPTIONS(clause.Secondary effect
shouldRecreateMaterializedViewdecides whether to recreate by comparing formatted query text plus the incremental/non-incremental flag. Because these options never reach the query text, changingREFRESH_INTERVAL_MINUTESorMAX_STALENESSon an existing incremental view produces a byte-identical query and the view is left alone withMaterialized view requested, but a view with matching configuration exists. Skipping creation.So the values cannot be corrected by reconfiguring either; the view has to be dropped manually.Fix
Pass both arguments in the incremental branch. Note the non-incremental branch also passes
enableRefresh: trueexplicitly while the incremental branch sets nothing — today both land ontruebecause that is BigQuery's default, so a fix that adds onlyrefresh_interval_minuteswould leave that asymmetry in place.Worth a test asserting the generated DDL contains
refresh_interval_minutesandmax_stalenessfor the incremental path, since the current tests only cover the non-incremental one.This is pre-existing extension behaviour, not a kit-migration regression; the kit inherits it via the shared tracker dependency (the extension's
^2.0.4and the kit's^2.2.1both resolve to 2.2.1, and the bug is present in the 2.0.4 source too).