* feat(playback): formalize resumable direct streams and stall observability Implements #443: strong stat-based ETag + If-Range on original-file direct play (via http.ServeContent), stream-end outcome classification in RollingDeadlineWriter (stalled_reap vs client_gone vs completed) with a structured log event and Prometheus counters, the direct_stream_resume_v1 protocol-v3 capability, and a contract doc. Progressive remux is explicitly excluded from the resume contract. Code written by OpenAI Codex CLI (gpt-5.6-sol) from a Claude-authored spec; reviewed and verified by Claude. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(playback): harden direct stream resume contract * test(playback): cover resume platform contracts --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
50 lines
1.0 KiB
Go
50 lines
1.0 KiB
Go
//go:build windows
|
|
|
|
package playback
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
type windowsFileBasicInfo struct {
|
|
CreationTime int64
|
|
LastAccessTime int64
|
|
LastWriteTime int64
|
|
ChangeTime int64
|
|
FileAttributes uint32
|
|
}
|
|
|
|
func directPlayFilesystemRevision(file *os.File, _ os.FileInfo) (string, bool) {
|
|
handle := windows.Handle(file.Fd())
|
|
|
|
var identity windows.ByHandleFileInformation
|
|
if err := windows.GetFileInformationByHandle(handle, &identity); err != nil {
|
|
return "", false
|
|
}
|
|
|
|
var basic windowsFileBasicInfo
|
|
if err := windows.GetFileInformationByHandleEx(
|
|
handle,
|
|
windows.FileBasicInfo,
|
|
(*byte)(unsafe.Pointer(&basic)),
|
|
uint32(unsafe.Sizeof(basic)),
|
|
); err != nil {
|
|
return "", false
|
|
}
|
|
|
|
size := uint64(identity.FileSizeHigh)<<32 | uint64(identity.FileSizeLow)
|
|
fileID := uint64(identity.FileIndexHigh)<<32 | uint64(identity.FileIndexLow)
|
|
return fmt.Sprintf(
|
|
"windows:%x:%x:%x:%x:%x",
|
|
identity.VolumeSerialNumber,
|
|
fileID,
|
|
basic.ChangeTime,
|
|
basic.LastWriteTime,
|
|
size,
|
|
), true
|
|
}
|