Skip to content

Commit 9c15c77

Browse files
committed
setup stripe link expiration
1 parent 9701102 commit 9c15c77

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

onetime/stripelink-expiration.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import boto3
2+
import time
3+
import logging
4+
from datetime import datetime, timezone, timedelta
5+
from decimal import Decimal
6+
from botocore.exceptions import ClientError
7+
from numpy import partition
8+
9+
# --- Configuration ---
10+
TABLE_NAME = "infra-core-api-stripe-links"
11+
EXPIRY_DAYS_FROM_NOW = 30
12+
# AWS credentials and region should be configured via environment variables,
13+
# IAM roles, or the ~/.aws/credentials file.
14+
15+
# --- Logging Setup ---
16+
logging.basicConfig(
17+
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
18+
)
19+
20+
21+
def process_inactive_records():
22+
"""
23+
Scans the table for records where 'active' is false and updates their
24+
'expiresAt' and 'updatedAt' attributes.
25+
"""
26+
try:
27+
dynamodb = boto3.resource("dynamodb")
28+
table = dynamodb.Table(TABLE_NAME)
29+
30+
# Calculate the target expiration timestamp (30 days from now)
31+
expires_at_dt = datetime.now(timezone.utc) + timedelta(
32+
days=EXPIRY_DAYS_FROM_NOW
33+
)
34+
expires_at_ts = int(expires_at_dt.timestamp())
35+
36+
# Get the current timestamp for the 'updatedAt' field
37+
new_updated_at = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
38+
39+
logging.info(
40+
f"Target expiration timestamp set to: {expires_at_ts} ({expires_at_dt.isoformat()})"
41+
)
42+
43+
# Use a paginator to handle scanning tables of any size.
44+
# We filter on the server-side for items where 'active' is false.
45+
paginator = dynamodb.meta.client.get_paginator("scan")
46+
page_iterator = paginator.paginate(
47+
TableName=TABLE_NAME,
48+
)
49+
50+
item_count = 0
51+
updated_count = 0
52+
logging.info(f"Starting scan for inactive records in table: {TABLE_NAME}")
53+
54+
for page in page_iterator:
55+
for item in page.get("Items", []):
56+
item_count += 1
57+
58+
# --- MODIFIED: Extract composite primary key ---
59+
partition_key = item.get("userId", None)
60+
sort_key = item.get("linkId", None)
61+
active_key = item.get("active", True)
62+
if active_key:
63+
continue
64+
65+
if not partition_key or not sort_key:
66+
logging.warning(
67+
f"Skipping item with missing composite key parts: {item}"
68+
)
69+
continue
70+
# --- END MODIFICATION ---
71+
72+
# Prepare the update expression and values
73+
update_expression = "SET expiresAt = :ea, updatedAt = :ua"
74+
expression_attribute_values = {
75+
# DynamoDB requires numbers to be passed as Decimal objects
76+
":ea": Decimal(expires_at_ts),
77+
":ua": new_updated_at,
78+
}
79+
80+
# Update the item in DynamoDB
81+
try:
82+
# --- MODIFIED: Use composite key in the Key parameter ---
83+
table.update_item(
84+
Key={"userId": partition_key, "linkId": sort_key},
85+
UpdateExpression=update_expression,
86+
ExpressionAttributeValues=expression_attribute_values,
87+
)
88+
# --- END MODIFICATION ---
89+
updated_count += 1
90+
logging.info(
91+
f"Updated item with userId: {partition_key}, linkId: {sort_key}"
92+
)
93+
except ClientError as e:
94+
logging.error(
95+
f"Failed to update item ({partition_key}, {sort_key}): {e}"
96+
)
97+
98+
logging.info("--- Script Finished ---")
99+
logging.info(f"Total inactive items found: {item_count}")
100+
logging.info(f"Total inactive items updated: {updated_count}")
101+
102+
except ClientError as e:
103+
logging.critical(f"A critical AWS error occurred: {e}")
104+
except Exception as e:
105+
logging.critical(f"An unexpected error occurred: {e}")
106+
107+
108+
if __name__ == "__main__":
109+
process_inactive_records()

terraform/modules/dynamo/main.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ resource "null_resource" "onetime_events_expiration" {
99
}
1010
}
1111

12+
resource "null_resource" "onetime_events_expiration" {
13+
provisioner "local-exec" {
14+
command = <<-EOT
15+
set -e
16+
python stripelink-expiration.py
17+
EOT
18+
interpreter = ["bash", "-c"]
19+
working_dir = "${path.module}/../../../onetime/"
20+
}
21+
}
22+
1223
resource "aws_dynamodb_table" "app_audit_log" {
1324
billing_mode = "PAY_PER_REQUEST"
1425
name = "${var.ProjectId}-audit-log"

0 commit comments

Comments
 (0)