feat: [OCISDEV-900] Connect storageprovider with coordinator instead of driver - #721
feat: [OCISDEV-900] Connect storageprovider with coordinator instead of driver#721LarsJurgensen wants to merge 8 commits into
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
b1626ed to
6b608d1
Compare
LukasHirt
left a comment
There was a problem hiding this comment.
Two correctness regressions, one reachability concern, two cleanups.
Blocking:
TouchFile's create-only symlink leaks an orphaned node on a concurrent-create race (pkg/storage/utils/decomposedfs/tree/tree.go:175).OC-FileIdis now permanently omitted from TUS responses for newly-created files (pkg/rhttp/datatx/manager/tus/tus.go:216).
Worth a look:
3. This PR is what makes pkg/upload's postprocessing path live for the dataprovider — and that path has no guard against a node vanishing mid-postprocessing (internal/http/services/dataprovider/dataprovider.go:117).
Minor:
4. Doubled NATS subscriptions for combined decomposedfs+dataprovider deployments (same line).
5. getCoordinator duplicated near-verbatim with storageprovider.go:234 (internal/http/services/dataprovider/dataprovider.go:146).
| if err = os.Symlink(relativeNodePath, childNameLink); err != nil { | ||
| return errors.Wrap(err, "Decomposedfs: could not symlink child entry") | ||
| relativeNodePath := filepath.Join("../../../../../", lookup.Pathify(n.ID, 4, 2)) | ||
| if err = os.Symlink(relativeNodePath, childNameLink); err != nil { |
There was a problem hiding this comment.
The comment above claims the loser "gets AlreadyExists and its CAS loop re-reads and retries" — no such retry exists anywhere in the call chain (touchNode → Decomposedfs.TouchFile → here, each called exactly once, no re-read). The only CAS loop in the repo is in receivedsharecache.go for OCISDEV-855, an unrelated feature — looks like the comment got copied from there without the retry logic.
Net effect: on a real race, the node file/xattrs written above are permanently orphaned when the symlink loses, and neither session.Cleanup nor Decomposedfs.TouchFile's error path removes them.
There was a problem hiding this comment.
The only CAS loop in the repo is in receivedsharecache.go for OCISDEV-855, an unrelated feature
It's unrelated in a way. But the share service is also "uploading" files, so going through this logic. In the old upload flow, it did not return in error, but overwrite the file. In OCISDEV-855 this was fixed, to return an error and have a retry loop in share service. Now, the implementation lives in a different place, so we need the same (or very similar) change again. So two concurrent touchfile operations now make the second one fail & the cache service retries it. There are tests for this, which failed before this change, and pass now.
There was a problem hiding this comment.
no such retry exists anywhere in the call chain
This is the call chain:
retryPersist (20-attempt CAS loop) receivedsharecache.go:232
→ persist → storage.Upload (IfNoneMatch=*) receivedsharecache.go:382
→ CS3.Upload → InitiateFileUpload cs3.go:228
→ storageprovider.InitiateFileUpload storageprovider.go:462
→ coordinator.touchNode coordinator.go:304
→ Decomposedfs.TouchFile decomposedfs.go:566
→ tree.TouchFile: os.Symlink → AlreadyExists tree.go:175-177
There was a problem hiding this comment.
My bad with the chain. Just a question then:
Doesn't TouchFile write the node file + xattrs before attempting the symlink? And doesn't session.Cleanup on AlreadyExists only remove the upload session's bin/info, not that node? So wouldn't the loser's node stay orphaned regardless of whether the caller retries? And for plain PUT/TUS uploads with no CAS wrapper, is there any retry at all on a concurrent-create race, or does that caller just hit an error plus the same leak?
Wire storageprovider and dataprovider to the upload coordinator. This is the final step that makes TUS, postprocessing, AV scanning, and session management driver-independent.
storageprovider.InitiateFileUploadroutes throughcoord.InitiateUploadinstead offs.InitiateUploaddatatx.DataTX.Handlergains acoordargument alongside the driver; all three implementations (simple, spaces, tus) updatedcoord.Upload; TUS registerscoord.UseIninstead of the driver'sUseInComposableFScheck in the TUS manager removed; the coordinator satisfies the tusd data store interface for every driverPostprocessingFinished,PostprocessingStepFinished,RestartPostprocessing,CleanUpload; the coordinator owns thoseRevertRevisionunder a separate consumer group (<group>-revisions) so it gets its own copy without contending with the coordinator's groupupload_directoryconfig key; required for drivers with no local filesystem root