[grid] Store Dynamic Grid videos in a per-session subfolder via SE_VIDEO_SESSION_SUBFOLDER - #17856
Conversation
…ording Inline recording binds the assets root to /videos, so videos from every session landed flat in the assets root. When the Node opts in with SE_VIDEO_SESSION_SUBFOLDER=true, the recorder now creates assets/<sessionId>/ itself, matching the layout the external video container already gets from its per-session bind mount. The recorder only honours the subfolder while it owns the file name, so subfolder mode forces SE_VIDEO_FILE_NAME=auto. The external video container is pinned to false because every SE_* variable on the Node is copied into child containers and would otherwise nest twice. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both recording modes mount the assets volume at /videos, so a session subfolder written by the recorder is already the final asset location. When the Node opts in, the browser container and the video sidecar get SE_VIDEO_SESSION_SUBFOLDER=true and the recorder takes over naming; injecting jobName.mp4 would put the recorder on its fixed-name path, which ignores the subfolder. Sessions in this mode carry no relocation target, which the following change uses to skip the Pod termination wait. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
stop() waited up to terminationGracePeriodSeconds + 10 for the Pod to reach a terminal phase before relocating the video, even when there was no video to relocate. That is now the normal case in session subfolder mode, and was already the case with SE_VIDEO_FILE_NAME=auto. The wait moves into relocateVideoFiles(), after the guard that decides whether a file has to be moved at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR Summary by QodoDynamic Grid: opt into SE_VIDEO_SESSION_SUBFOLDER for per-session video layout
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1. Duplicate K8s video env
|
|
Code review by qodo was updated up to the latest commit 5ad47d6 |
Inline recording binds the assets root, so a flat layout scatters every session's video into it. The subfolder and the recorder-managed file name are now enforced over anything inherited from the Node environment rather than opted into, since neither inherited value produces a usable layout on this path. The external video container gets a blank SE_VIDEO_SESSION_SUBFOLDER instead of "false", so a Node-level setting cannot pass through and the image default stays in charge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Viet Nguyen Duc <nguyenducviet4496@gmail.com>
5ad47d6 to
4706596
Compare
|
Code review by qodo was updated up to the latest commit 4706596 |
🔗 Related Issues
Follows up on docker-selenium SeleniumHQ/docker-selenium@752d1bf, which added
SE_VIDEO_SESSION_SUBFOLDERto the video images.💥 What does this PR do?
Makes Dynamic Grid use
SE_VIDEO_SESSION_SUBFOLDERso the recorder writes videos straight to<assets>/<sessionId>/, which is where the Grid serves session assets from.Docker, inline recording (
--docker-video-imagenot set): the browser container binds the assets root to/videos, so every session's video used to land flat in the assets root. The recorder now always creates the session folder itself, matching the layout the external video container already gets from its per-session bind mount.Kubernetes (both inline recording and the video sidecar): the assets volume is mounted at
/videosand at the assets path, so a session subfolder written by the recorder is the final location. Grid therefore no longer has to wait for the Pod to terminate and move the file afterwards. This one is opt-in viaSE_VIDEO_SESSION_SUBFOLDER=trueon the Node, and behaviour is unchanged when it is unset.🔧 Implementation Notes
On Kubernetes the variable is read from the Node's own environment (default
false) rather than added as a CLI flag, matching howKubernetesSessionFactoryalready readsSE_VIDEO_FILE_NAME,SE_VIDEO_FILE_NAME_SUFFIXandSE_VIDEO_FILE_NAME_TRIM_REGEX. SincesetEnvVarsToContainer()already copies everySE_*variable into child containers, opting in is a single Node-level setting.Three details drove the design:
Subfolder mode implies recorder-managed naming. In
video.shthe subfolder branch only exists on the dynamic naming path, so a fixedSE_VIDEO_FILE_NAMEsilently disables the feature. Grid therefore forcesSE_VIDEO_FILE_NAME=autoin this mode and stops injecting<jobName>.mp4on Kubernetes. On the Docker inline path both this and the subfolder are enforced over anything inherited from the Node (with a warning when a fixed name is discarded), because neither inherited value produces a usable layout when the mount is the assets root.The Docker video sidecar gets a blank
SE_VIDEO_SESSION_SUBFOLDER. Its bind mount is already per-session (assets/<sessionId>→/videos), so inheriting a Node-leveltruewould produceassets/<id>/<id>/video.mp4. Blanking rather than settingfalsestops the passthrough while leaving the image's own default in charge — both recorders treat an empty value as disabled.KubernetesSession.stop()only waits for the Pod when a file must be moved. The wait (terminationGracePeriodSeconds + 10) existed solely to let the recorder finish before relocating, sowaitForPodTerminated()moved insiderelocateVideoFiles(), after the guard. This also removes an existing cost: withSE_VIDEO_FILE_NAME=auto,videoFileNamewas alreadynulland nothing was relocated, yet every session still paid the full grace period.Alternative considered and rejected: changing the Docker video container to mount the assets root and use the subfolder for one uniform mechanism. It would have altered a working path for no gain.
Older docker-selenium images simply ignore the variable and keep today's flat layout; there is no version check.
🤖 AI assistance
💡 Additional Considerations
Worth aligning upstream:
video.shhonoursSE_VIDEO_SESSION_SUBFOLDERonly on its dynamic-naming path, whilevideo_service.pyhonours it for fixed names too. Grid works around this by forcingSE_VIDEO_FILE_NAME=auto; making the two recorders consistent in docker-selenium would let that workaround go away.No cross-binding impact — this is Grid-side Java only, and no binding exposes video asset layout.
Testing: new
DockerSessionFactoryTest(5 cases) andKubernetesSessionTest(2 cases), plus 3 cases added toKubernetesSessionFactoryTest. All 132 tests in//java/test/org/openqa/selenium/grid/...at sizesmallpass, spotbugs included.🔄 Types of changes
🤖 Generated with Claude Code