feat(uploads): choose the language of a recording; record it, show it, carry it to the engines (#61)

Form field (Swedish preselected, Other = auto) read before the file part and refused
before anything is spooled if outside the closed set; stored on the row (migration 021,
CHECK constraint, default sv for history); carried on the Job and the worker's context;
shown on the status page. Feature scenarios and the coverage map are updated, and
ADR-033/034 amended.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-04 22:29:58 +02:00
co-authored by Claude Sonnet 5.5
parent ed9d76b0cf
commit 0338b18a17
26 changed files with 718 additions and 371 deletions
+23
View File
@@ -126,6 +126,7 @@ type fakeTranscriber struct {
result domain.Transcription
err error
paths []string
langs []domain.Language // what each call's context carried
// block, when non-nil, holds every call until it is closed or ctx ends.
block chan struct{}
running atomic.Int32
@@ -134,6 +135,7 @@ type fakeTranscriber struct {
func (f *fakeTranscriber) Transcribe(ctx context.Context, wav string) (domain.Transcription, error) {
f.paths = append(f.paths, wav)
f.langs = append(f.langs, domain.LanguageFrom(ctx))
n := f.running.Add(1)
defer f.running.Add(-1)
for {
@@ -337,3 +339,24 @@ func (dbErr) Error() string {
return `ERROR: invalid input syntax for type json: "zebrakaka secret words"`
}
func (dbErr) SQLState() string { return "22P02" }
func TestWorker_TheTranscriberSeesTheLanguageOfTheJobOnItsContext(t *testing.T) {
for name, tt := range map[string]struct {
job domain.Language
want domain.Language
}{
"auto": {domain.LangAuto, domain.LangAuto},
"swedish": {domain.LangSwedish, domain.LangSwedish},
"a job with no language": {"", domain.LangSwedish}, // queued before the field existed
} {
t.Run(name, func(t *testing.T) {
r := newWRig(t, time.Minute)
job := r.spool(t, "a")
job.Language = tt.job
r.w.Process(context.Background(), job)
assert.Equal(t, []domain.Language{tt.want}, r.tr.langs)
})
}
}