constructor()

in src/lib/stack.ts [15:166]


  constructor(scope: Construct, id: string, props: StackProps = {}) {
    super(scope, id, props);

    const accessLogBucket = new Bucket(this, 'BucketAccessLog', {
      encryption: BucketEncryption.S3_MANAGED,
      removalPolicy: RemovalPolicy.RETAIN,
      serverAccessLogsPrefix: 'accessLogBucketAccessLog',
    });

    const vpcId = this.node.tryGetContext('vpcId');
    const vpc = vpcId ? Vpc.fromLookup(this, 'FraudDetectionVpc', {
      vpcId: vpcId === 'default' ? undefined : vpcId,
      isDefault: vpcId === 'default' ? true : undefined,
    }) : (() => {
      const newVpc = new Vpc(this, 'FraudDetectionVpc', {
        maxAzs: 2,
        gatewayEndpoints: {
          s3: {
            service: GatewayVpcEndpointAwsService.S3,
          },
          dynamodb: {
            service: GatewayVpcEndpointAwsService.DYNAMODB,
          },
        },
      });
      newVpc.addFlowLog('VpcFlowlogs', {
        destination: FlowLogDestination.toS3(accessLogBucket, 'vpcFlowLogs'),
      });
      return newVpc;
    })();
    if (vpc.privateSubnets.length < 1) {
      throw new Error('The VPC must have PRIVATE subnet.');
    }

    const bucket = new Bucket(this, 'FraudDetectionDataBucket', {
      encryption: BucketEncryption.S3_MANAGED,
      removalPolicy: RemovalPolicy.RETAIN,
      serverAccessLogsBucket: accessLogBucket,
      serverAccessLogsPrefix: 'dataBucketAccessLog',
    });

    const neptuneInstanceType = new CfnParameter(this, 'NeptuneInstaneType', {
      description: 'Instance type of graph database Neptune',
      type: 'String',
      allowedValues: [
        'db.r5.xlarge',
        'db.r5.2xlarge',
        'db.r5.4xlarge',
        'db.r5.8xlarge',
        'db.r5.12xlarge',
      ],
      default: 'db.r5.xlarge',
    });

    const dataPrefix = 'fraud-detection/';
    const replicaCount = this.node.tryGetContext('NeptuneReplicaCount');
    const neptuneInfo = this._createGraphDB_Neptune(vpc, bucket, dataPrefix,
      neptuneInstanceType.valueAsString,
      (replicaCount === undefined) ? 1 : parseInt(replicaCount),
    );

    const dataColumnsArg = {
      id_cols: 'card1,card2,card3,card4,card5,card6,ProductCD,addr1,addr2,P_emaildomain,R_emaildomain',
      cat_cols: 'M1,M2,M3,M4,M5,M6,M7,M8,M9',
      dummies_cols: 'M1_F,M1_T,M2_F,M2_T,M3_F,M3_T,M4_M0,M4_M1,M4_M2,M5_F,M5_T,M6_F,M6_T,M7_F,M7_T,M8_F,M8_T,M9_F,M9_T',
    };

    const trainingStack = new TrainingStack(this, 'training', {
      vpc,
      bucket,
      accessLogBucket,
      neptune: neptuneInfo,
      dataPrefix,
      dataColumnsArg: dataColumnsArg,
    });

    const tranQueue = new Queue(this, 'TransQueue', {
      contentBasedDeduplication: true,
      encryption: QueueEncryption.KMS_MANAGED,
      fifo: true,
      removalPolicy: RemovalPolicy.DESTROY,
      visibilityTimeout: Duration.seconds(60),
      deadLetterQueue: {
        queue: new Queue(this, 'TransDLQ', {
          contentBasedDeduplication: true,
          encryption: QueueEncryption.KMS_MANAGED,
          fifo: true,
          visibilityTimeout: Duration.seconds(60),
          removalPolicy: RemovalPolicy.DESTROY,
        }),
        maxReceiveCount: 5,
      },
    });

    const inferenceStack = new InferenceStack(this, 'inference', {
      vpc,
      neptune: neptuneInfo.cluster,
      queue: tranQueue,
      sagemakerEndpointName: trainingStack.endpointName,
      dataColumnsArg: dataColumnsArg,
    });

    const inferenceFnArn = inferenceStack.inferenceFn.functionArn;
    const interParameterGroups = [
      {
        Label: { default: 'The configuration of graph database Neptune' },
        Parameters: [neptuneInstanceType.logicalId],
      },
    ];

    let customDomain: string | undefined;
    let r53HostZoneId: string | undefined;
    if ('aws-cn' === this.node.tryGetContext('TargetPartition') ||
      (/true/i).test(this.node.tryGetContext('EnableDashboardCustomDomain'))) {
      const dashboardDomainNamePara = new CfnParameter(this, 'DashboardDomain', {
        description: 'Custom domain name for dashboard',
        type: 'String',
        allowedPattern: '(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]',
      });
      const r53HostZoneIdPara = new CfnParameter(this, 'Route53HostedZoneId', {
        type: 'AWS::Route53::HostedZone::Id',
        description: 'Route53 public hosted zone ID of given domain',
      });
      interParameterGroups.push({
        Label: { default: 'The dashboard configuration' },
        Parameters: [dashboardDomainNamePara.logicalId, r53HostZoneIdPara.logicalId],
      });
      customDomain = dashboardDomainNamePara.valueAsString;
      r53HostZoneId = r53HostZoneIdPara.valueAsString;
    }

    const dashboardStack = new TransactionDashboardStack(this, 'dashboard', {
      vpc,
      queue: tranQueue,
      inferenceArn: inferenceFnArn,
      accessLogBucket,
      customDomain: customDomain,
      r53HostZoneId: r53HostZoneId,
    });

    this.templateOptions.metadata = {
      'AWS::CloudFormation::Interface': {
        ParameterGroups: interParameterGroups,
      },
    };
    this.templateOptions.description = `(SO8013) - Real-time Fraud Detection with Graph Neural Network on DGL. Template version ${pjson.version}`;

    new CfnOutput(this, 'DashboardWebsiteUrl', {
      value: customDomain ?? dashboardStack.distribution.distributionDomainName,
      description: 'url of dashboard website',
    });
  }