Skip to content

Commit 915e50b

Browse files
committed
Comments
1 parent ba8c923 commit 915e50b

6 files changed

Lines changed: 96 additions & 70 deletions

File tree

src/adapter/endpoint.ts

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class AdapterEndpoint<T extends EndpointGenerics> implements AdapterEndpo
4646
settings: T['Settings'],
4747
) => string
4848
defaultTransport?: string
49-
fallbackTransport?: string
49+
fallbackTransport?: Record<string, string>
5050

5151
constructor(params: AdapterEndpointParams<T>) {
5252
this.name = params.name
@@ -56,7 +56,14 @@ export class AdapterEndpoint<T extends EndpointGenerics> implements AdapterEndpo
5656
this.transportRoutes = params.transportRoutes
5757
this.customRouter = params.customRouter
5858
this.defaultTransport = params.defaultTransport
59-
this.fallbackTransport = params.fallbackTransport?.toLowerCase()
59+
this.fallbackTransport = params.fallbackTransport
60+
? Object.fromEntries(
61+
Object.entries(params.fallbackTransport).map(([k, v]) => [
62+
k.toLowerCase(),
63+
v.toLowerCase(),
64+
]),
65+
)
66+
: undefined
6067
} else {
6168
this.transportRoutes = new TransportRoutes<T>().register(
6269
DEFAULT_TRANSPORT_NAME,
@@ -71,6 +78,25 @@ export class AdapterEndpoint<T extends EndpointGenerics> implements AdapterEndpo
7178
this.customOutputValidation = params.customOutputValidation
7279
this.overrides = params.overrides
7380
this.requestTransforms = [this.symbolOverrider.bind(this), ...(params.requestTransforms || [])]
81+
82+
// Validate fallback structure if it's defined
83+
Object.entries(this.fallbackTransport || {}).forEach(([primary, fallback]) => {
84+
if (primary === fallback) {
85+
throw new AdapterError({
86+
statusCode: 400,
87+
message: `Fallback transport "${fallback}" cannot be the same as primary transport.`,
88+
})
89+
}
90+
91+
if (!this.transportRoutes.get(fallback)) {
92+
throw new AdapterError({
93+
statusCode: 400,
94+
message: `No fallback transport found for key "${fallback}", must be one of ${JSON.stringify(
95+
this.transportRoutes.routeNames(),
96+
)}`,
97+
})
98+
}
99+
})
74100
}
75101

76102
/**
@@ -194,26 +220,14 @@ export class AdapterEndpoint<T extends EndpointGenerics> implements AdapterEndpo
194220
return
195221
}
196222

197-
const fallbackTransportName = this.fallbackTransport.toLowerCase()
198-
199-
if (!this.transportRoutes.get(fallbackTransportName)) {
200-
throw new AdapterError({
201-
statusCode: 400,
202-
message: `No fallback transport found for key "${fallbackTransportName}", must be one of ${JSON.stringify(
203-
this.transportRoutes.routeNames(),
204-
)}`,
205-
})
206-
}
223+
const fallbackTransportName = this.fallbackTransport[primaryTransportName.toLowerCase()]
207224

208-
if (fallbackTransportName === primaryTransportName.toLowerCase()) {
209-
throw new AdapterError({
210-
statusCode: 400,
211-
message: `Fallback transport "${fallbackTransportName}" cannot be the same as primary transport.`,
212-
})
225+
if (fallbackTransportName) {
226+
logger.debug(`Request can fall back to transport "${fallbackTransportName}"`)
227+
return fallbackTransportName
228+
} else {
229+
logger.trace(`No fallback transport defined for "${primaryTransportName}"`)
213230
}
214-
215-
logger.debug(`Request can fall back to transport "${fallbackTransportName}"`)
216-
return fallbackTransportName
217231
}
218232

219233
/**

src/adapter/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ type MultiTransportAdapterEndpointParams<T extends EndpointGenerics> = {
184184
/** If no value is returned from the custom router or the default (transport param), which transport to use */
185185
defaultTransport?: string
186186

187-
/** Backup transport to use when the primary transport is unable to return data */
188-
fallbackTransport?: string
187+
/** Primary transport mapped to backup transport to use when primary is unable to return data */
188+
fallbackTransport?: Record<string, string>
189189
}
190190

