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

ENG-0000 - Refresh + API Client Architecture #234

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mcnielsen
Copy link
Contributor

@mcnielsen mcnielsen commented Aug 25, 2022

Summary

  • Updated type script to 4.7.x
  • Updated other packages to corresponding latest version
  • AlApiClient renamed to AlXHRAdapter for accuracy
  • AlDefaultClient renamed to AlRootClient (again, for accuracy)
  • Added @ServiceClient decorator and AlBaseServiceClient, allowing JIT
    service instantiation and better tree shaking
  • Updated AIMSClient and SubscriptionsClient to use new client model
  • Retired some obsolete content

Client Architecture:

Previously, our API Client architecture has consisted of declaring the
client class and then immediately instantiating it as a global variable.
In practice, this means that clients a) cannot be tree shaken or bundled
outside of the main bundle, and b) every client must by compiled and
instantiated before application bootstrap. This is dumb.

The new model uses a decorator to identify classes that represent a
client. The decorator stores the class's constructor and some default
settings for it into a dictionary, which can be used to instantiate the
client on-demand.

For example:

@ServiceClient( {
    service_name: "gestalt",
    service_stack: AlLocation.GestaltAPI,
    version: 1
} )
export class AlsGestalt extends AlBaseServiceClient {
    ...
}

Or

@ServiceClient( {
    service_name: "iris",
    version: 'v3',
    residencyAware: true
} )
export class AlsIris extends AlBaseServiceClient {
    ...
}

These classes do not need to be instantiated until they are actually
needed. Additional, the properties provided to the ServiceClient
decorator as used as defaults, and the AlBaseServiceClient provides
convenience get, put, post, delete, and request methods to
facilitate extremely minimal implementations.

Nomenclature:

Client classes should begin with an "Als" prefix, and be stored with a
.service-client.ts extension.

@mcnielsen mcnielsen marked this pull request as draft August 25, 2022 22:55
@al-cibot
Copy link

CI Service Job Number 606 Logs - FAILURE

alps ci job-logs --organization alertlogic --repository nepal-core --job-num 606 -g

Stages Run:

  • PR Test

@mcnielsen
Copy link
Contributor Author

test it

@al-cibot
Copy link

CI Service Job Number 607 Logs - FAILURE

alps ci job-logs --organization alertlogic --repository nepal-core --job-num 607 -g

Stages Run:

  • PR Test

@mcnielsen mcnielsen force-pushed the api-client-architecture branch from 5d721b8 to d47c5f7 Compare August 25, 2022 23:19
@al-cibot
Copy link

CI Service Job Number 608 Logs - FAILURE

alps ci job-logs --organization alertlogic --repository nepal-core --job-num 608 -g

Stages Run:

  • PR Test

- Updated typescript to 4.7.x
- Updated other packages to corresponding latest version
- AlApiClient renamed to AlXHRAdapter for accuracy
- AlDefaultClient renamed to AlRootClient (again, for accuracy)
- Added @ServiceClient decorator and AlBaseServiceClient, allowing JIT
  service instantiation and better tree shaking
- Updated AIMSClient and SubscriptionsClient to use new client model
- Retired some obsolete content

Client Architecture:

Previously, our API Client architecture has consisted of declaring the
client class and then immediately instantiating it as a global variable.
In practice, this means that clients a) cannot be tree shaken or bundled
outside of the main bundle, and b) every client must by compiled and
instantiated before application bootstrap.  This is dumb.

The new model uses a decorator to identify classes that represent a
client.  The decorator stores the class's constructor and some default
settings for it into a dictionary, which can be used to instantiate the
client on-demand.

For example:

```
@ServiceClient( {
    service_name: "gestalt",
    service_stack: AlLocation.GestaltAPI,
    version: 1
} )
export class AlsGestalt extends AlBaseServiceClient {
    ...
}
```

Or

```
@ServiceClient( {
    service_name: "iris",
    version: 'v3',
    residencyAware: true
} )
export class AlsIris extends AlBaseServiceClient {
    ...
}
```

These classes do not need to be instantiated until they are actually
needed. Additional, the properties provided to the ServiceClient
decorator as used as defaults, and the AlBaseServiceClient provides
convenience `get`, `put`, `post`, `delete`, and `request` methods to
facilitate extremely minimal implementations.

Nomenclature:

Client classes should begin with an "Als" prefix, and be stored with a
.service-client.ts extension.
@mcnielsen mcnielsen force-pushed the api-client-architecture branch from d47c5f7 to 46ebab6 Compare August 25, 2022 23:41
@al-cibot
Copy link

Unit Test Coverage Report

branches
64.35% 1105/1717
branchesTrue
100% 0/0
functions
72% 450/625
lines
73.2% 2054/2806
statements
73.42% 2130/2901

@al-cibot
Copy link

CI Service Job Number 609 Logs - SUCCESS

alps ci job-logs --organization alertlogic --repository nepal-core --job-num 609 -g

Stages Run:

  • PR Test

Copy link
Contributor

@parky128 parky128 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty damn cool, you really are a 🧙‍♂️ aren't you?

I'm loving how those convenience methods for get, post, etc mean you now dont have to repeat yourself adding the service name, stack and versions.

In terms of consumption it looks like its just a case of changing something like

import {DashboardsClient} from '@al/dashboards'
...
DashboardsClient.getUserDashboardItem(...)

to be

import {
    AlRootClient,
    AlsDashboards,
} from "../core";
...
AlRootClient.getClient( AlsDashboards ).getUserDashboardItem(...)

I guess to help with adopting this new approach, where our guys are used to importing the global instances, they could just assign the result of getClient into a variable in say their component\service constructors and reference it accordingly.

const dashboardsClient = AlRootClient.getClient(AlsDashboards)
dashboardsClient.getUserDashboardItem(...)

Im also assuming for the non core clients, so those we currently have as separate packages, these would now get folded into the main src/client directory and we no longer publish individual libs?

As for next steps, do you want any assistance with migrating rest of the codebase and then we try and suck into a feature branch of magma, or you already on that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants