import { Configuration , Security } from "../base" ; import { Proxy , Service } from "../decorators" ; import { InternalServerError } from "../errors" ; import { Logger } from "../logger" ; import { ContainerMetadata } from "../metadata" ; import { EventRequest , EventResult , HttpRequest , HttpResponse , RemoteRequest } from "../types" ; import { Container , ContainerState } from "./common" ; import { ContainerInstance } from "./instance" ; export class ContainerPool implements Container { protected log : Logger ; private application : string ; private name : string ; private cstate : ContainerState ; private registers : { target : any ; args : any [ ] ; } [ ] ; private publishes : { service : any ; args : any [ ] ; } [ ] ; private head : ContainerInstance ; private pool : ContainerInstance [ ] ; constructor ( application , name ? ) { this . application = application ; this . name = name || ContainerPool . name ; this . log = Logger . get ( application , this . name ) ; this . cstate = ContainerState . Pending ; this . registers = [ ] ; this . publishes = [ ] ; this . pool = [ ] ; } public get state ( ) : ContainerState { return this . cstate ; } public get metadata ( ) : ContainerMetadata { if ( this . cstate !== ContainerState . Ready ) return undefined ; return this . head . metadata ; } public get config ( ) : Configuration { if ( this . cstate !== ContainerState . Ready ) return undefined ; return this . head . get < Configuration > ( Configuration ) ; } public get security ( ) : Security { if ( this . cstate !== ContainerState . Ready ) return undefined ; return this . head . get < Security > ( Security ) ; } public register ( resource , name ? ) ; public register ( service ) ; public register ( proxy ) ; public register ( type , ... args ) ; public register ( target , ... args ) { if ( this . cstate !== ContainerState . Pending ) throw new InternalServerError ( "Invalid container state" ) ; this . registers . push ( { target , args } ) ; return this ; } public publish ( service , ... args ) ; public publish ( service ) ; public publish ( service , ... args ) { if ( this . cstate !== ContainerState . Pending ) throw new InternalServerError ( "Invalid container state" ) ; this . publishes . push ( { service , args } ) ; return this ; } public prepare ( ) { let instance = this . pool . find ( x => x . state === ContainerState . Ready ) ; if ( ! instance ) { instance = new ContainerInstance ( this . application , this . pool . length . toString ( ) ) ; this . registers . forEach ( u => instance . register ( u . target , ... u . args ) ) ; this . publishes . forEach ( p => instance . publish ( p . service , ... p . args ) ) ; instance . prepare ( ) ; this . pool . push ( instance ) ; this . head = this . head || instance ; } if ( this . cstate === ContainerState . Pending ) this . cstate = ContainerState . Ready ; return instance ; } public dispose ( ) { if ( this . cstate !== ContainerState . Ready ) throw new InternalServerError ( "Invalid container state" ) ; this . pool = [ this . head ] ; } public async remoteRequest ( req ) { if ( this . cstate !== ContainerState . Ready ) throw new InternalServerError ( "Invalid container state" ) ; let instance = this . prepare ( ) ; return instance . remoteRequest ( req ) ; } public async eventRequest ( req ) { if ( this . cstate !== ContainerState . Ready ) throw new InternalServerError ( "Invalid container state" ) ; let instance = this . prepare ( ) ; return instance . eventRequest ( req ) ; } public async httpRequest ( req ) { if ( this . cstate !== ContainerState . Ready ) throw new InternalServerError ( "Invalid container state" ) ; let instance = this . prepare ( ) ; return instance . httpRequest ( req ) ; } }