Skip to content

Commit bbd39e1

Browse files
committed
chore(search): sync staging and sequence embedding repair
2 parents d12717f + 9a10d35 commit bbd39e1

37 files changed

Lines changed: 29147 additions & 2258 deletions

.github/workflows/test-build.yml

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ jobs:
3030
--health-interval 5s
3131
--health-timeout 5s
3232
--health-retries 10
33+
postgres-legacy:
34+
image: postgres:16-alpine
35+
env:
36+
POSTGRES_USER: postgres
37+
POSTGRES_PASSWORD: postgres
38+
POSTGRES_DB: sim_billing_test
39+
ports:
40+
- 5433:5432
41+
options: >-
42+
--health-cmd "pg_isready -U postgres -d sim_billing_test"
43+
--health-interval 5s
44+
--health-timeout 5s
45+
--health-retries 10
3346
env:
3447
DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim
3548
OAUTH_TOKEN_FAMILY_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim
@@ -83,6 +96,19 @@ jobs:
8396
ee/scim/lib/managed-membership.postgres.test.ts
8497
lib/auth/sso/application/admit-sso-user.postgres.test.ts
8598
99+
- name: Verify cumulative billing timeout recovery in PostgreSQL
100+
working-directory: apps/sim
101+
env:
102+
BILLING_USAGE_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim
103+
run: bunx vitest run lib/billing/core/usage-log.postgres.test.ts
104+
105+
- name: Verify cumulative billing timeout recovery on PostgreSQL 16
106+
if: matrix.provision == 'push'
107+
working-directory: apps/sim
108+
env:
109+
BILLING_USAGE_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5433/sim_billing_test
110+
run: bunx vitest run lib/billing/core/usage-log.postgres.test.ts
111+
86112
- name: Verify SCIM and administration over real HTTP
87113
working-directory: apps/sim
88114
env:
@@ -153,14 +179,16 @@ jobs:
153179
lib/table/rows/secret-provenance.postgres.test.ts
154180
lib/memory/message-provenance.postgres.test.ts
155181
156-
- name: Verify Search progress and pagination in PostgreSQL
182+
- name: Verify Search progress, pagination, and outbox scheduling in PostgreSQL
157183
working-directory: apps/sim
158184
env:
159185
KNOWLEDGE_ACL_TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/sim_auth_scim
160186
run: >-
161187
bunx vitest run --mode integration
162188
lib/knowledge/__integration__/search-source-progress.integration.ts
163189
lib/knowledge/__integration__/search-source-pagination.integration.ts
190+
lib/core/outbox/service.integration.ts
191+
lib/knowledge/__integration__/connector-upload.integration.ts
164192
165193
test-build:
166194
name: Lint and Test

apps/docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"fumadocs-mdx": "14.3.2",
2929
"fumadocs-openapi": "10.8.1",
3030
"fumadocs-ui": "16.8.5",
31-
"next": "16.3.1",
31+
"next": "16.3.4",
3232
"next-themes": "^0.4.6",
3333
"react": "19.2.4",
3434
"react-dom": "19.2.4",

apps/sim/app/(landing)/components/featured-customer/featured-customer-card.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@ interface FeaturedCustomerCardProps {
3434
story: FeaturedCustomerStory
3535
active: boolean
3636
emphasized: boolean
37+
preload: boolean
3738
}
3839

