The week before: what only a real party finds
A week before my birthday, I tested Orfeo over dinner with four friends. All my tests were passing. The evening still found five bugs — and the big day found a sixth.
A week before my birthday, all my tests were passing.
Orfeo's brain was tested. The database held 140 simulated guests. On paper, it was ready.
So I did the one thing that was missing: dinner with four friends, Orfeo in charge, as if it were the real day.
Twenty-eight fixes later, I understood the difference between "every part works" and "it holds for a whole evening".
The banned song that comes back
First ghost. During dinner a track plays, nobody wants it, I veto it. It skips. Perfect.
An hour later, it's back on the room screen. Position 4 in the queue. While it's listed, in black and white, in my blocklist.
The explanation is silly. Banning an upcoming track did remove it from the player. Banning the current track just skipped it — its entry stayed in Apple Music's list. And when the player reached the end and looped, my banned track became an "upcoming" track like any other.
My tests checked that a veto skipped the track. None of them waited an hour to see if it came back.
The rap from an hour ago
This one really worried me.
Dinner moves on, the mood has changed, and suddenly: The Kinks, then Chappell Roan… with French rap queued behind. Rap picked an hour earlier, when the evening was still rap.
I thought to myself that smooth, logical transitions were far from a done deal.
Here's what was happening. When nobody suggests anything, Orfeo picks tracks on its own and puts them in the queue like any other suggestion. Except those tracks never expired. They lost to voted tracks, so they sat behind them. But they won every slot the guests didn't fill.
Result: the room was hearing the register of an hour ago.
And nothing in my formula caught it. My genre penalty punishes repetition, not incoherence. Two tracks from opposite registers can have the same energy and fit the phase equally well.
The fix: past forty minutes, a track picked by the machine is no longer a candidate. With one exception that is the whole difficulty — unless there isn't enough left to play. Those tracks are the safety net. Expire them too strictly and you empty the queue exactly when you need it.
The net that deletes itself
Speaking of nets.
I had planned an emergency exit: if everything crashes or runs away, export the upcoming queue as an Apple Music playlist and carry on by hand. A "just in case".
Rereading the code that week, I found this: when Orfeo published an empty queue, it deleted everything that existed. Logical, in a way. Except a simple network hiccup at the wrong moment was indistinguishable from an empty queue.
So: network drops, Orfeo thinks the queue is empty, it deletes everything — including the rows my emergency exit was supposed to read.
The safety net, deleted at the worst moment, by the failure of the very read that was meant to restore it.
The rule since then: an empty queue means "I have nothing to say". Never "erase".
I never used the emergency exit. But I slept better knowing it worked.
The screen that falls asleep
The last two are less spectacular, and just as impossible to see from my desk.
The room screen — the one showing the current track — went dark after a while. Nothing kept it awake. And when I added what was needed, I discovered that the browser releases that lock on its own as soon as the page goes to the background, without telling you.
And the phones. On every update, every phone reloaded everything. With four friends, you don't notice. With forty-five, each vote triggers forty-five full reloads. My load test couldn't see it: it simulated guests, not the application running in their pocket.
The one the rehearsal didn't find
I could stop here and say the rehearsal caught everything. That would be false.
On the night of my birthday, the Apple Music queue made a jump — a loop, a veto landing far down. Orfeo looked at the player's position, saw it had moved forward twelve tracks, and concluded that twelve tracks had just played.
In one minute, twelve guest suggestions were marked "played". None of them had been.
I didn't see it at the time. Nobody told me. I found it afterwards, in the data. Twelve songs suggested by guests that night, and never heard.
The fix fits in one sentence: a track can't be "finished" if less than sixty seconds have passed. The principle behind it matters more than the code: missing a mark costs little, inventing one costs a guest their song. When in doubt, don't mark.
What I take from it
What scared me most, that whole week, was the flow from one track to the next. Not a crash. Not an error on screen. Just the music carrying on, but sounding wrong.
And that's exactly what my tests couldn't see. A test checks that a rule does what it says. It doesn't sit at the table for three hours and feel that the mood has changed.
That week's bugs all share a profile. None of them crash. All of them need time — an hour, a loop, forty minutes — and real people doing things out of order.
If you're building something that has to hold for an evening, throw an evening. A small one. Four friends and a dinner are enough.
This is the last article in this series. What's next for Orfeo is opening it to people other than me — and there will be things to tell.
— Pato