33 Client as IClient ,
44 Command ,
55 FetchHttpHandlerOptions ,
6+ Handler ,
67 MetadataBearer ,
78 MiddlewareStack ,
89 NodeHttpHandlerOptions ,
@@ -24,6 +25,22 @@ export interface SmithyConfiguration<HandlerOptions> {
2425 * @internal
2526 */
2627 readonly apiVersion : string ;
28+ /**
29+ * @public
30+ *
31+ * Default false.
32+ *
33+ * When true, the client will only resolve the middleware stack once per
34+ * Command class. This means modifying the middlewareStack of the
35+ * command or client after requests have been made will not be
36+ * recognized.
37+ *
38+ * Calling client.destroy() also clears this cache.
39+ *
40+ * Enable this only if needing the additional time saved (0-1ms per request)
41+ * and not needing middleware modifications between requests.
42+ */
43+ cacheMiddleware ?: boolean ;
2744}
2845
2946/**
@@ -32,6 +49,7 @@ export interface SmithyConfiguration<HandlerOptions> {
3249export type SmithyResolvedConfiguration < HandlerOptions > = {
3350 requestHandler : RequestHandler < any , any , HandlerOptions > ;
3451 readonly apiVersion : string ;
52+ cacheMiddleware ?: boolean ;
3553} ;
3654
3755/**
@@ -45,10 +63,13 @@ export class Client<
4563> implements IClient < ClientInput , ClientOutput , ResolvedClientConfiguration >
4664{
4765 public middlewareStack : MiddlewareStack < ClientInput , ClientOutput > = constructStack < ClientInput , ClientOutput > ( ) ;
48- readonly config : ResolvedClientConfiguration ;
49- constructor ( config : ResolvedClientConfiguration ) {
50- this . config = config ;
51- }
66+ /**
67+ * May be used to cache the resolved handler function for a Command class.
68+ */
69+ private handlers ?: WeakMap < Function , Handler < any , any > > | undefined ;
70+
71+ constructor ( public readonly config : ResolvedClientConfiguration ) { }
72+
5273 send < InputType extends ClientInput , OutputType extends ClientOutput > (
5374 command : Command < ClientInput , InputType , ClientOutput , OutputType , SmithyResolvedConfiguration < HandlerOptions > > ,
5475 options ?: HandlerOptions
@@ -69,7 +90,28 @@ export class Client<
6990 ) : Promise < OutputType > | void {
7091 const options = typeof optionsOrCb !== "function" ? optionsOrCb : undefined ;
7192 const callback = typeof optionsOrCb === "function" ? ( optionsOrCb as ( err : any , data ?: OutputType ) => void ) : cb ;
72- const handler = command . resolveMiddleware ( this . middlewareStack as any , this . config , options ) ;
93+
94+ const useHandlerCache = options === undefined && this . config . cacheMiddleware === true ;
95+
96+ let handler : Handler < any , any > ;
97+
98+ if ( useHandlerCache ) {
99+ if ( ! this . handlers ) {
100+ this . handlers = new WeakMap ( ) ;
101+ }
102+ const handlers = this . handlers ! ;
103+
104+ if ( handlers . has ( command . constructor ) ) {
105+ handler = handlers . get ( command . constructor ) ! ;
106+ } else {
107+ handler = command . resolveMiddleware ( this . middlewareStack as any , this . config , options ) ;
108+ handlers . set ( command . constructor , handler ) ;
109+ }
110+ } else {
111+ delete this . handlers ;
112+ handler = command . resolveMiddleware ( this . middlewareStack as any , this . config , options ) ;
113+ }
114+
73115 if ( callback ) {
74116 handler ( command )
75117 . then (
@@ -87,6 +129,7 @@ export class Client<
87129 }
88130
89131 destroy ( ) {
90- if ( this . config . requestHandler . destroy ) this . config . requestHandler . destroy ( ) ;
132+ this . config ?. requestHandler ?. destroy ?.( ) ;
133+ delete this . handlers ;
91134 }
92135}
0 commit comments