3940
/** Shared media and editorial caption treatment for each featured-customer slide. */
40-
export function FeaturedCustomerCard({ story, active, emphasized }: FeaturedCustomerCardProps) {
41+
export function FeaturedCustomerCard({
42+
story,
43+
active,
44+
emphasized,
45+
preload,
46+
}: FeaturedCustomerCardProps) {
4147
const videoRef = useRef<HTMLVideoElement>(null)
4248
const reducedMotion = usePrefersReducedMotion()
4349
const isFilm = story.media.kind === 'video'
@@ -51,10 +57,9 @@ export function FeaturedCustomerCard({ story, active, emphasized }: FeaturedCust
5157
}
5258

5359
/**
54-
* The film streams only while the slide is on screen in a visible tab:
55-
* `play()` defeats `preload='none'`, so calling it at mount would pull
56-
* the whole file for a section well below the fold. Autoplay may still be
57-
* blocked, in which case the poster remains the fallback.
60+
* Preload prepares neighboring films when the carousel reaches the viewport.
61+
* Playback is restricted to the active, visible slide in a visible tab.
62+
* If autoplay is blocked, the poster remains the fallback.
5863
*/
5964
const canObserve = typeof IntersectionObserver !== 'undefined'
6065
let inView = !canObserve
@@ -103,7 +108,7 @@ export function FeaturedCustomerCard({ story, active, emphasized }: FeaturedCust
103108
loop
104109
muted
105110
playsInline
106-
preload='none'
111+
preload={preload && !reducedMotion ? 'auto' : 'none'}
107112
src={story.media.src}
108113
tabIndex={-1}
109114
className='pointer-events-none absolute inset-0 size-full rounded-[inherit] object-cover motion-reduce:hidden'

apps/sim/app/(landing)/components/featured-customer/featured-customer.test.tsx

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ beforeEach(() => {
4343
afterEach(() => {
4444
vi.useRealTimers()
4545
vi.restoreAllMocks()
46+
vi.unstubAllGlobals()
4647
document.body.replaceChildren()
4748
})
4849

@@ -87,7 +88,7 @@ describe('FeaturedCustomer', () => {
8788
)
8889
const expVideo = expRealty.querySelector('video') as HTMLVideoElement
8990
expect(expVideo.getAttribute('src')).toBe('/landing/customer-stories/exp-house-color-loop.mp4')
90-
expect(expVideo.getAttribute('preload')).toBe('none')
91+
expect(expVideo.getAttribute('preload')).toBe('auto')
9192
expect(expVideo.muted).toBe(true)
9293
expect(vi.mocked(video.play).mock.contexts).not.toContain(expVideo)
9394
expect(
@@ -178,6 +179,55 @@ describe('FeaturedCustomer', () => {
178179
})
179180
})
180181

182+
it('prepares neighboring videos only once the carousel is visible without starting playback', () => {
183+
const observers: Array<{
184+
target: Element
185+
intersect: (isIntersecting: boolean) => void
186+
}> = []
187+
vi.stubGlobal(
188+
'IntersectionObserver',
189+
class {
190+
constructor(private readonly callback: IntersectionObserverCallback) {}
191+
192+
observe(target: Element) {
193+
observers.push({
194+
target,
195+
intersect: (isIntersecting) =>
196+
this.callback(
197+
[{ target, isIntersecting } as IntersectionObserverEntry],
198+
{} as IntersectionObserver
199+
),
200+
})
201+
}
202+
203+
disconnect() {}
204+
}
205+
)
206+
const host = document.createElement('div')
207+
document.body.appendChild(host)
208+
const root = createRoot(host)
209+
act(() => root.render(<FeaturedCustomer />))
210+
211+
const videos = [...host.querySelectorAll('video')]
212+
expect(videos.map((video) => video.preload)).toEqual(['none', 'none'])
213+
expect(HTMLMediaElement.prototype.play).not.toHaveBeenCalled()
214+
215+
const regionObserver = observers.find(({ target }) => target.tagName === 'DIV')!
216+
act(() => regionObserver.intersect(true))
217+
expect(videos.map((video) => video.preload)).toEqual(['auto', 'auto'])
218+
expect(HTMLMediaElement.prototype.play).not.toHaveBeenCalled()
219+
220+
const playbackObserver = observers.find(({ target }) => target === videos[0])!
221+
act(() => playbackObserver.intersect(true))
222+
expect(vi.mocked(HTMLMediaElement.prototype.play).mock.contexts).toEqual([videos[0]])
223+
224+
motionPreference.reduced = true
225+
act(() => root.render(<FeaturedCustomer />))
226+
expect(videos.map((video) => video.preload)).toEqual(['none', 'none'])
227+
228+
act(() => root.unmount())
229+
})
230+
181231
it('keeps video paused with reduced motion and responds to preference changes', () => {
182232
motionPreference.reduced = true
183233
;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true

apps/sim/app/(landing)/components/featured-customer/featured-customer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
LANDING_GUTTER,
1313
LANDING_STAGE_RADIUS,
1414
} from '@/app/(landing)/components/landing-layout'
15+
import { useLazyMount } from '@/app/(landing)/hooks/use-lazy-mount'
1516

1617
const WHEEL_GESTURE_GAP_MS = 200
1718
const WHEEL_THRESHOLD_PX = 50
@@ -58,6 +59,7 @@ const CUSTOMER_STORIES: FeaturedCustomerStory[] = [
5859
export function FeaturedCustomer() {
5960
const railRef = useRef<HTMLDivElement>(null)
6061
const touchStartRef = useRef<{ id: number; x: number; y: number } | null>(null)
62+
const { ref: mediaRegionRef, inView: preloadVideos } = useLazyMount('0px')
6163
const [activeIndex, setActiveIndex] = useState(0)
6264
const [previewedIndex, setPreviewedIndex] = useState<number | null>(null)
6365
const activeStory = CUSTOMER_STORIES[activeIndex]
@@ -143,7 +145,7 @@ export function FeaturedCustomer() {
143145
aria-roledescription='carousel'
144146
className='w-full overflow-hidden'
145147
>
146-
<div className={cn(LANDING_CONTENT_WIDTH, LANDING_GUTTER)}>
148+
<div ref={mediaRegionRef} className={cn(LANDING_CONTENT_WIDTH, LANDING_GUTTER)}>
147149
<div className='mb-4 flex items-center justify-end gap-2 xl:pr-24'>
148150
<FeaturedCustomerNavigationButton
149151
direction='previous'
@@ -210,6 +212,7 @@ export function FeaturedCustomer() {
210212
story={story}
211213
active={isActive}
212214
emphasized={isActive || isPreviewed}
215+
preload={preloadVideos}
213216
/>
214217
{!isActive && (
215218
<button

apps/sim/app/(landing)/customers/components/customer-story-media/customer-story-media.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ describe('CustomerStoryMedia', () => {
2727
const html = renderToStaticMarkup(<CustomerStoryMedia story={exp} />)
2828

2929
expect(html).not.toContain('<video')
30-
expect(html).toContain(exp.logo.src)
30+
expect(html).toContain(encodeURIComponent(exp.heroImage!))
31+
expect(html).toContain(exp.heroAlt)
3132
})
3233

3334
it('keeps the artwork fallback for stories without video', () => {

apps/sim/app/api/billing/update-cost/route.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ async function updateCostInner(req: NextRequest, span: Span): Promise<NextRespon
312312
* Every accepted callback has a stable key, so the maximum cumulative cost
313313
* converges on one ledger event without underbilling or double-billing.
314314
*/
315+
const usageStartedAt = Date.now()
315316
const result = await recordCumulativeUsage({
316317
userId,
317318
workspaceId: resolvedWorkspaceId,
@@ -330,6 +331,7 @@ async function updateCostInner(req: NextRequest, span: Span): Promise<NextRespon
330331
billedDelta: result.delta,
331332
newTotal: result.total,
332333
billed: result.billed,
334+
durationMs: Date.now() - usageStartedAt,
333335
})
334336

335337
// Reconcile the payer's ledger-backed threshold after every cumulative

apps/sim/app/api/webhooks/outbox/process/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
5454
}
5555

5656
const result = await processOutboxEvents(handlers, {
57-
batchSize: 20,
57+
batchSize: 500,
5858
maxRuntimeMs: 790_000,
5959
minRemainingMs: 95_000,
6060
})

0 commit comments

Comments
 (0)