Repository navigation
feat(service,host): poll where Neon Realtime is not configured - #3943
Closed
charleslpan wants to merge 3 commits into
Closed
charleslpan wants to merge 3 commits into
charleslpan wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
luke-agent
Bot
force-pushed
the
luke/neon-realtime-service-wake
branch
from
October 20, 2026 01:36
e46eaf4 to
b3338fd
Compare
luke-agent
Bot
force-pushed
the
luke/neon-realtime-poll-fallback
branch
from
October 20, 2026 01:36
8d0aca4 to
b1374da
Compare
luke-agent
Bot
force-pushed
the
luke/neon-realtime-service-wake
branch
from
October 20, 2026 02:06
b3338fd to
a768591
Compare
luke-agent
Bot
force-pushed
the
luke/neon-realtime-poll-fallback
branch
from
October 20, 2026 02:27
5463d81 to
92c32aa
Compare
A deployment without NEON_REALTIME_URL and NEON_REALTIME_SECRET (a Preview, local dev) now polls behind the same interfaces rather than hearing nothing: the service's LiveWake wakes every held read about once a second, its sealer reads each live statement on the database client and answers the rows inline at LIVE_POLL_URL, and the host's client at that address hands those rows on, sealing again every three seconds and skipping a poll whose rows did not change. Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
luke-agent
Bot
force-pushed
the
luke/neon-realtime-poll-fallback
branch
from
October 20, 2026 02:33
92c32aa to
7c1266c
Compare
…og as an error Previews and local dev poll quietly; production should never poll, so an instance there that finds the Realtime variables missing logs an error at start instead of polling silently. Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
Contributor
|
Closing as superseded by #4172 (with #4167), now on main. The wire's |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacks on #3266. Production has
NEON_REALTIME_URLandNEON_REALTIME_SECRETand keeps running on Realtime. Previews and local dev have neither, and until now they heard nothing. This PR adds a polling fallback for them, chosen in one place per side, so no live area changes.The fallback
live/live-wake.ts): the wake that died when Realtime wasn't configured is nowpollingWake. Itswatchfires everyLIVE_WAKE_POLL(1 s), so every held read checks again about once a second, which covers board look's 8 s deadline. A Realtime that refuses its configuration also falls back to polling.LIVE_SAFETY_POLLis unchanged, and its doc comment now says it is the only recovery from a refused or dropped Realtime watch.live/realtime.ts,runtime.ts): without the variables,liveSealingFromEnvironmentreturnspollSealer. Itssealruns the statement throughSqlClientand answers the usual shape at the sentinelLIVE_POLL_URL, with the rows inline. The layer now needsSqlClient.runtime.tsprovides it with the samewebSqlClient, and layer memoization keeps it to one pool. A secret that Realtime refuses still answersunavailable.live-wire.ts):sealedLiveQuerySchemagains an optionalrows. The wire's JSON Schema has no form forUnknown, so the rows travel as JSON text (fromJsonString). The live endpoints now encode their answers through the answer schemas, and the host already decodes with them. The JSON Schema goldens are regenerated withLUKE_UPDATE_FIXTURES=1, and the only change in them isrows: {type: string}. No new route or token was added: the rows only travel through/api/live/*, behind the bearer.live-follow.ts): when the address isLIVE_POLL_URL,openRealtimeClientreturns a pollingLiveClient. It hands on each seal's rows and skips a renewal whose rows haven't changed.liveRowsre-seals everyLIVE_POLL_EVERY(3 s) at that address. I put the cadence there rather than in a made-upexpiresAtbecause an expiry close to now would make the renewal fire immediately, over and over.Tests
live-app.test.ts: with the poll sealer, a plan inbox's rows come back at the poll address. Decoded through the wire schemas, they equal whattaskInboxItems(the held read) returns.realtime.test.ts: without the variables the sealer polls and returns rows. A refused secret still leaves it off.live-wake.test.ts: with no wake configured, a held read checks again after 1 s. This replaces the "dies when not configured" test.live-follow.test.ts(new): a polled read feedsliveRowsand skips unchanged rows.Checks run locally
Typecheck for features, service, host and web. Biome, oxlint,
repository-checks.shand knip. Vitest for the host, features and service projects, plusplan-comments.Not confirmed
Made with Luke