Skip to content

Commit 42866c4

Browse files
committed
Fix props to List component
1 parent 28654f5 commit 42866c4

2 files changed

Lines changed: 75 additions & 83 deletions

File tree

  • src/content/articles
    • idempotent-message-handlers-deduplication-retries
    • internal-cli-kubectl-terraform-wrapper-abstraction

src/content/articles/idempotent-message-handlers-deduplication-retries/index.mdx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,24 @@ There are four common strategies, each with distinct tradeoffs:
3131

3232
<List
3333
variant="check-icons-list"
34-
content={{
35-
items: [
36-
{
37-
lead: "Producer-supplied message ID",
38-
text: "is the cleanest approach. The producer generates a UUID or ULID when creating the message and includes it in the payload. This key survives redeliveries because it's part of the message content, not queue metadata. The downside is that it requires producer discipline - every producer must generate and include a unique ID.",
39-
},
40-
{
41-
lead: "Content hash",
42-
text: "works when you can't control producers. Hash the message payload with SHA-256 and use that as the key. Identical content produces identical keys automatically. The risk is that sometimes identical content _should_ be processed multiple times (two separate orders for the same product), and a content hash would incorrectly dedupe them.",
43-
},
44-
{
45-
lead: "Business key composite",
46-
text: "combines entity identifiers with operation context: `order:12345:payment:v3`. This approach has semantic meaning, making debugging easier, but requires careful thought about what constitutes a unique operation.",
47-
},
48-
{
49-
lead: "Queue message ID",
50-
text: "- avoid this approach. SQS assigns a new MessageId on each redelivery. RabbitMQ's delivery tag changes. This approach only deduplicates within a single delivery attempt, which defeats the purpose entirely.",
51-
},
52-
],
53-
}}
34+
items={[
35+
{
36+
lead: "Producer-supplied message ID",
37+
text: "is the cleanest approach. The producer generates a UUID or ULID when creating the message and includes it in the payload. This key survives redeliveries because it's part of the message content, not queue metadata. The downside is that it requires producer discipline - every producer must generate and include a unique ID.",
38+
},
39+
{
40+
lead: "Content hash",
41+
text: "works when you can't control producers. Hash the message payload with SHA-256 and use that as the key. Identical content produces identical keys automatically. The risk is that sometimes identical content _should_ be processed multiple times (two separate orders for the same product), and a content hash would incorrectly dedupe them.",
42+
},
43+
{
44+
lead: "Business key composite",
45+
text: "combines entity identifiers with operation context: `order:12345:payment:v3`. This approach has semantic meaning, making debugging easier, but requires careful thought about what constitutes a unique operation.",
46+
},
47+
{
48+
lead: "Queue message ID",
49+
text: "- avoid this approach. SQS assigns a new MessageId on each redelivery. RabbitMQ's delivery tag changes. This approach only deduplicates within a single delivery attempt, which defeats the purpose entirely.",
50+
},
51+
]}
5452
/>
5553

5654
The recommended pattern combines producer-supplied IDs with business context:

src/content/articles/internal-cli-kubectl-terraform-wrapper-abstraction/index.mdx

Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,24 @@ Not all wrappers are created equal. Some genuinely earn their maintenance cost;
2727

2828
<List
2929
variant="check-icons-list"
30-
content={{
31-
items: [
32-
{
33-
lead: "Complexity hiding",
34-
text: "is the strongest justification. When a workflow requires five or more manual steps with dependencies and ordering constraints, a wrapper reduces cognitive load and enforces the correct sequence. A `deploy-service` command that builds, pushes, runs helm upgrade, and executes smoke tests in the right order prevents the \"I forgot to push the image before deploying\" class of errors.",
35-
},
36-
{
37-
lead: "Guard rails",
38-
text: "prevent dangerous operations. A `kubectl-safe` wrapper that blocks `delete` in production without an approval ticket prevents the kind of outages that make the news. This works when the underlying tool allows dangerous operations with severe consequences and the policy can be codified clearly.",
39-
},
40-
{
41-
lead: "Context injection",
42-
text: "automatically selects environment-specific configuration. A terraform wrapper that auto-selects workspace, backend, and var files based on your git branch eliminates \"I thought I was in staging\" mistakes - but only if it _shows_ you what it detected. Silent context switching is how you get production outages.",
43-
},
44-
{
45-
lead: "Credential management",
46-
text: "handles authentication complexity transparently. A kubectl wrapper that auto-refreshes tokens and selects the correct cluster config reduces auth friction when tokens expire frequently and manual credential management is error-prone.",
47-
},
48-
],
49-
}}
30+
items={[
31+
{
32+
lead: "Complexity hiding",
33+
text: "is the strongest justification. When a workflow requires five or more manual steps with dependencies and ordering constraints, a wrapper reduces cognitive load and enforces the correct sequence. A `deploy-service` command that builds, pushes, runs helm upgrade, and executes smoke tests in the right order prevents the \"I forgot to push the image before deploying\" class of errors.",
34+
},
35+
{
36+
lead: "Guard rails",
37+
text: "prevent dangerous operations. A `kubectl-safe` wrapper that blocks `delete` in production without an approval ticket prevents the kind of outages that make the news. This works when the underlying tool allows dangerous operations with severe consequences and the policy can be codified clearly.",
38+
},
39+
{
40+
lead: "Context injection",
41+
text: "automatically selects environment-specific configuration. A terraform wrapper that auto-selects workspace, backend, and var files based on your git branch eliminates \"I thought I was in staging\" mistakes - but only if it _shows_ you what it detected. Silent context switching is how you get production outages.",
42+
},
43+
{
44+
lead: "Credential management",
45+
text: "handles authentication complexity transparently. A kubectl wrapper that auto-refreshes tokens and selects the correct cluster config reduces auth friction when tokens expire frequently and manual credential management is error-prone.",
46+
},
47+
]}
5048
/>
5149