191191
/**

src/util/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export type AdapterRequestContext<T> = {
3939
cacheKey: string
4040

4141
/** Fallback transport context to use if the primary transport is unable to return data */
42+
// TODO: Implement using this
4243
fallback?: {
4344
transportName: string
4445
cacheKey: string

src/validation/index.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
TypeFromDefinition,
2020
validateOverrides,
2121
} from './input-params'
22+
import { _ } from 'ajv'
2223
export { InputParameters } from './input-params'
2324

2425
const errorCatcherLogger = makeLogger('ErrorCatchingMiddleware')
@@ -77,10 +78,6 @@ export const validatorMiddleware: AdapterMiddlewareBuilder =
7778
req,
7879
adapter.config.settings,
7980
)
80-
const fallbackTransportName = endpoint.getFallbackTransportNameForRequest(
81-
req.requestContext.transportName,
82-
adapter.config.settings,
83-
)
8481

8582
// Custom input validation defined in the EA
8683
const error =
@@ -110,12 +107,18 @@ export const validatorMiddleware: AdapterMiddlewareBuilder =
110107
req.requestContext = { ...req.requestContext, meta: { metrics } }
111108
}
112109

110+
const fallbackTransportName = endpoint.getFallbackTransportNameForRequest(
111+
req.requestContext.transportName,
112+
adapter.config.settings,
113+
)
114+
113115
// Now that all the transformations have been applied, all that's left is calculating the cache key
114116
if (endpoint.cacheKeyGenerator) {
115117
if (fallbackTransportName) {
116-
errorCatcherLogger.warn(
117-
'Fallback transports ignored for endpoints with custom cache key generators',
118-
)
118+
throw new AdapterInputError({
119+
message: 'fallbackTransport not supported for endpoints with cacheKeyGenerator',
120+
statusCode: 404,
121+
})
119122
}
120123

121124
let cacheKey
@@ -135,23 +138,24 @@ export const validatorMiddleware: AdapterMiddlewareBuilder =
135138

136139
req.requestContext.cacheKey = `${cachePrefix}${cacheKey}`
137140
} else {
138-
req.requestContext.cacheKey = calculateCacheKey({
141+
const commonCacheKeyParams = {
139142
data: req.requestContext.data,
140143
adapterName: adapter.name,
141144
endpointName: endpoint.name,
142-
transportName: req.requestContext.transportName,
143145
adapterSettings: adapter.config.settings,
146+
}
147+
148+
req.requestContext.cacheKey = calculateCacheKey({
149+
...commonCacheKeyParams,
150+
transportName: req.requestContext.transportName,
144151
})
145152

146153
if (fallbackTransportName) {
147154
req.requestContext.fallback = {
148155
transportName: fallbackTransportName,
149156
cacheKey: calculateCacheKey({
150-
data: req.requestContext.data,
151-
adapterName: adapter.name,
152-
endpointName: endpoint.name,
157+
...commonCacheKeyParams,
153158
transportName: fallbackTransportName,
154-
adapterSettings: adapter.config.settings,
155159
}),
156160
}
157161
}

test/cache/cache-key.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ test.serial('builds fallback cache key from fallback transport name', async (t)
211211
)
212212
.register('fallback', new NopTransport()),
213213
defaultTransport: 'primary',
214-
fallbackTransport: 'fallback',
214+
fallbackTransport: { primary: 'fallback' },
215215
}),
216216
],
217217
})
@@ -225,7 +225,7 @@ test.serial('builds fallback cache key from fallback transport name', async (t)
225225
)
226226
})
227227

228-
test.serial('custom cache key generator ignores fallback transport', async (t) => {
228+
test.serial('custom cache key generator throws on fallback transport', async (t) => {
229229
const config = new AdapterConfig(
230230
{},
231231
{
@@ -265,16 +265,19 @@ test.serial('custom cache key generator ignores fallback transport', async (t) =
265265
)
266266
.register('fallback', new NopTransport()),
267267
defaultTransport: 'primary',
268-
fallbackTransport: 'fallback',
268+
fallbackTransport: { primary: 'fallback' },
269269
}),
270270
],
271271
})
272272
const testAdapter = await TestAdapter.start(adapter, t.context)
273273

274274
const response = await testAdapter.request({})
275275

276-
t.is(response.statusCode, 200)
277-
t.is(response.json().result, 'test:custom_cache_key')
276+
t.is(response.statusCode, 404)
277+
t.is(
278+
response.json().error.message,
279+
'fallbackTransport not supported for endpoints with cacheKeyGenerator',
280+
)
278281
})
279282

