Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move the selection of specific implementation classes to the static method within the base classes #106

Open
jianzs opened this issue Dec 22, 2023 · 1 comment
Labels
enhancement New feature or request generator Generator sdk Client SDK and Infra SDK

Comments

@jianzs
Copy link
Contributor

jianzs commented Dec 22, 2023

During the Proof of Concept (PoC) phase, specific Client implementation classes were created through the resource type's buildClient method, while specific Infra implementation classes were registered in the Registry and then retrieved by querying the Registry based on platform and engine type. Both of these methods introduced additional cognitive load for SDK developers, requiring an understanding of the specific creation methods and adding extra logic to Pluto's implementation. Simplification in this area could be explored.

// Resource Client 
export class Queue implements Resource {
  constructor(name: string, opts?: QueueOptions) {
    name;
    opts;
    throw new Error(
      "Cannot instantiate this class, instead of its subclass depending on the target runtime."
    );
  }

  public static buildClient(name: string, opts?: QueueClientOptions): QueueClient {
    const rtType = process.env["RUNTIME_TYPE"];
    switch (rtType) {
      case runtime.Type.AWS:
        return new aws.SNSQueue(name, opts);
      case runtime.Type.K8s:
        return new k8s.RedisQueue(name, opts);
      case runtime.Type.Simulator:
        if (!process.env.PLUTO_SIMULATOR_URL) throw new Error("PLUTO_SIMULATOR_URL doesn't exist");
        return simulator.makeSimulatorClient(process.env.PLUTO_SIMULATOR_URL!, name);
      default:
        throw new Error(`not support this runtime '${rtType}'`);
    }
  }
}

// Resource Infra
export function register(reg: Registry) {
  reg.register(runtime.Type.AWS, engine.Type.pulumi, Router, aws.ApiGatewayRouter);
  reg.register(runtime.Type.AWS, engine.Type.pulumi, KVStore, aws.DynamoKVStore);
  reg.register(runtime.Type.AWS, engine.Type.pulumi, Queue, aws.SNSQueue);
  reg.register(runtime.Type.AWS, engine.Type.pulumi, Schedule, aws.CloudWatchSchedule);
  reg.register(runtime.Type.AWS, engine.Type.pulumi, "FnResource", aws.Lambda);
  reg.register(runtime.Type.AWS, engine.Type.pulumi, Tester, aws.Tester);
}

We can place the logic for selecting the specific implementation class within the constructor, allowing SDK developers to manage this process. By eliminating Registry and buildClient, Pluto would no longer have to add extra logic for handling type conversion and could instead focus solely on maintaining user code.

We'd like to instantiate the implementation classes asynchronously, which can help cut down on package loading costs. This process will be encapsulated within an asynchronous function, often referred to as a 'lazy importing' function. However, in JavaScript, it's not feasible to call an async function within a constructor.

So we've come up with a solution where each resource has an abstract base class at the root of the infra SDK and includes a static async method named createInstance. This method serves to create instances of resource infrastructure implementation classes based on the target platform and engine.

Not only does this strategy streamline operations, but it also allows SDK developers to concentrate more effectively on their tasks.

The stipulation is that the parameters for both the client implementation class and infrastructure implementation class of a resource, along with those of the createInstance method from its base class, must all be consistent.

abstract class Queue {
    public static async createInstance(name, opts) {
      if (currentPlatform == "AWS") {
          return new SNSQueue(name, opts);
        } else if (...) {
           // ...
        }
    }
}

class SNSQueue {
    public subscribe(handler: any) {
        // do something...
    }
}
@jianzs jianzs added enhancement New feature or request generator Generator sdk Client SDK and Infra SDK labels Dec 22, 2023
@jianzs jianzs changed the title Move the selection of specific implementation classes to the constructor of base class Move the selection of specific implementation classes to the static method within the base classes Jan 11, 2024
@jianzs
Copy link
Contributor Author

jianzs commented Jan 11, 2024

After #122, the instance of the resource infrastructure implementation class will be instantiated asynchronously. The creation process is completed within the createInstance method.

However, instances of the resource client are still created synchronously. This is because users may instantiate a resource object in global scope. We can't simply change constructor invocation to asynchronous method buildClient. In CommonJS, it's not practical to call an asynchronous function in global scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request generator Generator sdk Client SDK and Infra SDK
Projects
None yet
Development

No branches or pull requests

1 participant