5250
### What Doesn't Warrant a Wrapper
@@ -123,25 +121,23 @@ The detection hierarchy should be predictable and documented:
123121

124122
<List
125123
variant="numbered-with-background-list"
126-
content={{
127-
items: [
128-
{
129-
text: "Explicit flags (`--context=prod`)",
130-
},
131-
{
132-
text: "Environment variables (`DEPLOY_ENV=staging`)",
133-
},
134-
{
135-
text: "Git branch detection (`main` → production)",
136-
},
137-
{
138-
text: "Directory structure (`/environments/dev/`)",
139-
},
140-
{
141-
text: "Default fallback (usually dev)",
142-
},
143-
],
144-
}}
124+
items={[
125+
{
126+
text: "Explicit flags (`--context=prod`)",
127+
},
128+
{
129+
text: "Environment variables (`DEPLOY_ENV=staging`)",
130+
},
131+
{
132+
text: "Git branch detection (`main` → production)",
133+
},
134+
{
135+
text: "Directory structure (`/environments/dev/`)",
136+
},
137+
{
138+
text: "Default fallback (usually dev)",
139+
},
140+
]}
145141
/>
146142

147143
And when context is injected automatically, don't override explicit user flags - if someone types `--namespace=testing`, respect it even if your wrapper thinks they should be in `production`.
@@ -152,30 +148,28 @@ Wrappers often fail gradually. Usage stays high because it's in deployment scrip
152148

153149
<List
154150
variant="check-icons-list"
155-
content={{
156-
items: [
157-
{
158-
lead: "Bypass rate above 20%",
159-
text: "means developers don't trust the wrapper for real work. They're using the \"safe\" path for routine operations but dropping to raw tools when it matters.",
160-
},
161-
{
162-
lead: "Support tickets mention the wrapper",
163-
text: "more than the underlying tool. If \"tf-deploy\" appears in more tickets than \"terraform,\" your abstraction is creating problems instead of solving them.",
164-
},
165-
{
166-
lead: "Developers ask \"what command is this actually running?\"",
167-
text: "for basic operations. Transparency has failed - they can't predict what the wrapper does.",
168-
},
169-
{
170-
lead: "You're more than one major version behind",
171-
text: "the upstream tool. You can't track releases, and the gap will only widen.",
172-
},
173-
{
174-
lead: "New team members learn the raw tool first",
175-
text: "because the wrapper's behavior is too unpredictable. Your \"simplification\" made things more complex.",
176-
},
177-
],
178-
}}
151+
items={[
152+
{
153+
lead: "Bypass rate above 20%",
154+
text: "means developers don't trust the wrapper for real work. They're using the \"safe\" path for routine operations but dropping to raw tools when it matters.",
155+
},
156+
{
157+
lead: "Support tickets mention the wrapper",
158+
text: "more than the underlying tool. If \"tf-deploy\" appears in more tickets than \"terraform,\" your abstraction is creating problems instead of solving them.",
159+
},
160+
{
161+
lead: "Developers ask \"what command is this actually running?\"",
162+
text: "for basic operations. Transparency has failed - they can't predict what the wrapper does.",
163+
},
164+
{
165+
lead: "You're more than one major version behind",
166+
text: "the upstream tool. You can't track releases, and the gap will only widen.",
167+
},
168+
{
169+
lead: "New team members learn the raw tool first",
170+
text: "because the wrapper's behavior is too unpredictable. Your \"simplification\" made things more complex.",
171+
},
172+
]}
179173
/>
180174

181175
### Health Metrics to Track

0 commit comments

Comments
 (0)