Skip to content
This repository was archived by the owner on Oct 6, 2022. It is now read-only.
This repository was archived by the owner on Oct 6, 2022. It is now read-only.

API design and consistancy #20

@quinchs

Description

@quinchs

Summary

The API design for creating, managing, and using clients differ from other EdgeDB drivers. The goal is to make a driver that is easy to switch to from other drivers.

Current Design

The current clients follow an abstraction design pattern to allow for user-based abstraction as well as easy drop-in client types for pooling.

Client hierarchy:

image

Note

The client pool does not have direct access to the type of client its using, its sole job is to manage the pool of clients based on the configuration.

API

Terminology

  • Client Pool: A pool of clients that can be used to communicate with the database.
  • Client Instance: A single connection to the database, whether that be tcp, http, etc.

Functionality

The client pool (EdgeDBClient class) is not lazy in how it instantiates clients, clients Connect method will be called when the user requests a client.

Example

var client = new EdgeDBClient(...);

await using var rawClient = await client.GetOrCreateClientAsync();

Method logic

edgedb_client drawio

Pooled client lifetime

A client instance returned from a client pool will be added back into the client pool apon the disposal of the client instance class. This is done by the IDisposable interface.

await using (var rawClient = await client.GetOrCreateClientAsync())
{
  // preform operations with the client instance
}

// 'rawClient' falls out of scope and the 'using' statement calls the 'DisposeAsync' method, this returns the client instance back to the client pool

Proposed design

The proposed design for the client pool is as follows:

  • Clients are lazily instantiated, when the user requests a client instance, that instance is only connected apon the first query operation.
  • GetOrCreateClientAsync will be renamed to CreateClient
  • Client instances connection methods are blocked by a client pool. If the pool is full, the connect method will wait until a free spot is available.
  • Pooling logic is done at the query step, since the client is connected at that step as well.

Example

using var rawClient = client.CreateClient(); // create a client instance
var result = await rawClient.QueryAsync(...); // 'QueryAsync' will wait for the pool to allow connection, connect, and then query

Caveats

  • User can instantiate multiple client instance classes which can lead to poor memory usage compared to current design.
  • Client instance classes have a short lifetime and arn't resused.
  • Users don't implicitly know that the execute methods of a client also preform pooling and connection operations.

cc @colinhacks @1st1

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions