diff --git a/assets/resource-class-diagram.png b/assets/resource-class-diagram.png index b9d1f6df..dbda08ca 100644 Binary files a/assets/resource-class-diagram.png and b/assets/resource-class-diagram.png differ diff --git a/docs/dev_guide/extend-sdk.en.md b/docs/dev_guide/extend-sdk.en.md index 49f8ee4c..460df1f4 100644 --- a/docs/dev_guide/extend-sdk.en.md +++ b/docs/dev_guide/extend-sdk.en.md @@ -10,6 +10,7 @@ If you encounter any unclear concepts or unexplained terms in this document, ple - Define two types of functional interfaces in the Client SDK: - An interface for defining runtime functionality methods, called the Client Interface. - An interface for defining infrastructure-related methods, called the Infra Interface. + - An interface that includes attributes generated at compile-time and accessed at runtime, referred to as a Prop Interface. - Define a resource operation interface in the Client SDK to expose the functionality methods for the resource. - Adding a new implementation for the resource type - Create a class implementation for the Client Interface in the Client SDK and bind it through the `buildClient` method of the resource type. @@ -29,7 +30,7 @@ The methods defined in the Client Interface are the runtime functional methods t ```typescript // The client interface is used to define the methods for accessing resources that are used during runtime. -export interface QueueClient { +export interface IQueueClientApi extends base.IResourceClientApi { push(msg: string): Promise; } ``` @@ -41,14 +42,12 @@ The methods defined in the Infra Interface are used to build resource associatio As a message queue, the Queue usually allows creating a subscriber to consume the messages published in the Queue. The method for creating a subscriber is called `subscribe`. The `subscribe` method takes an `EventHandler` type object as a parameter. The `EventHandler` type is a function type interface that inherits the `base.FnResource` interface, indicating that the `EventHandler` type is a FaaS resource type. ```typescript -import { FnResource } from "@plutolang/base"; - // The infra interface is used to define the methods for accessing resources that are used during compilation. -export interface QueueInfra { +export interface IQueueInfraApi extends base.IResourceInfraApi { subscribe(fn: EventHandler): void; } -export interface EventHandler extends FnResource { +export interface EventHandler extends base.FnResource { (evt: CloudEvent): Promise; } @@ -58,7 +57,15 @@ export interface CloudEvent { } ``` -### Define the resource operation interface exposed to users +### Define the Prop Interface + +The property interface defines a set of getter methods. The values corresponding to these methods cannot be obtained solely based on the data provided by the user. For instance, the URL of a router in apigateway can only be known after deployment. Currently, Queue does not have such requirements, hence it is empty. + +```typescript +export interface IQueueCapturedProps extends base.IResourceCapturedProps {} +``` + +### Define the Resource Operation Interface Exposed to Users The resource operation interface exposed to users consists of a pair of classes and interfaces with the same name. The interface inherits both the client interface and the infrastructure interface, while the class only defines the constructor and a static `buildClient` method. This leverages the TypeScript feature of type merging, allowing the class to provide sufficient hints to developers even though it does not implement the interface methods. @@ -68,7 +75,10 @@ Here, the resource class should be treated as an equivalent of an abstract class import { Resource, runtime } from "@plutolang/base"; import { aws, k8s } from "./clients"; -export class Queue implements Resource { +export type IQueueClient = IQueueCapturedProps & IQueueClientApi; +export type IQueueInfra = IQueueCapturedProps & IQueueInfraApi; + +export class Queue { constructor(name: string, opts?: QueueOptions) { name; opts; @@ -77,7 +87,7 @@ export class Queue implements Resource { ); } - public static buildClient(name: string, opts?: QueueClientOptions): QueueClient { + public static buildClient(name: string, opts?: QueueClientOptions): IQueueClient { const rtType = process.env["RUNTIME_TYPE"]; switch (rtType) { case runtime.Type.K8s: @@ -88,7 +98,7 @@ export class Queue implements Resource { } } -export interface Queue extends QueueInfra, QueueClient, Resource {} +export interface Queue extends IQueueClient, IQueueInfra, IResource {} export interface QueueInfraOptions {} export interface QueueClientOptions {} @@ -101,18 +111,18 @@ export interface QueueOptions extends QueueInfraOptions, QueueClientOptions {} In the `src/clients/aws` directory of `@plutolang/pluto`, create an `snsQueue.ts` file. The file and the class it contains are usually named after the component and the type. -In this file, the `SNSQueue` class implements the `QueueClient` interface using the AWS SDK. When calling the `PublishCommand` in the aws-sdk, the ARN of the SNS topic needs to be specified. Here, the ARN is constructed by concatenating the required parameters obtained from the environment variables, which are set in the aws `runtime.ts` of `@plutolang/pluto-infra`. +In this file, the `SNSQueue` class implements the `IQueueClient` interface using the AWS SDK. When calling the `PublishCommand` in the aws-sdk, the ARN of the SNS topic needs to be specified. Here, the ARN is constructed by concatenating the required parameters obtained from the environment variables, which are set in the aws `runtime.ts` of `@plutolang/pluto-infra`. _Currently, there is no effective solution on how to transfer the information generated during compilation to the runtime for effective use._ ```typescript import { SNSClient, PublishCommand } from "@aws-sdk/client-sns"; -import { CloudEvent, QueueClient, QueueClientOptions } from "../../queue"; +import { CloudEvent, IQueueClient, QueueClientOptions } from "../../queue"; /** * Implementation of Queue using AWS SNS. */ -export class SNSQueue implements QueueClient { +export class SNSQueue implements IQueueClient { private topicName: string; private client: SNSClient; @@ -155,7 +165,7 @@ After implementing the `SNSQueue` class, it needs to be created at runtime based ```typescript ... -public static buildClient(name: string, opts?: QueueClientOptions): QueueClient { + public static buildClient(name: string, opts?: QueueClientOptions): IQueueClient { const rtType = process.env["RUNTIME_TYPE"]; switch (rtType) { case runtime.Type.AWS: @@ -165,12 +175,67 @@ public static buildClient(name: string, opts?: QueueClientOptions): QueueClient default: throw new Error(`not support this runtime '${rtType}'`); } + } ... ``` +### Create an Abstract Base Class for the Infrastructure Implementation Class + +In the `src/` directory of `@plutolang/pluto-infra`, create a file named `queue.ts`. In this file, define the interfaces that the base class needs to implement. Also, define an abstract class for instantiating specific implementation classes based on platform and engine. The example below uses lazy loading to import corresponding specific instances, reducing library load time. + +When implementing, it's important to note that the parameters of the constructor for implementation classes and Queue's static method `createInstance` should be consistent with those of Client's constructor. + +```typescript +import { engine, runtime, utils } from "@plutolang/base"; +import { IQueueInfra QueueOptions } from "@plutolang/pluto"; +import { ImplClassMap } from "./utils"; + +// Construct a type for a class constructor. The key point is that the parameters of the constructor +// must be consistent with the client class of this resource type. Use this type to ensure that +// all implementation classes have the correct and same constructor signature. +type QueueInfraImplClass = new (name: string, options?: QueueOptions) => IQueueInfra; + +// Construct a map that contains all the implementation classes for this resource type. +// The final selection will be determined at runtime, and the class will be imported lazily. +const implClassMap = new ImplClassMap({ + [engine.Type.pulumi]: { + [runtime.Type.AWS]: async () => (await import("./aws")).SNSQueue, + [runtime.Type.K8s]: async () => (await import("./k8s")).RedisQueue, + }, +}); + +/** + * This is a factory class that provides an interface to create instances of this resource type + * based on the target platform and engine. + */ +export abstract class Queue { + /** + * Asynchronously creates an instance of the queue infrastructure class. The parameters of this function + * must be consistent with the constructor of both the client class and infrastructure class associated + * with this resource type. + */ + public static async createInstance(name: string, options?: QueueOptions): Promise { + // TODO: ensure that the resource implementation class for the simulator has identical methods as those for the cloud. + if ( + utils.currentPlatformType() === runtime.Type.Simulator && + utils.currentEngineType() === engine.Type.simulator + ) { + return new (await import("./simulator")).SimQueue(name, options) as any; + } + + return implClassMap.createInstanceOrThrow( + utils.currentPlatformType(), + utils.currentEngineType(), + name, + options + ); + } +} +``` + ### Create an Infrastructure Implementation Class -In the `src/aws` directory of `@plutolang/pluto-infra`, create an `snsQueue.ts` file. The file and the class it contains are usually named after the component and the type. In this file, the `SNSQueue` class needs to implement the `ResourceInfra` and `QueueInfra` interfaces. Typically, the creation process of the main components is defined in the constructor, and the association with other resources is built in other methods. Note that the operation names in `getPermission` should correspond to the functions in the client interface. +In the `src/aws` directory of `@plutolang/pluto-infra`, create an `snsQueue.ts` file. The file and the class it contains are usually named after the component and the type. In this file, the `SNSQueue` class needs to implement the `ResourceInfra` and `IQueueInfra` interfaces. Typically, the creation process of the main components is defined in the constructor, and the association with other resources is built in other methods. Note that the operation names in `getPermission` should correspond to the functions in the client interface. Currently, Pluto supports implementation based on Pulumi and will support more IaC tools in the future. @@ -178,7 +243,7 @@ Currently, Pluto supports implementation based on Pulumi and will support more I import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi"; import { Resource, ResourceInfra } from "@plutolang/base"; -import { QueueInfra, QueueInfraOptions } from "@plutolang/pluto/dist/queue"; +import { IQueueInfra, QueueInfraOptions } from "@plutolang/pluto"; import { Lambda } from "./lambda"; import { Permission } from "./permission"; @@ -186,7 +251,7 @@ export enum SNSOps { PUSH = "push", } -export class SNSQueue extends pulumi.ComponentResource implements ResourceInfra, QueueInfra { +export class SNSQueue extends pulumi.ComponentResource implements ResourceInfra, IQueueInfra { readonly name: string; public readonly topic: aws.sns.Topic; @@ -257,10 +322,17 @@ export class SNSQueue extends pulumi.ComponentResource implements ResourceInfra, } ``` -After implementing the `SNSQueue` class, it needs to be registered to the registry in order to instantiate the corresponding implementation class for the target platform during deployment. In the `src/aws/index.ts` of `@plutolang/pluto-infra`, export this class and add the following statement in the `register` method of `src/index.ts` to register it: +After implementing the `SNSQueue` class, it needs to be registered to the abstract base class of `Queue`. In the `src/queue.ts` of `@plutolang/pluto-infra`, add the following statement to the `implClassMap` variable: -```typescript -reg.register(runtime.Type.AWS, engine.Type.pulumi, Queue, aws.SNSQueue); +the registry in order to instantiate the corresponding implementation class for the target platform during deployment. In the `src/aws/index.ts` of `@plutolang/pluto-infra`, export this class and add the following statement in the `register` method of `src/index.ts` to register it: + +```typescript {3} +const implClassMap = new ImplClassMap({ + [engine.Type.pulumi]: { + [runtime.Type.AWS]: async () => (await import("./aws")).SNSQueue, + [runtime.Type.K8s]: async () => (await import("./k8s")).RedisQueue, + }, +}); ``` With this, the extension of the BaaS resource type is completed. @@ -271,6 +343,6 @@ Not all resources have both the Client Interface and the Infra Interface. For example, the Router resource only has the Infra Interface and does not have the Client Interface, meaning the Router type does not have any functional methods for the compute module to call during runtime. -The KVStore resource only has the Client Interface and does not have the Infra Interface, indicating that the Router type currently does not have the need to establish triggering associations with other resources. +The KVStore resource only has the Client Interface and does not have the Infra Interface, indicating that the KVStore type currently does not have the need to establish triggering associations with other resources. It is important to note that whether there is an Infra Interface or not, if it's a type of cloud resource, there needs to be an infrastructure implementation class that completes the resource creation in its constructor. diff --git a/docs/dev_guide/extend-sdk.zh-CN.md b/docs/dev_guide/extend-sdk.zh-CN.md index 927a414c..54b28e96 100644 --- a/docs/dev_guide/extend-sdk.zh-CN.md +++ b/docs/dev_guide/extend-sdk.zh-CN.md @@ -8,8 +8,9 @@ - 添加一种新的资源类型 - 在 Client SDK 中定义两类功能接口 - - 用于定义运行时功能方法的接口,称作客户端接口(Client Interface) - - 用于定义基础设施关联方法的接口,称作基础设施接口(Infra Interface) + - 定义运行时功能方法的接口,称作客户端接口(Client Interface) + - 定义基础设施关联方法的接口,称作基础设施接口(Infra Interface) + - 定义一个接口,包含编译时生成、运行时访问的属性,称作属性接口(Prop Interface) - 在 Client SDK 中定义暴露资源功能方法的资源操作界面。 - 添加资源类型的一种新实现 - 在 Client SDK 中创建一个类实现客户端接口,并通过资源类型的 `buildClient` 中绑定该实现。 @@ -31,7 +32,7 @@ Queue 目前作为消息队列,会包含一个 push 方法,用户将消息 ```typescript // The client interface is used to define the methods for accessing resources that are used during runtime. -export interface QueueClient { +export interface IQueueClientApi extends base.IResourceClientApi { push(msg: string): Promise; } ``` @@ -43,14 +44,12 @@ export interface QueueClient { Queue 作为消息队列,通常可以创建一个订阅者用于消费 Queue 中发布的消息,该创建方法即为 `subscribe`,`subscribe` 接收一个 `EventHandler` 类型对象作为参数,而 `EventHandler` 类型为一个函数类型接口,并继承了 `base.FnResource` 接口,表明 `EventHandler` 类型是一个函数计算资源类型。 ```typescript -import { FnResource } from "@plutolang/base"; - // The infra interface is used to define the methods for accessing resources that are used during compilation. -export interface QueueInfra { +export interface IQueueInfraApi extends base.IResourceInfraApi { subscribe(fn: EventHandler): void; } -export interface EventHandler extends FnResource { +export interface EventHandler extends base.FnResource { (evt: CloudEvent): Promise; } @@ -60,6 +59,14 @@ export interface CloudEvent { } ``` +### 定义属性接口 + +属性接口中定义了一组 getter 方法,这些方法对应的值,仅根据用户提供的数据是不足以得到的,例如只有在 apigateway 部署后才能知道的 router 的 url。Queue 目前没有此类属性需求,因此为空。 + +```typescript +export interface IQueueCapturedProps extends base.IResourceCapturedProps {} +``` + ### 定义暴露给用户的资源操作界面 暴露给用户的资源操作界面包含一对同名的类和接口,接口继承客户端接口和基础设施接口,而类中只定义构造函数和静态 `buildClient` 方法。这里利用了 TypeScript 的类型合并的特性,使得类虽然不实现接口方法,仍能给开发者足够的提示。 @@ -70,7 +77,10 @@ export interface CloudEvent { import { Resource, runtime } from "@plutolang/base"; import { aws, k8s } from "./clients"; -export class Queue implements Resource { +export type IQueueClient = IQueueCapturedProps & IQueueClientApi; +export type IQueueInfra = IQueueCapturedProps & IQueueInfraApi; + +export class Queue { constructor(name: string, opts?: QueueOptions) { name; opts; @@ -79,7 +89,7 @@ export class Queue implements Resource { ); } - public static buildClient(name: string, opts?: QueueClientOptions): QueueClient { + public static buildClient(name: string, opts?: QueueClientOptions): IQueueClient { const rtType = process.env["RUNTIME_TYPE"]; switch (rtType) { case runtime.Type.K8s: @@ -90,7 +100,7 @@ export class Queue implements Resource { } } -export interface Queue extends QueueInfra, QueueClient, Resource {} +export interface Queue extends IQueueClient, IQueueInfra, IResource {} export interface QueueInfraOptions {} export interface QueueClientOptions {} @@ -103,18 +113,16 @@ export interface QueueOptions extends QueueInfraOptions, QueueClientOptions {} 在 `@plutolang/pluto` 的 src/clients/aws 目录下,创建一个 `snsQueue.ts` 文件,文件与包含的类名通常以 组件名 + 类型名 来命名。 -该文件主要通过使用 AWS SDK 实现 `QueueClient` 接口,在使用 aws-sdk 调用 `PublishCommand` 时需要指定 SNS 主题的 ARN,这里采用拼接的方式构建 ARN,其中依赖的参数信息从环境变量获得,而环境变量在 `@plutolang/pluto-infra` 的 aws `runtime.ts` 设定。 - -_编译时生成的信息如何有效传输至运行时使用,目前尚未有有效的解决方案。_ +该文件主要通过使用 AWS SDK 实现 `IQueueClient` 接口,在使用 aws-sdk 调用 `PublishCommand` 时需要指定 SNS 主题的 ARN,这里采用拼接的方式构建 ARN,其中依赖的参数信息从环境变量获得,而环境变量在 `@plutolang/pluto-infra` 的 aws `runtime.ts` 设定。 ```typescript import { SNSClient, PublishCommand } from "@aws-sdk/client-sns"; -import { CloudEvent, QueueClient, QueueClientOptions } from "../../queue"; +import { CloudEvent, IQueueClient, QueueClientOptions } from "../../queue"; /** * Implementation of Queue using AWS SNS. */ -export class SNSQueue implements QueueClient { +export class SNSQueue implements IQueueClient { private topicName: string; private client: SNSClient; @@ -157,7 +165,7 @@ export class SNSQueue implements QueueClient { ```typescript ... -public static buildClient(name: string, opts?: QueueClientOptions): QueueClient { + public static buildClient(name: string, opts?: QueueClientOptions): IQueueClient { const rtType = process.env["RUNTIME_TYPE"]; switch (rtType) { case runtime.Type.AWS: @@ -167,14 +175,69 @@ public static buildClient(name: string, opts?: QueueClientOptions): QueueClient default: throw new Error(`not support this runtime '${rtType}'`); } + } ... ``` +### 创建 基础设施 基础抽象类 + +在 `@plutolang/pluto-infra` 的 `src/` 目录下,创建一个 `queue.ts`,在其中定义基础类要实现的接口,同时定义一个抽象类来根据平台与引擎实例化具体的实现类。下面实例中采用懒加载的方式导入相应具体实例,减少库的加载时间。 + +在实现时需要注意,实现类的构造函数 和 Queue 的静态方法 `createInstance` 的参数需要与 Client 实现类的构造函数参数 保持一致。 + +```typescript +import { engine, runtime, utils } from "@plutolang/base"; +import { IQueueInfra QueueOptions } from "@plutolang/pluto"; +import { ImplClassMap } from "./utils"; + +// Construct a type for a class constructor. The key point is that the parameters of the constructor +// must be consistent with the client class of this resource type. Use this type to ensure that +// all implementation classes have the correct and same constructor signature. +type QueueInfraImplClass = new (name: string, options?: QueueOptions) => IQueueInfra; + +// Construct a map that contains all the implementation classes for this resource type. +// The final selection will be determined at runtime, and the class will be imported lazily. +const implClassMap = new ImplClassMap({ + [engine.Type.pulumi]: { + [runtime.Type.AWS]: async () => (await import("./aws")).SNSQueue, + [runtime.Type.K8s]: async () => (await import("./k8s")).RedisQueue, + }, +}); + +/** + * This is a factory class that provides an interface to create instances of this resource type + * based on the target platform and engine. + */ +export abstract class Queue { + /** + * Asynchronously creates an instance of the queue infrastructure class. The parameters of this function + * must be consistent with the constructor of both the client class and infrastructure class associated + * with this resource type. + */ + public static async createInstance(name: string, options?: QueueOptions): Promise { + // TODO: ensure that the resource implementation class for the simulator has identical methods as those for the cloud. + if ( + utils.currentPlatformType() === runtime.Type.Simulator && + utils.currentEngineType() === engine.Type.simulator + ) { + return new (await import("./simulator")).SimQueue(name, options) as any; + } + + return implClassMap.createInstanceOrThrow( + utils.currentPlatformType(), + utils.currentEngineType(), + name, + options + ); + } +} +``` + ### 创建 基础设施 实现类 在 `@plutolang/pluto-infra` 的 `src/aws` 目录下,创建一个 `snsQueue.ts` 文件,文件与包含的类名通常以 组件名 + 类型名 来命名。 -在该文件中,需要实现 `ResourceInfra` 和 `QueueInfra` 接口。通常在构造函数中定义主要组件的创建过程,并在其他方法中构建与其他资源的关联。需要注意的是,`getPermission` 中的操作名称,应与客户端接口中的函数对应。 +在该文件中,需要实现 `ResourceInfra` 和 `IQueueInfra` 接口。通常在构造函数中定义主要组件的创建过程,并在其他方法中构建与其他资源的关联。需要注意的是,`getPermission` 中的操作名称,应与客户端接口中的函数对应。 目前 Pluto 支持基于 Pulumi 实现,后续将支持更多 IaC 工具。 @@ -182,7 +245,7 @@ public static buildClient(name: string, opts?: QueueClientOptions): QueueClient import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi"; import { Resource, ResourceInfra } from "@plutolang/base"; -import { QueueInfra, QueueInfraOptions } from "@plutolang/pluto/dist/queue"; +import { IQueueInfra, QueueInfraOptions } from "@plutolang/pluto"; import { Lambda } from "./lambda"; import { Permission } from "./permission"; @@ -190,7 +253,7 @@ export enum SNSOps { PUSH = "push", } -export class SNSQueue extends pulumi.ComponentResource implements ResourceInfra, QueueInfra { +export class SNSQueue extends pulumi.ComponentResource implements ResourceInfra, IQueueInfra { readonly name: string; public readonly topic: aws.sns.Topic; @@ -261,14 +324,19 @@ export class SNSQueue extends pulumi.ComponentResource implements ResourceInfra, } ``` -在实现完 `SNSQueue` 类后,需要将其注册到注册中心以实现在部署时实例化目标平台对应的实现类。在 `@plutolang/pluto-infra` 的 `src/aws/index.ts` 将该类 export,并在 `src/index.ts` 中的 `register` 方法中添加下列语句,实现注册: +在实现完 `SNSQueue` 类后,需要将其注册到 Queue 基础抽象类的映射表中, 在 `@plutolang/pluto-infra` 的 `src/queue.ts` 中,在 `implClassMap` 中添加一条记录: -```typescript -reg.register(runtime.Type.AWS, engine.Type.pulumi, Queue, aws.SNSQueue); +```typescript {3} +const implClassMap = new ImplClassMap({ + [engine.Type.pulumi]: { + [runtime.Type.AWS]: async () => (await import("./aws")).SNSQueue, + [runtime.Type.K8s]: async () => (await import("./k8s")).RedisQueue, + }, +}); ``` 至此, BaaS 资源类型的扩展就完成了。 ## 注 -并非所有资源都同时拥有客户端接口和基础设施接口,例如,Router 资源只有基础设施接口,没有客户端接口,即 Router 类型没有功能方法供计算模块在运行过程中调用;KVStroe 资源只有客户端接口,没有基础设施接口,即 Router 类型目前没有与其他资源建立触发关联的需求。需要注意的是,无论是否有基础设施接口,都需要有基础设施实现类,并在其构造函数中完成资源的创建。 +并非所有资源都同时拥有客户端接口和基础设施接口,例如,Router 资源只有基础设施接口,没有客户端接口,即 Router 类型没有功能方法供计算模块在运行过程中调用;KVStroe 资源只有客户端接口,没有基础设施接口,即 KVStore 类型目前没有与其他资源建立触发关联的需求。需要注意的是,无论是否有基础设施接口,都需要有基础设施实现类,并在其构造函数中完成资源的创建。 diff --git a/docs/documentation/concepts/sdk.en.md b/docs/documentation/concepts/sdk.en.md index cfdf43f2..13bc79ac 100644 --- a/docs/documentation/concepts/sdk.en.md +++ b/docs/documentation/concepts/sdk.en.md @@ -18,12 +18,18 @@ In Pluto, there are two types of SDKs related to the cloud platform. These two S The `@plutolang/base` library contains three basic interfaces: -1. Resource: Indicates that the class or interface is related to cloud resources. During compilation, whether an instantiated object's type implements this interface is used to determine if it is a cloud resource. -2. FnResource: Indicates that the class or interface is related to FaaS resources. During compilation, whether a function type inherits this interface is used to determine if the function is an instance of FaaS resource. -3. ResourceInfra: This interface must be implemented by infrastructure implementation classes. It is used to complete the creation of infrastructure components. +1. **IResource**: Indicates that the class or interface is related to cloud resources. During compilation, whether an instantiated object's type implements this interface is used to determine if it is a cloud resource. +2. **FnResource**: Indicates that the class or interface is related to FaaS resources. During compilation, whether a function type inherits this interface is used to determine if the function is an instance of FaaS resource. +3. **ResourceInfra**: This interface must be implemented by infrastructure implementation classes. It is used to complete the creation of infrastructure components. - `get name()`: Retrieves the basic name of the resource object, which may be different from the name of the created resource instance. - `getPermission()`: Generates the necessary permissions for calling specific operations on itself. - `postProcess()`: Some operations need to be performed only after all configuration processes are completed. These operations are placed in this function. For example, AWS ApiGateway needs to configure Deployment and Stage after setting up all routes. +4. **IResourceCapturedProps**: This interface should be extended within both the client implementaion and infrastructure implementation of a resource type. It contains some getter methods that defines the properties of the resource, which are generated at compile time and will be obtained during runtime. More details can be found in [this design document](../design/capture-value.en.md). + - For instance, the URL of a Router resource. +5. **IResourceClientApi**: This interface should be extended within the client implementation of a resource type. It contains several methods that can be called during runtime. Typically, these methods represents the function provided by the platform's specific resource type. + - For instance, the `push` method of message queue is used to publish a message to the message queue during runtime. +6. **IResourceInfraAPi**:This interface should be extended within the infrastructure implementation of a resource type. It contains several methods that can be called at compile time. Typically, these methods are employed to establish the connections between resources. + - For instance, methods such as Get and Post of the Router type are used to define the relationship between a Router resource object and a FaaS resource object. If you're looking to extend the SDKs, check out [this document](../../dev_guide/extend-sdk.en.md). diff --git a/docs/documentation/concepts/sdk.zh-CN.md b/docs/documentation/concepts/sdk.zh-CN.md index a8528dd7..d0280bdf 100644 --- a/docs/documentation/concepts/sdk.zh-CN.md +++ b/docs/documentation/concepts/sdk.zh-CN.md @@ -13,14 +13,20 @@ - 在构造方法中完成资源创建的过程,例如在 `pluto-infra.SNSQueue` 中进行 AWS SNS 组件的定义。 - 在类方法中实现资源间的关联,例如 `pluto-infra.SNSQueue` 的 `subscribe` 中通过触发器构建 SNS 与 Lambda 之间的关联。 -在 `@plutolang/base` 库中包含三个基本接口: +在 `@plutolang/base` 库中包含几个基本接口: -- Resource:表明该类或接口与云资源相关,在编译时,通过查看开发者实例化对象的类型是否实现该接口来判断是否是云资源。 -- FnResource:表明该类或接口与 FaaS 资源相关,在编译时,通过查看函数类型是否继承该接口来判断该函数是否是 FaaS 资源实例。 -- ResourceInfra:基础设施实现类时必须实现的接口,用于完成基础设施组件的创建。 +- **IResource**:表明该类或接口与云资源相关,在编译时,通过查看开发者实例化对象的类型是否实现该接口来判断是否是云资源。 +- **FnResource**:表明该类或接口与 FaaS 资源相关,在编译时,通过查看函数类型是否继承该接口来判断该函数是否是 FaaS 资源实例。 +- **ResourceInfra**:基础设施实现类时必须实现的接口,用于完成基础设施组件的创建。 - `get name()`:获取资源对象的基本名称,可能与创建的资源实例的名称不同。 - `getPermission()`: 用于生成调用自身特定操作时所需的权限。 - `postProcess()`: 存在某些操作需要待所有配置过程完成后再开始进行,将该类操作放置在函数中。例如,AWS 的 ApiGateway 需要在配置完所有路由后,再配置 Deployment 和 Stage。 +- **IResourceCapturedProps**:资源类型实例化后获得资源对象,资源对象提供用户可访问的属性值,即为资源的属性。 + - 例如,Router 资源的 URL。 +- **IResourceClientApi**:资源类型提供给用户在运行时使用的一组功能接口。 + - 例如,消息队列类型的 push 方法,用于在运行时向消息队列发布消息。 +- **IResourceInfraAPi**:资源类型提供用户用于指明资源间关系的一组功能接口。 + - 例如,Router 类型的 Get、Post 等方法,用于指定一个 Router 资源对象与 Handler 对应的 FaaS 资源对象之间的关系。 如果你想扩展 SDK,请参考[这篇文档](../../dev_guide/extend-sdk.zh-CN.md). diff --git a/docs/documentation/design/_meta.en.json b/docs/documentation/design/_meta.en.json new file mode 100644 index 00000000..31704881 --- /dev/null +++ b/docs/documentation/design/_meta.en.json @@ -0,0 +1,8 @@ +{ + "getting-started": "Getting Started", + "how-pluto-works": "How Pluto Works", + "what-problems-pluto-aims-to-address": "What Problem does Pluto Solve?", + "whats-different": "Differences between Pluto and other Products", + "concepts": "Concepts", + "design": "Design" +} diff --git a/docs/documentation/design/_meta.zh-CN.json b/docs/documentation/design/_meta.zh-CN.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/docs/documentation/design/_meta.zh-CN.json @@ -0,0 +1 @@ +{} diff --git a/docs/documentation/design/capture-value.en.md b/docs/documentation/design/capture-value.en.md index 364aa67a..079e8f4c 100644 --- a/docs/documentation/design/capture-value.en.md +++ b/docs/documentation/design/capture-value.en.md @@ -3,7 +3,9 @@ title: Runtime Access to Values Generated by Infrastructure Code at Compile Time date: 2024-01-08 --- -Pluto programs are split into multiple functions at compile time, which are then deployed to cloud platforms by [adapters](../concepts/adapter.zh-CN.md). The most common deployment method is: a set of infrastructure definition code (hereafter referred to as IaC code) is generated by the [generator](../concepts/generator.zh-CN.md), and then the adapter executes the IaC code using the corresponding IaC engine. Alternatively, for runtime environments that do not support IaC engines (such as local simulation environments), the adapter may directly call the APIs of the runtime environment to build the infrastructure environment and deploy all functions of the Pluto program based on the architecture reference. +# Runtime Access to Values Generated by Infrastructure Code at Compile Time + +Pluto programs are split into multiple functions at compile time, which are then deployed to cloud platforms by [adapters](../concepts/adapter.en.md). The most common deployment method is: a set of infrastructure definition code (hereafter referred to as IaC code) is generated by the [generator](../concepts/generator.en.md), and then the adapter executes the IaC code using the corresponding IaC engine. Alternatively, for runtime environments that do not support IaC engines (such as local simulation environments), the adapter may directly call the APIs of the runtime environment to build the infrastructure environment and deploy all functions of the Pluto program based on the architecture reference. After a Pluto program is deployed, the deployed function instances access certain methods or properties of resource objects at runtime to interact with resource instances. However, the values of resource object properties may be returned by the platform after executing the IaC code or calling the runtime environment API, such as the URL of ApiGateway. These property values cannot be obtained based solely on the information provided by the user in the program. Therefore, a mechanism needs to be built to allow runtime functions to access values generated by infrastructure code at compile time. diff --git a/docs/documentation/design/capture-value.zh-CN.md b/docs/documentation/design/capture-value.zh-CN.md index 74c5f842..66555f92 100644 --- a/docs/documentation/design/capture-value.zh-CN.md +++ b/docs/documentation/design/capture-value.zh-CN.md @@ -3,6 +3,8 @@ title: 运行时函数访问基础设施代码在编译时生成的值 date: 2024-01-08 --- +# 运行时函数访问基础设施代码在编译时生成的值 + Pluto 程序在编译时会被拆分成多个函数,然后由[适配器](../concepts/adapter.zh-CN.md)部署到云平台上。第一种部署方式,也是最常用的部署方式就是:先由[生成器](../concepts/generator.zh-CN.md)生成一份基础设施定义代码(下称 IaC 代码),然后由适配器调用相应 IaC 引擎执行 IaC 代码。其次,第二种部署方式是:针对不支持 IaC 引擎的运行时环境(如本地模拟环境),适配器可能会采用根据参考架构直接调用运行时环境的 API,来构建基础设施环境,部署 Pluto 程序的所有函数。 Pluto 程序被部署后,所部署的函数实例会在运行时访问资源对象的一些方法或属性,来与资源实例交互。但是,资源对象属性的值可能是在执行 IaC 代码或调用运行时环境 API 后,运行时环境返回的值,如 ApiGateway 的 URL。仅凭用户在程序中提供的信息无法获取到这些属性值。因此,需要构建一个机制来使得基础设施代码在编译时生成的值能够被运行时函数访问到。