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(gamelift): add MatchmakingConfiguration L2 Construct for GameLift #23326

Merged
merged 20 commits into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b5b0257
Adding matchmaking configuration construct
stevehouel Nov 24, 2022
c3af54a
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 6, 2022
769f664
Adding MatchmakingConfiguration constructs for GameLift
stevehouel Dec 7, 2022
81a4650
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 8, 2022
1f6338f
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 8, 2022
f2a816f
Adding GameSessionQueue entity and fixing some typos.
stevehouel Dec 8, 2022
be0adfb
Add MatchmakingConfiguration L2 constructs and related tests
stevehouel Dec 13, 2022
e74d031
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 13, 2022
20f0256
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 14, 2022
de74f62
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 14, 2022
cd90aaa
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 14, 2022
c3a3b3b
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 15, 2022
e43609e
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 15, 2022
74e2b9b
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 19, 2022
775fbf7
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Dec 20, 2022
e5aeab4
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Jan 3, 2023
74d0c6b
fix formatting
stevehouel Jan 3, 2023
f9e7b44
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Jan 3, 2023
463fb0f
Merge branch 'main' into houes/rfc-436-matchmakingconf
stevehouel Jan 3, 2023
bf74937
Merge branch 'main' into houes/rfc-436-matchmakingconf
mergify[bot] Jan 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions packages/@aws-cdk/aws-gamelift/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,44 @@ configuration or game server fleet management system.

## GameLift FlexMatch

### Defining a Matchmaking configuration

FlexMatch is available both as a GameLift game hosting solution (including
Realtime Servers) and as a standalone matchmaking service. To set up a
FlexMatch matchmaker to process matchmaking requests, you have to create a
matchmaking configuration based on a RuleSet.