280283
test.serial('custom cache key is truncated if over max size', async (t) => {

test/transports/routing.test.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -685,37 +685,32 @@ test.serial('fallback transport is ignored when disabled', (t) => {
685685
inputParameters,
686686
name: 'price',
687687
transportRoutes: transports,
688-
fallbackTransport: 'invalid',
688+
fallbackTransport: { batch: 'websocket' },
689689
})
690690
const config = new AdapterConfig(settings)
691691
config.initialize()
692692

693693
t.is(endpoint.getFallbackTransportNameForRequest('batch', config.settings), undefined)
694694
})
695695

696-
test.serial('fallback transport is normalized when enabled', (t) => {
696+
test.serial('fallback transport missing', (t) => {
697697
const endpoint = new AdapterEndpoint<BaseEndpointTypes>({
698698
inputParameters,
699699
name: 'price',
700700
transportRoutes: transports,
701-
fallbackTransport: 'WEBSOCKET',
702-
})
703-
const config = new AdapterConfig(settings, {
704-
envDefaultOverrides: {
705-
TRANSPORT_FALLBACK_ENABLED: true,
706-
},
707701
})
702+
const config = new AdapterConfig(settings)
708703
config.initialize()
709704

710-
t.is(endpoint.getFallbackTransportNameForRequest('batch', config.settings), 'websocket')
705+
t.is(endpoint.getFallbackTransportNameForRequest('batch', config.settings), undefined)
711706
})
712707

713-
test.serial('fallback transport must be registered when enabled', (t) => {
708+
test.serial('fallback transport is normalized when enabled', (t) => {
714709
const endpoint = new AdapterEndpoint<BaseEndpointTypes>({
715710
inputParameters,
716711
name: 'price',
717712
transportRoutes: transports,
718-
fallbackTransport: 'invalid',
713+
fallbackTransport: { BATCH: 'WEBSOCKET' },
719714
})
720715
const config = new AdapterConfig(settings, {
721716
envDefaultOverrides: {
@@ -724,29 +719,38 @@ test.serial('fallback transport must be registered when enabled', (t) => {
724719
})
725720
config.initialize()
726721

727-
t.throws(() => endpoint.getFallbackTransportNameForRequest('batch', config.settings), {
728-
message:
729-
'No fallback transport found for key "invalid", must be one of ["websocket","batch","sse"]',
730-
})
722+
t.is(endpoint.getFallbackTransportNameForRequest('batch', config.settings), 'websocket')
731723
})
732724

733-
test.serial('fallback transport cannot match primary transport', (t) => {
734-
const endpoint = new AdapterEndpoint<BaseEndpointTypes>({
735-
inputParameters,
736-
name: 'price',
737-
transportRoutes: transports,
738-
fallbackTransport: 'batch',
739-
})
740-
const config = new AdapterConfig(settings, {
741-
envDefaultOverrides: {
742-
TRANSPORT_FALLBACK_ENABLED: true,
725+
test.serial('fallback transport must be registered', async (t) => {
726+
t.throws(
727+
() =>
728+
new AdapterEndpoint<BaseEndpointTypes>({
729+
inputParameters,
730+
name: 'price',
731+
transportRoutes: transports,
732+
fallbackTransport: { batch: 'invalid' },
733+
}),
734+
{
735+
message:
736+
'No fallback transport found for key "invalid", must be one of ["websocket","batch","sse"]',
743737
},
744-
})
745-
config.initialize()
738+
)
739+
})
746740

747-
t.throws(() => endpoint.getFallbackTransportNameForRequest('batch', config.settings), {
748-
message: 'Fallback transport "batch" cannot be the same as primary transport.',
749-
})
741+
test.serial('fallback transport cannot match primary transport', async (t) => {
742+
t.throws(
743+
() =>
744+
new AdapterEndpoint<BaseEndpointTypes>({
745+
inputParameters,
746+
name: 'price',
747+
transportRoutes: transports,
748+
fallbackTransport: { batch: 'batch' },
749+
}),
750+
{
751+
message: 'Fallback transport "batch" cannot be the same as primary transport.',
752+
},
753+
)
750754
})
751755

752756
test.serial('transport override routes to correct Transport', async (t) => {

0 commit comments

Comments
 (0)