pk: createDelimitedAttribute()

in source/packages/services/greengrass2-provisioning/src/deploymentTasks/deploymentTasks.dao.ts [55:325]


                pk: createDelimitedAttribute(PkType.DeploymentTask, taskId),
                sk: createDelimitedAttribute(PkType.CoreDevice, coreName),
            },
        };
        const result = await this.dbc.send(new GetCommand(params));

        if (!result.Item) {
            logger.debug('deploymentTasks.dao getDeploymentTaskStatusByCore: exit: undefined');
            return undefined;
        }

        const deployment = this.assembleDeployment(result.Item);
        logger.debug(
            `deploymentTasks.dao getDeploymentTaskStatusByCore: exit: deployment:${deployment}}`
        );

        return deployment;
    }

    public async listDeploymentsByCore(
        coreName: string,
        count?: number,
        lastEvaluated?: DeploymentTaskListPaginationKey
    ): Promise<[Deployment[], DeploymentTaskListPaginationKey]> {
        logger.debug(
            `deploymentTasks.dao listDeploymentsByCore: in: coreName:${coreName}, count:${count}, lastEvaluated:${JSON.stringify(
                lastEvaluated
            )}`
        );

        let exclusiveStartKey: DynamoDbPaginationKey;

        if (lastEvaluated?.taskId) {
            exclusiveStartKey = {
                siKey1: createDelimitedAttribute(PkType.CoreDevice, coreName),
                sk: createDelimitedAttribute(PkType.CoreDevice, coreName),
                pk: createDelimitedAttribute(PkType.DeploymentTask, lastEvaluated.taskId),
            };
        }

        const params: QueryCommandInput = {
            TableName: process.env.AWS_DYNAMODB_TABLE_NAME,
            IndexName: GSI1_INDEX_NAME,
            KeyConditionExpression: `#hash=:hash  AND begins_with( #sortKey, :sortKey )`,
            ExpressionAttributeNames: {
                '#hash': 'siKey1',
                '#sortKey': 'pk',
            },
            ExpressionAttributeValues: {
                ':hash': createDelimitedAttribute(PkType.CoreDevice, coreName),
                ':sortKey': createDelimitedAttribute(PkType.DeploymentTask),
            },
            Select: 'ALL_ATTRIBUTES',
            ExclusiveStartKey: exclusiveStartKey,
            Limit: count,
        };

        const results = await this.dbc.send(new QueryCommand(params));
        if ((results?.Items?.length ?? 0) === 0) {
            logger.debug('deploymentTasks.dao listDeploymentsByCore: exit: undefined');
            return [[], undefined];
        }

        const deployments = this.assembleDeployments(results.Items);

        let paginationKey: DeploymentTaskListPaginationKey;
        if (results.LastEvaluatedKey) {
            console.log(results);
            const lastEvaluatedTaskId = expandDelimitedAttribute(results.LastEvaluatedKey.pk)[1];
            paginationKey = {
                taskId: lastEvaluatedTaskId,
            };
        }

        logger.debug(
            `deploymentTasks.dao listDeploymentsByCore: in: deployments:${JSON.stringify(
                deployments
            )}, paginationKey: ${JSON.stringify(paginationKey)}`
        );
        return [deployments, paginationKey];
    }

    public async listCoresByDeploymentTask(
        taskId: string,
        count?: number,
        lastEvaluated?: CoreDeploymentListPaginationKey
    ): Promise<[Deployment[], CoreDeploymentListPaginationKey]> {
        logger.debug(
            `deploymentTasks.dao list: in: taskId:${taskId}, count:${count}, lastEvaluated:${JSON.stringify(
                lastEvaluated
            )}`
        );

        let exclusiveStartKey: DynamoDbPaginationKey;

        if (lastEvaluated?.thingName) {
            exclusiveStartKey = {
                pk: createDelimitedAttribute(PkType.DeploymentTask, taskId),
                sk: createDelimitedAttribute(PkType.CoreDevice, lastEvaluated.thingName),
            };
        }

        const params: QueryCommandInput = {
            TableName: process.env.AWS_DYNAMODB_TABLE_NAME,
            KeyConditionExpression: `#hash=:hash AND begins_with( #sortKey, :sortKey )`,
            ExpressionAttributeNames: {
                '#hash': 'pk',
                '#sortKey': 'sk',
            },
            ExpressionAttributeValues: {
                ':hash': createDelimitedAttribute(PkType.DeploymentTask, taskId),
                ':sortKey': createDelimitedAttribute(PkType.CoreDevice),
            },
            Select: 'ALL_ATTRIBUTES',
            ExclusiveStartKey: exclusiveStartKey,
            Limit: count,
        };

        const results = await this.dbc.send(new QueryCommand(params));
        if ((results?.Items?.length ?? 0) === 0) {
            logger.debug('deploymentTasks.dao listCoresByDeploymentTask: exit: undefined');
            return [[], undefined];
        }

        const deployments = this.assembleDeployments(results.Items);

        let paginationKey: CoreDeploymentListPaginationKey;
        if (results.LastEvaluatedKey) {
            const lastEvaluatedThingName = expandDelimitedAttribute(
                results.LastEvaluatedKey.sk
            )[1];
            paginationKey = {
                thingName: lastEvaluatedThingName,
            };
        }

        logger.debug(
            `deploymentTasks.dao listCoresByDeploymentTask: in: deployments:${JSON.stringify(
                deployments
            )}, paginationKey: ${JSON.stringify(paginationKey)}`
        );
        return [deployments, paginationKey];
    }

    public async list(
        count?: number,
        lastEvaluated?: DeploymentTaskListPaginationKey
    ): Promise<[DeploymentTask[], DeploymentTaskListPaginationKey]> {
        logger.debug(
            `deploymentTasks.dao list: in: count:${count}, lastEvaluated:${JSON.stringify(
                lastEvaluated
            )}`
        );

        let exclusiveStartKey: DynamoDbPaginationKey;
        if (lastEvaluated?.taskId) {
            exclusiveStartKey = {
                pk: createDelimitedAttribute(PkType.DeploymentTask, lastEvaluated.taskId),
                sk: createDelimitedAttribute(PkType.DeploymentTask, lastEvaluated.taskId),
                siKey1: PkType.DeploymentTask,
            };
        }

        const params: QueryCommandInput = {
            TableName: process.env.AWS_DYNAMODB_TABLE_NAME,
            IndexName: GSI1_INDEX_NAME,
            KeyConditionExpression: `#hash=:hash`,
            ExpressionAttributeNames: {
                '#hash': 'siKey1',
            },
            ExpressionAttributeValues: {
                ':hash': PkType.DeploymentTask,
            },
            Select: 'ALL_ATTRIBUTES',
            ExclusiveStartKey: exclusiveStartKey,
            Limit: count,
        };

        const results = await this.dbc.send(new QueryCommand(params));
        if ((results?.Items?.length ?? 0) === 0) {
            logger.debug('deploymentTasks.dao list: exit: undefined');
            return [undefined, undefined];
        }

        const deploymentTaskList = this.assembleList(results.Items);

        let paginationKey: DeploymentTaskListPaginationKey;
        if (results.LastEvaluatedKey) {
            const lastEvaluatedTaskId = expandDelimitedAttribute(results.LastEvaluatedKey.pk)[1];
            paginationKey = {
                taskId: lastEvaluatedTaskId,
            };
        }

        logger.debug(
            `templates.dao list: exit: response:${JSON.stringify(
                deploymentTaskList
            )}, paginationKey:${paginationKey}`
        );

        return [deploymentTaskList, paginationKey];
    }

    public async get(taskId: string, summarize = false): Promise<DeploymentTask> {
        logger.debug(`deploymentTasks.dao get: in: taskId:${taskId}, summarize:${summarize}`);

        const taskDbId = createDelimitedAttribute(PkType.DeploymentTask, taskId);

        const params: QueryCommandInput = {
            TableName: process.env.AWS_DYNAMODB_TABLE_NAME,
            KeyConditionExpression: `#pk=:pk`,
            ExpressionAttributeNames: {
                '#pk': 'pk',
            },
            ExpressionAttributeValues: {
                ':pk': taskDbId,
            },
            ScanIndexForward: true,
        };

        if (summarize) {
            // only return the summary record if the summary is all we need
            params.KeyConditionExpression += ' AND #sk=:sk';
            params.ExpressionAttributeNames['#sk'] = 'sk';
            params.ExpressionAttributeValues[':sk'] = taskDbId;
        }

        // TODO: either handle pagination of targeted cores, or expose as a different paginated endpoint
        const results = await this.dbc.send(new QueryCommand(params));
        if (results.Items === undefined || results.Items.length === 0) {
            logger.debug('deploymentTasks.dao get: exit: undefined');
            return undefined;
        }

        const task = this.assemble(results.Items);
        logger.debug(`deploymentTasks.dao get: exit: ${JSON.stringify(task)}`);
        return task;
    }

    public async saveDeploymentTask(
        task: DeploymentTask,
        saveBatchProgress: boolean
    ): Promise<void> {
        logger.debug(
            `deploymentTasks.dao saveDeploymentTask: in: task:${JSON.stringify(
                task
            )}, saveBatchProgress:${saveBatchProgress}`
        );

        ow(task, ow.object.nonEmpty);
        ow(task.id, ow.string.nonEmpty);
        ow(task.taskStatus, ow.string.nonEmpty);
        for (const d of task.deployments) {
            ow(d, ow.object.nonEmpty);
            ow(d.coreName, ow.string.nonEmpty);
        }

        const params: BatchWriteCommandInput = {
            RequestItems: {
                [process.env.AWS_DYNAMODB_TABLE_NAME]: [],
            },
        };

        const createdAt = task.createdAt ? new Date(task.createdAt).toISOString() : undefined;
        const updatedAt = task.updatedAt ? new Date(task.updatedAt).toISOString() : undefined;

        // main task item
        const taskDbId = createDelimitedAttribute(PkType.DeploymentTask, task.id);
        const taskItem = {
            PutRequest: {
                Item: {