More details about matchmaking ruleSet are covered [below](#matchmaking-ruleset).

There is two types of Matchmaking configuration:

Through a game session queue system to let FlexMatch forms matches and uses the specified GameLift queue to start a game session for the match.

```ts
declare const queue: gamelift.GameSessionQueue;
declare const ruleSet: gamelift.MatchmakingRuleSet;

new gamelift.QueuedMatchmakingConfiguration(this, 'QueuedMatchmakingConfiguration', {
matchmakingConfigurationName: 'test-queued-config-name',
gameSessionQueues: [queue],
ruleSet: ruleSet,
});
```

Or through a standalone version to let FlexMatch forms matches and returns match information in an event.

```ts
declare const ruleSet: gamelift.MatchmakingRuleSet;

new gamelift.StandaloneMatchmakingConfiguration(this, 'StandaloneMatchmaking', {
matchmakingConfigurationName: 'test-standalone-config-name',
ruleSet: ruleSet,
});
```


More details about Game session queue are covered [below](#game-session-queue).

### Matchmaking RuleSet

Every FlexMatch matchmaker must have a rule set. The rule set determines the
Expand Down
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-gamelift/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export * from './game-server-group';
export * from './ingress-rule';
export * from './fleet-base';
export * from './build-fleet';
export * from './matchmaking-configuration';
export * from './queued-matchmaking-configuration';
export * from './standalone-matchmaking-configuration';
export * from './game-session-queue';
export * from './matchmaking-ruleset';
export * from './matchmaking-ruleset-body';
Expand Down
286 changes: 286 additions & 0 deletions packages/@aws-cdk/aws-gamelift/lib/matchmaking-configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
import * as sns from '@aws-cdk/aws-sns';
import * as cdk from '@aws-cdk/core';
import { Construct } from 'constructs';
import { IMatchmakingRuleSet } from '.';

/**
* A set of custom properties for a game session, formatted as key-value pairs.
* These properties are passed to a game server process with a request to start a new game session.
*
* This parameter is not used for Standalone FlexMatch mode.
*
* @see https://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-sdk-server-api.html#gamelift-sdk-server-startsession
*/
export interface GameProperty {
/**
* The game property identifier.
*/
readonly key: string;
/**
* The game property value.
*/
readonly value: string;
}

/**
* Represents a Gamelift matchmaking configuration
*/
export interface IMatchmakingConfiguration extends cdk.IResource {
/**
* The name of the matchmaking configuration.
*
* @attribute
*/
readonly matchmakingConfigurationName: string;
stevehouel marked this conversation as resolved.
Show resolved Hide resolved

/**
* The ARN of the matchmaking configuration.
*
* @attribute
*/
readonly matchmakingConfigurationArn: string;

/**
* The notification target for matchmaking events
*
* @attribute
*/
readonly notificationTarget?: sns.ITopic;


/**
* Return the given named metric for this matchmaking configuration.
*/
metric(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Matchmaking requests currently being processed or waiting to be processed.
*/
metricCurrentTickets(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* For matchmaking configurations that require acceptance, the potential matches that were accepted since the last report.
*/
metricMatchesAccepted(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Potential matches that were created since the last report.
*/
metricMatchesCreated(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Matches that were successfully placed into a game session since the last report.
*/
metricMatchesPlaced(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* For matchmaking configurations that require acceptance, the potential matches that were rejected by at least one player since the last report.
*/
metricMatchesRejected(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* Players in matchmaking tickets that were added since the last report.
*/
metricPlayersStarted(props?: cloudwatch.MetricOptions): cloudwatch.Metric;

/**
* For matchmaking requests that were put into a potential match before the last report,
* the amount of time between ticket creation and potential match creation.
*
* Units: seconds
*/
metricTimeToMatch(props?: cloudwatch.MetricOptions): cloudwatch.Metric;
}

/**
* A full specification of a matchmaking configuration that can be used to import it fluently into the CDK application.
*/
export interface MatchmakingConfigurationAttributes {
/**
* The ARN of the Matchmaking configuration
*
* At least one of `matchmakingConfigurationArn` and `matchmakingConfigurationName` must be provided.
*
* @default derived from `matchmakingConfigurationName`.
*/
readonly matchmakingConfigurationArn?: string;

/**
* The identifier of the Matchmaking configuration
*
* At least one of `matchmakingConfigurationName` and `matchmakingConfigurationArn` must be provided.
*
* @default derived from `matchmakingConfigurationArn`.
*/
stevehouel marked this conversation as resolved.
Show resolved Hide resolved
readonly matchmakingConfigurationName?: string;

/**
* An SNS topic ARN that is set up to receive matchmaking notifications.
*
* @see https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-notification.html
*
* @default no notification target binded to imported ressource
*/
readonly notificationTarget?: sns.ITopic;
}

/**
* Properties for a new Gamelift matchmaking configuration
*/
export interface MatchmakingConfigurationProps {

/**
* A unique identifier for the matchmaking configuration.
* This name is used to identify the configuration associated with a matchmaking request or ticket.
*/
readonly matchmakingConfigurationName: string;

/**
* A human-readable description of the matchmaking configuration.
*
* @default no description is provided
*/
readonly description?: string;

/**
* A flag that determines whether a match that was created with this configuration must be accepted by the matched players.
* With this option enabled, matchmaking tickets use the status `REQUIRES_ACCEPTANCE` to indicate when a completed potential match is waiting for player acceptance.
*
* @default Acceptance is not required
*/
readonly requireAcceptance?: boolean;

/**
* The length of time (in seconds) to wait for players to accept a proposed match, if acceptance is required.
*
* @default 300 seconds
*/
readonly acceptanceTimeout?: cdk.Duration;

/**
* Information to add to all events related to the matchmaking configuration.
*
* @default no custom data added to events
*/
readonly customEventData?: string;

/**
* An SNS topic ARN that is set up to receive matchmaking notifications.
*
* @see https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-notification.html
*
* @default no notification target
*/
readonly notificationTarget?: sns.ITopic;

/**
* The maximum duration, that a matchmaking ticket can remain in process before timing out.
* Requests that fail due to timing out can be resubmitted as needed.
*
* @default 300 seconds
*/
readonly requestTimeout?: cdk.Duration;

/**
* A matchmaking rule set to use with this configuration.
*
* A matchmaking configuration can only use rule sets that are defined in the same Region.
*/
readonly ruleSet: IMatchmakingRuleSet;
}

/**
* Base class for new and imported GameLift Matchmaking configuration.
*/
export abstract class MatchmakingConfigurationBase extends cdk.Resource implements IMatchmakingConfiguration {


/**
* Import an existing matchmaking configuration from its attributes.
*/
static fromMatchmakingConfigurationAttributes(scope: Construct, id: string, attrs: MatchmakingConfigurationAttributes): IMatchmakingConfiguration {
if (!attrs.matchmakingConfigurationName && !attrs.matchmakingConfigurationArn) {
throw new Error('Either matchmakingConfigurationName or matchmakingConfigurationArn must be provided in MatchmakingConfigurationAttributes');
}
const matchmakingConfigurationName = attrs.matchmakingConfigurationName ??
cdk.Stack.of(scope).splitArn(attrs.matchmakingConfigurationArn!, cdk.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
stevehouel marked this conversation as resolved.
Show resolved Hide resolved

if (!matchmakingConfigurationName) {
throw new Error(`No matchmaking configuration name found in ARN: '${attrs.matchmakingConfigurationArn}'`);
}
stevehouel marked this conversation as resolved.
Show resolved Hide resolved

const matchmakingConfigurationArn = attrs.matchmakingConfigurationArn ?? cdk.Stack.of(scope).formatArn({
service: 'gamelift',
resource: 'matchmakingconfiguration',
resourceName: attrs.matchmakingConfigurationName,
arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME,
});
class Import extends MatchmakingConfigurationBase {
public readonly matchmakingConfigurationName = matchmakingConfigurationName!;
public readonly matchmakingConfigurationArn = matchmakingConfigurationArn;
public readonly notificationTarget = attrs.notificationTarget;

constructor(s: Construct, i: string) {
super(s, i, {
environmentFromArn: matchmakingConfigurationArn,
});
}
}
return new Import(scope, id);
}

/**
* The Identifier of the matchmaking configuration.
*/
public abstract readonly matchmakingConfigurationName: string;
/**
* The ARN of the matchmaking configuration.
*/
public abstract readonly matchmakingConfigurationArn: string;

/**
* The notification target for matchmaking events
*/
public abstract readonly notificationTarget?: sns.ITopic;

metric(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return new cloudwatch.Metric({
namespace: 'AWS/GameLift',
metricName: metricName,
dimensionsMap: {
MatchmakingConfigurationName: this.matchmakingConfigurationName,
},
...props,
}).attachTo(this);
}

metricCurrentTickets(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('CurrentTickets', props);
}

metricMatchesAccepted(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('MatchesAccepted', props);
}

metricMatchesCreated(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('MatchesCreated', props);
}

metricMatchesPlaced(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('MatchesPlaced', props);
}

metricMatchesRejected(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('MatchesRejected', props);
}

metricPlayersStarted(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('PlayersStarted', props);
}

metricTimeToMatch(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('TimeToMatch', props);
}

}
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-gamelift/lib/matchmaking-ruleset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export abstract class MatchmakingRuleSetBase extends cdk.Resource implements IMa
namespace: 'AWS/GameLift',
metricName: metricName,
dimensionsMap: {
FleetId: this.matchmakingRuleSetName,
MatchmakingRuleSetName: this.matchmakingRuleSetName,
stevehouel marked this conversation as resolved.
Show resolved Hide resolved
},
...props,
}).attachTo(this);
Expand Down
Loading