Skip to content

Commit 4000e27

Browse files
author
LongYinan
committed
fix(ssr): skipped actions should always be retried on client
1 parent 4e50621 commit 4000e27

File tree

3 files changed

+46
-23
lines changed

3 files changed

+46
-23
lines changed

packages/core/src/module.ts

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ export abstract class EffectModule<S> {
4343
private readonly actionStreams: any = {}
4444
private readonly retryActionsCreator: any = {}
4545
private readonly actionNames: string[] = []
46-
private actionsToRetry: Set<string> = new Set()
47-
private actionsToSkip!: string[]
46+
private actionsToRetry!: Set<string>
47+
private actionsToSkip!: Set<string>
4848
private restoredFromSSR = false
4949

5050
get state$() {
@@ -119,10 +119,12 @@ export abstract class EffectModule<S> {
119119
if (!context.store.ready) {
120120
context.store.setup(context.getDefaultState())
121121
context.actionsToRetry = new Set(_globalThis[RETRY_KEY_SYMBOL]?.[this.moduleName] || [])
122-
context.actionsToSkip = context.restoredFromSSR
123-
? // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
124-
getActionsToSkip(context.constructor.prototype) || []
125-
: []
122+
context.actionsToSkip = new Set(
123+
context.restoredFromSSR
124+
? // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
125+
getActionsToSkip(context.constructor.prototype) || []
126+
: [],
127+
)
126128
}
127129
return rawSetter.call(this, value)
128130
}
@@ -131,10 +133,12 @@ export abstract class EffectModule<S> {
131133
if (!context.store.ready) {
132134
context.store.setup(context.getDefaultState())
133135
context.actionsToRetry = new Set(_globalThis[RETRY_KEY_SYMBOL]?.[context.moduleName] || [])
134-
context.actionsToSkip = context.restoredFromSSR
135-
? // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
136-
getActionsToSkip(context.constructor.prototype) || []
137-
: []
136+
context.actionsToSkip = new Set(
137+
context.restoredFromSSR
138+
? // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
139+
getActionsToSkip(context.constructor.prototype) || []
140+
: [],
141+
)
138142
}
139143
}
140144
}
@@ -146,10 +150,12 @@ export abstract class EffectModule<S> {
146150
if (!context.store.ready) {
147151
context.store.setup(context.getDefaultState())
148152
context.actionsToRetry = new Set(_globalThis[RETRY_KEY_SYMBOL]?.[context.moduleName] || [])
149-
context.actionsToSkip = context.restoredFromSSR
150-
? // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
151-
getActionsToSkip(context.constructor.prototype) || []
152-
: []
153+
context.actionsToSkip = new Set(
154+
context.restoredFromSSR
155+
? // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
156+
getActionsToSkip(context.constructor.prototype) || []
157+
: [],
158+
)
153159
}
154160
}
155161
return Reflect.set(target, p, value, receiver)
@@ -163,7 +169,7 @@ export abstract class EffectModule<S> {
163169
this.store.setup(this.getDefaultState())
164170
this.actionsToRetry = new Set(_globalThis[RETRY_KEY_SYMBOL]?.[this.moduleName] || [])
165171
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
166-
this.actionsToSkip = this.restoredFromSSR ? getActionsToSkip(this.constructor.prototype) || [] : []
172+
this.actionsToSkip = new Set(this.restoredFromSSR ? getActionsToSkip(this.constructor.prototype) || [] : [])
167173
}
168174
},
169175
get: () => {
@@ -281,7 +287,7 @@ export abstract class EffectModule<S> {
281287
const effect: Effect<unknown> = (this as any)[name]
282288
const payload$ = action$.pipe(
283289
filter(({ type }, index) => {
284-
const skipCount = !this.actionsToRetry.has(name) && this.actionsToSkip?.includes(name) ? 1 : 0
290+
const skipCount = !this.actionsToRetry.has(name) && this.actionsToSkip?.has(name) ? 1 : 0
285291
return type === name && skipCount <= index
286292
}),
287293
map(({ payload }) => payload),

packages/react/src/__tests__/ssr.spec.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ describe('SSR specs:', () => {
645645
expect(state['actionsToRetry']).toEqual({ ServiceModule: ['setNameWithFailure'] })
646646
})
647647

648-
it('should be able to persist actions to retry on the other module', async () => {
648+
it('should be able to persist actions to retry on the other module, and the skipped actions', async () => {
649649
@Module('InnerServiceModule')
650650
// eslint-disable-next-line @typescript-eslint/ban-types
651651
class InnerServiceModule extends EffectModule<CountState> {
@@ -680,12 +680,24 @@ describe('SSR specs:', () => {
680680
setName(payload$: Observable<void>): Observable<Action> {
681681
return payload$.pipe(mergeMap(() => of(this.serviceModule.getActions().setNameWithFailure(1))))
682682
}
683+
684+
@Effect({
685+
payloadGetter(_: any, skipAction) {
686+
return skipAction
687+
},
688+
})
689+
skippedSetName(payload$: Observable<void>): Observable<Action> {
690+
return payload$.pipe(map(() => this.serviceModule.getActions().setName('skipped')))
691+
}
683692
}
684693

685694
const req = {}
686695
const state = await emitSSREffects(req, [InnerServiceModule, InnerCountModule2], { providers: MODULES })
687696
.pendingState
688697

689-
expect(state['actionsToRetry']).toEqual({ InnerServiceModule: ['setNameWithFailure'] })
698+
expect(state['actionsToRetry']).toEqual({
699+
InnerCountModel2: ['skippedSetName'],
700+
InnerServiceModule: ['setNameWithFailure'],
701+
})
690702
})
691703
})

packages/ssr/src/run.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { EffectModule, TERMINATE_ACTION_TYPE_SYMBOL, getSSREffectMeta, RETRY_ACTION_TYPE_SYMBOL } from '@sigi/core'
22
import { rootInjector, Injector, Provider } from '@sigi/di'
3-
import { ConstructorOf } from '@sigi/types'
3+
import { ConstructorOf, Action } from '@sigi/types'
44

55
import { StateToPersist } from './state-to-persist'
66

@@ -60,11 +60,11 @@ export const runSSREffects = <Context, Returned = any>(
6060
const subscription = store.action$.subscribe({
6161
next: ({ type, payload }) => {
6262
if (type === RETRY_ACTION_TYPE_SYMBOL) {
63-
const { module, name } = payload as any
64-
if (!actionsToRetry[module.moduleName]) {
65-
actionsToRetry[module.moduleName] = [name] as string[]
63+
const { name } = payload as Action<{ name: string }>['payload']
64+
if (!actionsToRetry[moduleName]) {
65+
actionsToRetry[moduleName] = [name] as string[]
6666
} else {
67-
actionsToRetry[module.moduleName].push(name as string)
67+
actionsToRetry[moduleName].push(name as string)
6868
}
6969
}
7070
if (type === TERMINATE_ACTION_TYPE_SYMBOL) {
@@ -96,6 +96,11 @@ export const runSSREffects = <Context, Returned = any>(
9696
store,
9797
})
9898
} else {
99+
if (!actionsToRetry[moduleName]) {
100+
actionsToRetry[moduleName] = [ssrActionMeta.action]
101+
} else {
102+
actionsToRetry[moduleName].push(ssrActionMeta.action)
103+
}
99104
effectsCount--
100105
if (terminatedCount === effectsCount) {
101106
resolve()

0 commit comments

Comments
 (0)