Skip to content

Fix pseudo-irregular time series direct reads#1781

Merged
krowvin merged 15 commits into
developfrom
issue-1745-pseudo-irregular
Jul 9, 2026
Merged

Fix pseudo-irregular time series direct reads#1781
krowvin merged 15 commits into
developfrom
issue-1745-pseudo-irregular

Conversation

@krowvin

@krowvin krowvin commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the time-series direct-read path for pseudo-irregular old-style local-regular IDs such as *.~15Minutes.* when X-CWMS-LRTS-Formatting: true is present.

Root cause

The direct-read path could resolve pseudo-irregular old-style IDs through new LRTS formatting, producing local-regular metadata and returning no values. It also treated ~ intervals as regular without first honoring interval_utc_offset = UTC_OFFSET_IRREGULAR, which could incorrectly invoke gap-fill behavior for pseudo-irregular data.

Changes

  • Detect old-style ~ IDs whose old-format metadata has irregular interval offset.
  • Resolve/read those IDs under old LRTS formatting for direct reads.
  • Suppress regular gap-fill and report zero interval duration for truly irregular offset metadata.
  • Add an integration regression test that seeds a pseudo-irregular ~15Minutes series and verifies the CDA response matches retrieve_ts under the LRTS formatting header.

Validation

  • ./gradlew.bat :cwms-data-api:compileJava :cwms-data-api:compileTestJava --no-daemon
  • ./gradlew.bat :cwms-data-api:integrationTests --tests "*TimeSeriesDirectReadParityIT.pseudoIrregularReadWithLrtsHeaderMatchesRetrieveTs" "-PCDA_POOL_INIT_SIZE=5" "-PCDA_POOL_MAX_ACTIVE=10" "-PCDA_POOL_MAX_IDLE=5" "-PCDA_POOL_MIN_IDLE=2" --no-daemon
  • ./gradlew.bat :cwms-data-api:checkstyleMain :cwms-data-api:checkstyleTest --no-daemon

Note: broader TimeSeriesDirectReadParityIT runs were not clean in this local container due fixture/setup issues before the relevant endpoint path was exercised, including Oracle seed partition check failures and a default-data county error.

Closes #1745

Comment thread cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java Outdated
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
@krowvin

krowvin commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator Author

pseudo-irregular ~15Minutes series were being handled like true local-regular series in the direct-read path, which caused incorrect LRTS/session behavior and large window reads

changes

  • This fix uses database authoritative LRTS detection via CWMS_TS_PACKAGE.call_IS_LRTS__2(...).
  • Pseudo-irregular series with interval_utc_offset == UTC_OFFSET_IRREGULAR are treated as irregular and return observed rows only.
  • True local-regular/LRTS series still use expected-time generation and gap-fill behavior.
  • Removed the old workaround that forced old LRTS formatting through recursive DAO construction and raw JDBC row reads.
  • Kept the direct row read in jOOQ against AV_TSV_DQU.
  • Row reads now filter by requested UNIT_ID and normalize quality in Java.
  • Added/adapted regression coverage for ITPARPIRR.Flow.Inst.~15Minutes.0.BENCH with X-CWMS-LRTS-Formatting: true.
  • Verified the pseudo-irregular regression test passes.
  • Verified full TimeSeriesDirectReadParityIT passes locally.
  • Verified compile and checkstyle tasks pass locally with JDK 21.
  • Tested MVP timeseries Baldhill_Dam.Flow-Out.Inst.~15Minutes.0.best.

tests

  • For a 70,177-row production sized window (2024-01-01 to 2026-01-01), local CDA returned the same row count, timestamps, qualities, and pseudo-irregular metadata.
  • Local timing for that 70k-row window was about 2 seconds, compared with production runs around 29-38 seconds.
  • pulled data from each instance, local and prod, to confirm no drift in datasets.

timings

For this command

localhost

curl -sS -w '\nstatus=%{http_code} time=%{time_total}s bytes=%{size_download}\n' \
  -H 'Accept: application/json;version=2' \
  -H 'X-CWMS-LRTS-Formatting: true' \
  'http://localhost:8081/cwms-data/timeseries?name=Baldhill_Dam.Flow-Out.Inst.~15Minutes.0.best&office=MVP&unit=cfs&begin=2025-05-01T00:00:00Z&end=2025-06-01T00:00:00Z&page-size=100000'

national

