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

feat(appsync): add ApiCache L2 construct and addCache method #31174

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
136 changes: 136 additions & 0 deletions packages/aws-cdk-lib/aws-appsync/lib/api-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { Construct } from 'constructs';
import { CfnApiCache } from './appsync.generated';

/**
* enum with all Api Caching Behavior values
*/
export enum CacheBehavior {
/*
* FULL_REQUEST_CACHING: All requests are fully cached.
*/
FULL_REQUEST_CACHING = 'FULL_REQUEST_CACHING',
/**
* PER_RESOLVER_CACHING: Individual resolvers that you specify are cached.
*/
PER_RESOLVER_CACHING = 'PER_RESOLVER_CACHING',
}

/**
* enum with all Health Metrics Configuration options
*/
export enum HealthMetrics {
/**
* ENABLE CloudWatch metrics on cache
*/
ENABLED = 'ENABLED',
/**
* DISABLE CloudWatch metrics on cache
*/
DISABLED = 'DISABLED',
}

/**
* enum with all cache instance type values
*/
export enum CacheType {
/**
* SMALL cache instance type
*/
SMALL = 'SMALL',
/**
* MEDIUM cache instance type
*/
MEDIUM = 'MEDIUM',
/**
* LARGE cache instance type
*/
LARGE = 'LARGE',
/**
* XLARGE cache instance type
*/
XLARGE = 'XLARGE',
/**
* LARGE_2X cache instance type
*/
LARGE_2X = 'LARGE_2X',
/**
* LARGE_4X cache instance type
*/
LARGE_4X = 'LARGE_4X',
/**
* LARGE_8X cache instance type (not available in all regions)
*/
LARGE_8X = 'LARGE_8X ',
/**
* LARGE_12X cache instance type
*/
LARGE_12X = 'LARGE_12X',
}

/**
* Base properties for an Api Cache
*/
export interface ApiCacheBaseProps {
/**
* Caching behavior
*/
readonly apiCachingBehavior: CacheBehavior;

/**
* At-rest encryption flag for cache
*
* @default - idk
TonySherman marked this conversation as resolved.
Show resolved Hide resolved
*/
readonly atRestEncryptionEnabled?: boolean;
/**
* Controls how cache health metrics will be emitted to CloudWatch
* Metrics will be recorded by API ID
*
* @default - idk
*/
readonly healthMetricsConfig?: HealthMetrics;
/**
* Transit encryption flag when connecting to cache
*
* @default - idk
*/
readonly transitEncryptionEnabled?: boolean;
/**
* TTL in seconds for cache entries. Valid values are 1–3,600 seconds.
*
*/
readonly ttl: number;
/**
* The cache instance type
*/
readonly type: CacheType;
}

/**
* Properties for an Api Cache
*/
export interface ApiCacheProps extends ApiCacheBaseProps {
/**
* The GraphQL API ID.
*/
readonly apiId: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it should be

readonly api: IGraphqlApi;

}

/**
* Cache for a GraphQL API
*/
export class ApiCache extends Construct {
Copy link
Contributor

Choose a reason for hiding this comment

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

L2 construct should extends Resource implements IApiCache. You should export IApiCache as well.

constructor(scope: Construct, id: string, props: ApiCacheProps) {
super(scope, id);

new CfnApiCache(this, 'Resource', {
apiId: props.apiId,
apiCachingBehavior: props.apiCachingBehavior,
atRestEncryptionEnabled: props.atRestEncryptionEnabled,
healthMetricsConfig: props.healthMetricsConfig,
transitEncryptionEnabled: props.transitEncryptionEnabled,
ttl: props.ttl,
type: props.type,
});
}
}
19 changes: 19 additions & 0 deletions packages/aws-cdk-lib/aws-appsync/lib/graphqlapi-base.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApiCache, ApiCacheBaseProps } from './api-cache';
import {
DynamoDbDataSource,
HttpDataSource,
Expand Down Expand Up @@ -597,4 +598,22 @@ export abstract class GraphqlApiBase extends Resource implements IGraphqlApi {
public grantSubscription(grantee: IGrantable, ...fields: string[]): Grant {
return this.grant(grantee, IamResource.ofType('Subscription', ...fields), 'appsync:GraphQL');
}

/**
* Creates an API Cache for this GraphQLApi
*
* @param id The id for this resource
* @param props The configuration needed for the API Cache resource
*/
public addCache(id: string, props: ApiCacheBaseProps): ApiCache {
return new ApiCache(this, id, {
apiId: this.apiId,
apiCachingBehavior: props.apiCachingBehavior,
atRestEncryptionEnabled: props.atRestEncryptionEnabled,
healthMetricsConfig: props.healthMetricsConfig,
transitEncryptionEnabled: props.transitEncryptionEnabled,
ttl: props.ttl,
type: props.type,
});
}
}
1 change: 1 addition & 0 deletions packages/aws-cdk-lib/aws-appsync/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from './graphqlapi-base';
export * from './code';
export * from './runtime';
export * from './source-api-association';
export * from './api-cache';
51 changes: 51 additions & 0 deletions packages/aws-cdk-lib/aws-appsync/test/appsync-api-cache.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as path from 'path';
import { Template } from '../../assertions';
import * as cdk from '../../core';
import * as appsync from '../lib';

// GLOBAL GIVEN
let stack: cdk.Stack;
let api: appsync.GraphqlApi;
let cache: appsync.ApiCache;
beforeEach(() => {
stack = new cdk.Stack();
api = new appsync.GraphqlApi(stack, 'baseApi', {
name: 'api',
schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')),
});
});

describe('Api Cache configuration', () => {
test('API cache produces AWS::AppSync::ApiCache', () => {
cache = new appsync.ApiCache(stack, 'baseApiCache', {
apiId: api.apiId,
apiCachingBehavior: appsync.CacheBehavior.FULL_REQUEST_CACHING,
type: appsync.CacheType.LARGE,
ttl: 60,
});

Template.fromStack(stack).hasResourceProperties('AWS::AppSync::ApiCache', {
Type: 'LARGE',
Ttl: 60,
ApiCachingBehavior: 'FULL_REQUEST_CACHING',
ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] },
});
});
});

describe('Add a Cache to a GraphQL API resource', () => {
test('API cache gets added to api with addCache function', ()=> {
api.addCache('ApiCache', {
apiCachingBehavior: appsync.CacheBehavior.PER_RESOLVER_CACHING,
type: appsync.CacheType.LARGE,
ttl: 360,
});

Template.fromStack(stack).hasResourceProperties('AWS::AppSync::ApiCache', {
Type: 'LARGE',
Ttl: 360,
ApiCachingBehavior: 'PER_RESOLVER_CACHING',
ApiId: { 'Fn::GetAtt': ['baseApiCDA4D43A', 'ApiId'] },
});
});
});
Loading