Skip to content

Commit d65cdc7

Browse files
committed
ep1
1 parent 0f12dc9 commit d65cdc7

2 files changed

Lines changed: 200 additions & 8 deletions

File tree

youtube/episode-1.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# YouTube Video Script: Introducing Ganesha — a PHP Circuit Breaker library
2+
3+
**Channel**: [Hand-Rolled Code](channel.md)
4+
**Project**: [Ganesha](https://github.com/ackintosh/ganesha) — PHP Circuit Breaker library
5+
**Task**: Introduce the circuit breaker pattern and Ganesha's basic API
6+
**Estimated duration**: 12–18 minutes
7+
8+
---
9+
10+
## Scene 1 — Channel intro (camera on screen, terminal open)
11+
12+
> "Hey everyone, welcome to Hand-Rolled Code. This channel is about coding by hand — writing real software with my own hands, no AI autocomplete, no generated boilerplate. Just me and a keyboard. I'm planning to post sessions like this regularly, so if that sounds interesting, feel free to subscribe.
13+
>
14+
> Today I want to introduce a PHP library called **Ganesha** — a circuit breaker implementation I've been maintaining. We're going to look at what the circuit breaker pattern is, why it's useful, and how Ganesha implements it. I'll also walk through the basic API so you can start using it in your own projects."
15+
16+
---
17+
18+
## Scene 2 — What is the circuit breaker pattern?
19+
20+
> "Let me start with the concept, because the code makes a lot more sense once you understand what problem we're solving.
21+
>
22+
> Imagine you have a web application that calls an external payment API. If that API is slow or down, your app starts accumulating requests waiting for a response. Those requests pile up, consuming threads and memory. Eventually your entire application grinds to a halt — not because of your own code, but because of a dependency that's failing. This is called a **cascading failure**.
23+
>
24+
> The **circuit breaker pattern** is a way to prevent this. It works just like the electrical circuit breaker in your home. When something goes wrong — too many failures — the circuit 'trips' and you stop sending requests to the broken service. Instead of waiting for a timeout every time, you fail fast and return an error immediately. After some time, you let a test request through to see if the service has recovered.
25+
>
26+
> There are three states:
27+
> - **Closed** — everything is normal, requests go through
28+
> - **Open** — failures exceeded the threshold, requests are blocked
29+
> - **Half-Open** — a trial period, one request is allowed through to test recovery
30+
31+
*Optionally show the diagram image from the README.*
32+
33+
> "Ganesha implements this pattern in PHP."
34+
35+
---
36+
37+
## Scene 3 — Installing Ganesha
38+
39+
*Open terminal.*
40+
41+
> "Let me install it. Ganesha is on Packagist, so it's just a Composer command."
42+
43+
```bash
44+
composer require ackintosh/ganesha
45+
```
46+
47+
> "That's it. No extra extensions required for the basic setup."
48+
49+
---
50+
51+
## Scene 4 — Building Ganesha with the Count Strategy
52+
53+
*Open a new PHP file, for example `demo.php`.*
54+
55+
> "Ganesha provides two strategies for detecting failures. Let's start with the simpler one: the **Count strategy**. It trips the circuit when the number of failures reaches a threshold.
56+
>
57+
> Here's how you build a Ganesha instance."
58+
59+
```php
60+
<?php
61+
require 'vendor/autoload.php';
62+
63+
$redis = new Redis();
64+
$redis->connect('localhost');
65+
66+
$ganesha = Ackintosh\Ganesha\Builder::withCountStrategy()
67+
->adapter(new Ackintosh\Ganesha\Storage\Adapter\Redis($redis))
68+
->failureCountThreshold(3)
69+
->intervalToHalfOpen(10)
70+
->build();
71+
```
72+
73+
> "Let me walk through the options:
74+
>
75+
> - `failureCountThreshold(3)` — the circuit trips after 3 consecutive failures
76+
> - `intervalToHalfOpen(10)` — 10 seconds after tripping, Ganesha allows one trial request through
77+
>
78+
> The adapter is how Ganesha persists its state. Here I'm using Redis. Ganesha supports several adapters — Redis, Memcached, APCu, and MongoDB."
79+
80+
---
81+
82+
## Scene 5 — The basic API: `isAvailable()`, `success()`, `failure()`
83+
84+
> "Ganesha's API is deliberately minimal. There are three methods you need to know."
85+
86+
```php
87+
$service = 'payment-api';
88+
89+
if (!$ganesha->isAvailable($service)) {
90+
// fail fast — don't even try the request
91+
throw new RuntimeException('Payment API is not available');
92+
}
93+
94+
try {
95+
// make the actual request
96+
$result = callPaymentApi();
97+
$ganesha->success($service);
98+
} catch (RuntimeException $e) {
99+
$ganesha->failure($service);
100+
throw $e;
101+
}
102+
```
103+
104+
> "The `$service` string is just a name — it's how Ganesha tracks state per service. You can have as many services as you like, each with its own circuit state.
105+
>
106+
> - `isAvailable()` — returns `true` if the circuit is closed, `false` if it's open
107+
> - `success()` — tell Ganesha the request succeeded
108+
> - `failure()` — tell Ganesha the request failed
109+
>
110+
> That's the entire integration. You wrap your existing call with an `isAvailable()` check and record the outcome."
111+
112+
---
113+
114+
## Scene 6 — Watching the circuit trip
115+
116+
> "Let me show what actually happens when failures accumulate."
117+
118+
```php
119+
var_dump($ganesha->isAvailable($service)); // bool(true)
120+
121+
$ganesha->failure($service);
122+
$ganesha->failure($service);
123+
$ganesha->failure($service); // 3rd failure — threshold reached
124+
125+
var_dump($ganesha->isAvailable($service)); // bool(false)
126+
```
127+
128+
> "After the third failure, `isAvailable()` returns false. The circuit is open. Any further calls are blocked immediately — no waiting for timeouts, no wasted resources."
129+
130+
---
131+
132+
## Scene 7 — Subscribing to events
133+
134+
> "Ganesha also publishes events when the circuit state changes. This is useful for logging or alerting."
135+
136+
```php
137+
$ganesha->subscribe(function (string $event, string $service, string $message): void {
138+
error_log(sprintf('[Ganesha] %s: %s', $event, $service));
139+
});
140+
```
141+
142+
> "There are three events:
143+
> - `EVENT_TRIPPED` — the circuit just opened
144+
> - `EVENT_CALMED_DOWN` — the circuit recovered and closed again
145+
> - `EVENT_STORAGE_ERROR` — the storage backend had a problem
146+
>
147+
> Notice that storage errors are handled gracefully — if Redis goes down, Ganesha defaults to returning `true` from `isAvailable()` rather than crashing your application. It fails open, which is usually the right default for a circuit breaker."
148+
149+
---
150+
151+
## Scene 8 — Brief mention of the Rate Strategy
152+
153+
> "I mentioned there's a second strategy — the **Rate strategy**. Instead of counting raw failures, it tracks the failure rate as a percentage over a sliding time window. This is better for high-traffic services where a fixed count doesn't scale well.
154+
155+
```php
156+
$ganesha = Ackintosh\Ganesha\Builder::withRateStrategy()
157+
->adapter(new Ackintosh\Ganesha\Storage\Adapter\Redis($redis))
158+
->failureRateThreshold(50) // trip if 50% of requests fail
159+
->minimumRequests(10) // but only after at least 10 requests
160+
->timeWindow(30) // measured over a 30-second window
161+
->intervalToHalfOpen(10)
162+
->build();
163+
```
164+
165+
> "We won't go deeper into this today, but the API is identical — same three methods, same event system."
166+
167+
---
168+
169+
## Scene 9 — Tease for Episode 2
170+
171+
*Open [src/Ganesha/Storage/Adapter/Redis.php](../src/Ganesha/Storage/Adapter/Redis.php), navigate to the `reset()` method.*
172+
173+
> "Before I wrap up — let me show you something I found in the codebase."
174+
175+
*Scroll to the `reset()` method's TODO comment.*
176+
177+
> "There's a TODO here. The `reset()` method — which is supposed to clear all circuit breaker state — is not implemented for the Redis adapter. If you call `$ganesha->reset()` right now with Redis, nothing happens.
178+
>
179+
> In the next video, I'm going to fix this. We'll look at how Redis is storing Ganesha's data, figure out the right approach to delete it all safely, write the implementation, and test it.
180+
>
181+
> That's it for today. If you found this useful, give it a thumbs up. See you next time."
182+
183+
---
184+
185+
## Notes for Recording
186+
187+
- **Editor**: VS Code with the file tree visible on the left sidebar
188+
- **Font size**: Increase to at least 18pt for readability on video
189+
- **Terminal**: Keep it in the same window, use a split pane if possible
190+
- **Pace**: Pause after each code block to give viewers time to read
191+
- **For the demo**: Start Docker before recording — `docker-compose up` to have Redis running
192+
- **Pronunciation tips**:
193+
- "circuit breaker" → SIR-kit BRAY-ker
194+
- "cascading" → kas-KAY-ding
195+
- "threshold" → THRESH-old
196+
- "Packagist" → PACK-uh-jist
197+
- "Composer" → kom-POH-zer
Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,17 @@
22

33
**Channel**: [Hand-Rolled Code](channel.md)
44
**Project**: [Ganesha](https://github.com/ackintosh/ganesha) — PHP Circuit Breaker library
5+
**Episode**: 2 — continues from [episode-1.md](episode-1.md)
56
**Task**: Implement the `reset()` method in the Redis storage adapter
67
**Estimated duration**: 15–20 minutes
78

89
---
910

1011
## Scene 1 — Introduction (camera on screen, terminal open)
1112

12-
> "Hey everyone, welcome. This is my first video. This channel is about coding by hand — writing real software with my own hands, no AI autocomplete, no generated boilerplate. Just me and a keyboard. I'm planning to post sessions like this regularly, so if that sounds interesting, feel free to subscribe.
13+
> "Hey everyone, welcome back. Last time I introduced Ganesha — a PHP circuit breaker library I've been maintaining — and walked through the basic API.
1314
>
14-
> Today I'm going to do some coding on an open-source PHP library called **Ganesha** — which is a circuit breaker implementation I've been maintaining.
15-
16-
> If you're not familiar with the circuit breaker pattern — it's a design pattern used in distributed systems to prevent cascading failures. Think of it like an electrical circuit breaker: when too many failures happen, the circuit 'trips' and stops sending requests to a broken service, giving it time to recover.
17-
18-
> Ganesha supports two strategies for detecting failures: a **Rate strategy**, which tracks the failure rate as a percentage over a sliding time window, and a **Count strategy**, which simply counts how many failures have occurred.
19-
20-
> Today's task is pretty focused. I found a TODO comment in the codebase, and I want to take care of it."
15+
> Today's task is more focused. I found a TODO comment in the codebase, and I want to take care of it."
2116
2217
---
2318

0 commit comments

Comments
 (0)