mirror of
https://github.com/Sea-Haven-Industries/procurement-ingest.git
synced 2026-09-30 07:13:13 +00:00
* feat(infra): add kebab WO tables and PLAT-11 cutover tooling Create empty work-orders/work-order-comments under Terraform while writers stay on PascalCase; make emitter table classification env-driven and add same-account migrate/verify plus cutover runbook. * style(test): ruff-format shoc emitter envelope tests
169 lines
3.9 KiB
HCL
169 lines
3.9 KiB
HCL
# PLAT-11: PascalCase tables remain authoritative until the freeze cutover.
|
|
# Kebab tables are created empty in the prep apply; writers/ESMs stay on legacy
|
|
# until docs/plat-11/cutover-runbook.md Phase 2.
|
|
|
|
resource "aws_dynamodb_table" "work_orders" {
|
|
name = "WorkOrders"
|
|
billing_mode = "PAY_PER_REQUEST"
|
|
hash_key = "work_order_id"
|
|
|
|
attribute {
|
|
name = "work_order_id"
|
|
type = "S"
|
|
}
|
|
|
|
stream_enabled = true
|
|
stream_view_type = "NEW_AND_OLD_IMAGES"
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_dynamodb_table" "work_order_comments" {
|
|
name = "WorkOrderComments"
|
|
billing_mode = "PAY_PER_REQUEST"
|
|
hash_key = "work_order_id"
|
|
range_key = "comment_id"
|
|
|
|
attribute {
|
|
name = "work_order_id"
|
|
type = "S"
|
|
}
|
|
|
|
attribute {
|
|
name = "comment_id"
|
|
type = "S"
|
|
}
|
|
|
|
stream_enabled = true
|
|
stream_view_type = "NEW_AND_OLD_IMAGES"
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_dynamodb_table" "work_orders_kebab" {
|
|
name = "work-orders"
|
|
billing_mode = "PAY_PER_REQUEST"
|
|
hash_key = "work_order_id"
|
|
|
|
attribute {
|
|
name = "work_order_id"
|
|
type = "S"
|
|
}
|
|
|
|
stream_enabled = true
|
|
stream_view_type = "NEW_AND_OLD_IMAGES"
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_dynamodb_table" "work_order_comments_kebab" {
|
|
name = "work-order-comments"
|
|
billing_mode = "PAY_PER_REQUEST"
|
|
hash_key = "work_order_id"
|
|
range_key = "comment_id"
|
|
|
|
attribute {
|
|
name = "work_order_id"
|
|
type = "S"
|
|
}
|
|
|
|
attribute {
|
|
name = "comment_id"
|
|
type = "S"
|
|
}
|
|
|
|
stream_enabled = true
|
|
stream_view_type = "NEW_AND_OLD_IMAGES"
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
locals {
|
|
# Alarms stay on the live writer tables (legacy until cutover).
|
|
wo_ddb_alarm_tables = {
|
|
"WorkOrders" = aws_dynamodb_table.work_orders.name
|
|
"WorkOrderComments" = aws_dynamodb_table.work_order_comments.name
|
|
}
|
|
}
|
|
|
|
resource "aws_cloudwatch_metric_alarm" "wo_ddb_throttles" {
|
|
for_each = local.wo_ddb_alarm_tables
|
|
|
|
alarm_name = "${each.key}-throttles"
|
|
alarm_description = "${each.key} DynamoDB throttled requests"
|
|
comparison_operator = "GreaterThanThreshold"
|
|
evaluation_periods = 1
|
|
threshold = 0
|
|
treat_missing_data = "notBreaching"
|
|
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
|
|
|
|
metric_query {
|
|
id = "expr_1"
|
|
expression = local.ddb_throttle_expr
|
|
label = "Sum of throttled requests across all operations"
|
|
return_data = true
|
|
}
|
|
|
|
dynamic "metric_query" {
|
|
for_each = local.ddb_alarm_operations
|
|
content {
|
|
id = lower(metric_query.value)
|
|
metric {
|
|
metric_name = "ThrottledRequests"
|
|
namespace = "AWS/DynamoDB"
|
|
period = 300
|
|
stat = "Sum"
|
|
dimensions = {
|
|
TableName = each.value
|
|
Operation = metric_query.value
|
|
}
|
|
}
|
|
return_data = false
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "aws_cloudwatch_metric_alarm" "wo_ddb_system_errors" {
|
|
for_each = local.wo_ddb_alarm_tables
|
|
|
|
alarm_name = "${each.key}-system-errors"
|
|
alarm_description = "${each.key} DynamoDB server-side (5xx) errors"
|
|
comparison_operator = "GreaterThanThreshold"
|
|
evaluation_periods = 1
|
|
threshold = 0
|
|
treat_missing_data = "notBreaching"
|
|
alarm_actions = [data.aws_sns_topic.site_alerts.arn]
|
|
|
|
metric_query {
|
|
id = "expr_1"
|
|
expression = local.ddb_throttle_expr
|
|
label = "Sum of system errors across all operations"
|
|
return_data = true
|
|
}
|
|
|
|
dynamic "metric_query" {
|
|
for_each = local.ddb_alarm_operations
|
|
content {
|
|
id = lower(metric_query.value)
|
|
metric {
|
|
metric_name = "SystemErrors"
|
|
namespace = "AWS/DynamoDB"
|
|
period = 300
|
|
stat = "Sum"
|
|
dimensions = {
|
|
TableName = each.value
|
|
Operation = metric_query.value
|
|
}
|
|
}
|
|
return_data = false
|
|
}
|
|
}
|
|
}
|