I think you may have a user-process to implementation mismatch here.
First: will a user honestly want to perform multiple changes to a file simultaneously?
A rename (which may or may not include a change of path?), change of ownership, and perhaps change of file contents (for sake of argument) seem like separate actions.
Lets take the case where the answer is "yes" - your users really do want to make these changes simultaneously.
In that case, I'd strongly recommend against any implementation that sends multiple events - RenameFileCommand
, MoveFileCommand
, ChangeOwnerCommand
- to represent this single user intent.
Why? Because events can fail. Maybe its extremely rare, but your user submitted an operation that looked atomic - if a single one of the downstream events fails, then your application state is now invalid.
You are also inviting race hazards on a resource that is clearly shared between each of the event handlers. You will need to write "ChangeOwnerCommand" in such a way that the file name and file path do not matter, because they could be out of date by the time the command is received.
When implementing a non-event driven restful system with moving and renaming files, I prefer to ensure consistency by using something like an eTag system - ensure that the version of the resource being edited is the version that the user last retrieved, and fail if it has been modified since then. But if you are dispatching multiple commands for this single user operation, you will need to increment your resource version after each command - so you have no way to know that the resource the user is editing really is the same version as the resource they last read.
What I mean by that is - what if someone else performs another operation on the file at nearly the same time. The 6 commands could stack up in any order. If we had just 2 atomic commands, the earlier command could succeed and the later command could fail "resource has been modified since it was last retrieved". But there is no protection against this when the commands are not atomic, so system consistency is violated.
Interestingly there is a movement toward something like event based architecture in REST, called "Rest without PUT", recommended in the Thoughtworks technology radar, Jan 2015. There is a considerably longer blog about Rest without PUT here.
Essentially, the idea is that POST, PUT, DELETE and GET are fine for small applications, but when you need to start assuming how put and post and delete might be interpreted at the other end, you introduce coupling. (e.g. "when I DELETE the resource associated with my bank account, the account should be closed") And the solution proposed is to treat REST in a more Event sourced way. i.e. Lets POST the user intent as a single event resource.
The other case is simpler. If your users don't want to do all those operations simultaneously, don't let them. POST an event for each user intent. Now you can use etag versioning on your resources.
As for the other applications which are using a very different API to your resources. That smells like trouble. Can you construct a facade of the old API on top of your RESTful API and point them at the facade? i.e. expose a service that performs multiple updates to a file in sequence via the REST server?
If you neither build the RESTful interface on top of the old solution, nor build a facade of the old interface on top of the REST solution, and attempt to maintain both APIs pointing at a shared data resource, you will experience major headaches.