curl -sS -w '\nstatus=%{http_code} time=%{time_total}s bytes=%{size_download}\n' \
  -H 'Accept: application/json;version=2' \
  'https://cwms-data.usace.army.mil/cwms-data/timeseries?name=Baldhill_Dam.Flow-Out.Inst.~15Minutes.0.best&office=MVP&unit=cfs&begin=2025-05-01T00:00:00Z&end=2025-06-01T00:00:00Z&page-size=100000'

(LRTS header not in Prod yet)

Target Window Rows Runs Min Median Mean Max Next Page
Local CDA 2024-01-01 to 2026-01-01 70,177 5 1.815s 1.903s 2.075s 2.668s No
Production CDA 2024-01-01 to 2026-01-01 70,177 3 29.088s 37.805s

@krowvin krowvin requested a review from MikeNeilson June 20, 2026 15:09
@krowvin krowvin marked this pull request as ready for review June 20, 2026 15:09
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>

@MikeNeilson MikeNeilson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note possible conflicts with #1780 depending on which gets merged in first.

Comment thread cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java Outdated
@MikeNeilson

MikeNeilson commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

TSV PR was merged in, conflicts need to be fixed. Also see my comments about LRTS methods and usage, feels like something is stuck down a rabbit hole of over thinking and needs to get dug out.

Ask database if this TSID is LRTS or REGULAR interval
yes -> have expected interval set in some way shape or form
no -> just return the data from the tsv query as it, the timestamps provided are by definition correct.

Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
@krowvin krowvin force-pushed the issue-1745-pseudo-irregular branch from 3c4c715 to f362ce4 Compare June 26, 2026 01:56
krowvin added 2 commits June 25, 2026 22:15
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
@krowvin krowvin force-pushed the issue-1745-pseudo-irregular branch from f362ce4 to cea2f38 Compare June 26, 2026 03:19
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
@krowvin krowvin requested a review from MikeNeilson June 29, 2026 13:57

@MikeNeilson MikeNeilson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some concerns with the overall logic, but some of that wasn't touched in this PR.

Actual concerns address in specific comments.

Otherwise, looks reasonable, and the tests show expected behavior correctly.


Timestamp beginTimestamp = Timestamp.from(beginTime.toInstant());
Timestamp endTimestamp = Timestamp.from(endTime.toInstant());
String beginTimestampText = beginTimestamp.toLocalDateTime().format(ORACLE_DATE_FORMATTER);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we spending time formatting a timestamp that can be used as-is in the query?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I was trying to run the test for TimeSeriesDirectReadParityIT it started failing/saying missing.

I agree converting from one and back to the other is wasted cycles though. Any ideas on how to make it so it'll match up with AV_TSV_DQU.DATE_TIME?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. that's, unexpected, especially since it's a begin/end time stamp so a few seconds on either side shouldn't matter much. Might have something to do with the columns being Date instead of Timestamp in the database.

Presumably the performance is still improved overall? If so, I'd argue that challenge is reasonable cause to leave the extra conversions in. Not like it happens for every row. Just put a comment in about why for future readers.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it failing in your dev environment, or on GitHub Actions? I'm curious if your local time zone is getting in the mix somehow

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was failing in my local integration test run. The GitHub checks were green with the current to_date(bindText) comparison.

When I switched the AV_TSV_DQU.DATE_TIME to direct Timestamp locally TimeSeriesDirectReadParityIT started returning missing/zero direct read rows compared to retrieve_ts. I left the request conversion and added a comment explaining. Probably onto something about the local TZ though.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is your local database a docker instance or something else?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the conversion only happens once, it's not a huge performance hit, some I'm okay with this explanation for the time being. We'll want to look into it more, but we don't think we should hold up this change just for that.

Comment thread cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java Outdated
@krowvin krowvin requested a review from rma-psmorris June 29, 2026 16:22
@krowvin

krowvin commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Spoke in CDA biweekly if RMA would also be able to review and ensure nothing was missed.

krowvin added 2 commits June 29, 2026 16:57
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
@adamkorynta adamkorynta self-requested a review July 2, 2026 20:54
Comment thread cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java Outdated
krowvin added 3 commits July 8, 2026 14:46
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
Signed-off-by: Charles Graham, SWT <charles.r.graham@usace.army.mil>
@krowvin krowvin requested a review from adamkorynta July 9, 2026 04:39
@krowvin krowvin requested a review from MikeNeilson July 9, 2026 04:39
@krowvin krowvin merged commit a2a9029 into develop Jul 9, 2026
8 checks passed
@krowvin krowvin deleted the issue-1745-pseudo-irregular branch July 9, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TimeSeries Endpoint - Pseudo Irregular Fixes

3 participants