Is your feature request related to a problem? Please describe.
I frequently find myself performing delete operations on files that may or may not exist. Similar to how Cloud Firestore's delete operation works, I would like for the Cloud Storage delete operation to consider a non-existent file as a successful deletion. In other words, I want my delete operation to be considered successful if the file does not exist after the operation completes- regardless of if it did exist before the operation.
Describe the solution you'd like
The delete operation (docs here) takes an optional options object, whose only parameter is currently userProject. I would like a new property to be available that I could use to enable this mechanism on a per-operation basis. The syntax might look something like:
await myBucket.file("thisFileMightNotExist.txt").delete({mustExist: false})
Describe alternatives you've considered
The two alternatives are to either 1) run a File.exists operation first, or 2) handle deletion error in catch block. Both alternatives work, they're just not very elegant. Alternative 1 _technically_ also leaves an unlikely but possible scenario where the file is removed after the the exists operation but before the delete operation.
Additional context
None.
Hi @willbattel, thanks for raising the feature request. I understand where you're coming from, wanting a way for File.delete() to resolve when the file doesn't exists (Error 404 in this case), especially in batch operations.
Looking at your proposed solutions, here are some thoughts:
1) run a File.exists operation first
I'm reluctant to do this as this would incur additional operation cost (object.get is a Class B operation).
2) handle deletion error in catch block.
This could be doable. In that case, we'd modify the library to .catch() the error and in the case its statusCode is 404, we'd resolve the promise. This should already be possible (as is option 1) as a user workaround without changes to the library.
@stephenplusplus Do you think it is reasonable to add to the library?
In that case, we'd modify the library to
.catch()the error and in the case itsstatusCodeis 404, we'd resolve the promise.
A downside to this approach would be that we're being dishonest about what the user asked us. If the file doesn't exist, we didn't delete it (thus, success), we just can't delete it because it doesn't exist. I think the transparency of saying "We would if we could, but we couldn't, so we didn't" is a better approach. Users can always handle the 404 to mean what they want it to in their application code.
To keep in mind, "delete()" is a "ServiceObject" method, meaning it exists on almost every object we have across our APIs. That would mean we would want to back-port an option like this to every other API.
@stephenplusplus Adding a generalized "resolve if end condition met" type flag to ServiceObject could be valuable. I'm sure there are other instances where developers only care about the end state of the object- and not if an action was actually performed to achieve that state. I agree it should not change the default behavior, but being able to enable it in-line without our own catch block would be very nifty.
True! I agree that if we made that an option, it can't hurt. It seems relatively straightforward to implement (although updating all of the inline docs across the repos will be laborious), but I would be okay adding it in. Maybe bucket.delete({ ignore404: true }) or bucket.delete({ ignoreNotFound: true }) or something like that?
Sure. Either ignoreNotFound or ignoreMissing seems reasonable. What implications would this have for other APIs using ServiceObject?
This was released upstream, and here is a PR to officially introduce it here: #1347
Fantastic. Thanks a ton!
@willbattel thank you for the suggestion! 5.6.0 is out with the feature.