@@ -37,14 +37,24 @@ export interface RuntimeServiceDependencies {
3737 randomBytes ( size : number ) : Buffer
3838}
3939
40+ export interface RuntimeServiceProvider {
41+ readonly name : string
42+ readonly kind : string
43+ readonly version : string
44+ provision ( service : WorkspaceRecipeRuntimeService , dependencies : RuntimeServiceDependencies , signal : AbortSignal | undefined , evidence : RuntimeServiceEvidence [ ] ) : Promise < ManagedRuntimeService >
45+ }
46+
4047const defaultDependencies : RuntimeServiceDependencies = {
4148 execute : async ( command , args , options ) => await execFileAsync ( command , args , options ) ,
4249 waitForReady : waitForMysqlProtocol ,
4350 randomBytes,
4451}
4552
4653export function runtimeServicePlan ( services : WorkspaceRecipeRuntimeService [ ] ) : Array < { id : string ; kind : string ; provider : string ; version : string ; bind : "loopback" ; port : "ephemeral" ; persistentVolume : false ; outputs : Record < string , string > } > {
47- return services . map ( ( service ) => ( { id : service . id , kind : service . kind , provider : "docker" , version : MYSQL_IMAGE , bind : "loopback" , port : "ephemeral" , persistentVolume : false , outputs : service . outputs } ) )
54+ return services . map ( ( service ) => {
55+ const provider = runtimeServiceProvider ( service . kind )
56+ return { id : service . id , kind : service . kind , provider : provider . name , version : provider . version , bind : "loopback" , port : "ephemeral" , persistentVolume : false , outputs : service . outputs }
57+ } )
4858}
4959
5060export async function provisionRuntimeServices ( services : WorkspaceRecipeRuntimeService [ ] , options : { signal ?: AbortSignal ; dependencies ?: RuntimeServiceDependencies } = { } ) : Promise < { env : Record < string , string > ; evidence : RuntimeServiceEvidence [ ] ; release ( ) : Promise < void > } > {
@@ -53,7 +63,7 @@ export async function provisionRuntimeServices(services: WorkspaceRecipeRuntimeS
5363 const evidence : RuntimeServiceEvidence [ ] = [ ]
5464 try {
5565 for ( const service of services ) {
56- const managed = await provisionRuntimeService ( service , dependencies , options . signal , evidence )
66+ const managed = await runtimeServiceProvider ( service . kind ) . provision ( service , dependencies , options . signal , evidence )
5767 provisioned . push ( managed )
5868 }
5969 } catch ( error ) {
@@ -71,15 +81,21 @@ export async function provisionRuntimeServices(services: WorkspaceRecipeRuntimeS
7181 }
7282}
7383
74- async function provisionRuntimeService ( service : WorkspaceRecipeRuntimeService , dependencies : RuntimeServiceDependencies , signal : AbortSignal | undefined , evidenceList : RuntimeServiceEvidence [ ] ) : Promise < ManagedRuntimeService > {
84+ const mysqlDockerProvider : RuntimeServiceProvider = {
85+ name : "docker" ,
86+ kind : "mysql" ,
87+ version : MYSQL_IMAGE ,
88+ provision : provisionMysqlDockerService ,
89+ }
90+
91+ function runtimeServiceProvider ( kind : string ) : RuntimeServiceProvider {
92+ if ( kind === mysqlDockerProvider . kind ) return mysqlDockerProvider
93+ throw new Error ( `Unsupported managed runtime service kind: ${ kind } ` )
94+ }
95+
96+ async function provisionMysqlDockerService ( service : WorkspaceRecipeRuntimeService , dependencies : RuntimeServiceDependencies , signal : AbortSignal | undefined , evidenceList : RuntimeServiceEvidence [ ] ) : Promise < ManagedRuntimeService > {
7597 const evidence : RuntimeServiceEvidence = { id : service . id , kind : service . kind , provider : "docker" , version : MYSQL_IMAGE , readiness : "pending" , lifecycle : "provisioning" }
7698 evidenceList . push ( evidence )
77- if ( service . kind !== "mysql" ) {
78- evidence . lifecycle = "failed"
79- evidence . diagnostic = { code : "provision-failed" }
80- throw new RuntimeServiceProvisionError ( `Unsupported managed runtime service kind: ${ service . kind } ` , evidenceList )
81- }
82-
8399 const container = `wp-codebox-${ service . id } -${ dependencies . randomBytes ( 6 ) . toString ( "hex" ) } `
84100 const password = dependencies . randomBytes ( 24 ) . toString ( "base64url" )
85101 const childEnvironment = { PATH : process . env . PATH , MYSQL_DATABASE : "runtime" , MYSQL_USER : "runtime" , MYSQL_PASSWORD : password , MYSQL_ROOT_PASSWORD : password }
@@ -96,7 +112,7 @@ async function provisionRuntimeService(service: WorkspaceRecipeRuntimeService, d
96112 evidence . readiness = "ready"
97113 evidence . lifecycle = "provisioned"
98114 const values : Record < string , string > = { host : "127.0.0.1" , port : String ( port ) , username : "runtime" , password, database : "runtime" }
99- return { env : Object . fromEntries ( Object . entries ( service . outputs ) . map ( ( [ output , name ] ) => [ name , values [ output ] ?? "" ] ) ) , evidence, async release ( ) { await releaseService ( container , evidence , dependencies , signal ) } }
115+ return { env : Object . fromEntries ( Object . entries ( service . outputs ) . map ( ( [ output , name ] ) => [ name , values [ output ] ?? "" ] ) ) , evidence, async release ( ) { await releaseService ( container , evidence , dependencies ) } }
100116 } catch ( error ) {
101117 evidence . readiness = "failed"
102118 evidence . lifecycle = "failed"
0 commit comments