Reputation: 2049
I have a google drive app which will auto-save changes. If you have two active sessions then they will overwrite each other. The app supports merging changes but I can't see how to safely integrate this with the drive API. Some options I have considered:
Version safe commits
If failed then fetch latest version, merge and retry
problem: I don't think drive supports this. Previous API versions used etags but I see no mention of this in the current documenation.
Pre-commit check
otherwise download, merge and update
problem: obvious race condition between clients
Post-commit check
if new version higher than expected: download previous version, merge and update
problem: I don't have much faith this is safe. I can see multiple clients getting in edit loops.
Google real-time api - field binding
replace file format with a google rt datamodel
problem: It would require redesigning just for google-rt
Google real-time api - document support
use google rt api external document support
problem: I don't think this solves the problem
I would really like a way to achieve #1 but any suggestions would be helpful. I would be happy enough with a basic locking / handover scheme between clients but I don't think Drive supports that either.
Upvotes: 2
Views: 1232
Reputation: 7915
To follow up on user1828559's answer, the following Java code seems to work well:
private File updateDriveFile(Drive drive, File file, byte[] data) throws IOException {
try {
ByteArrayContent mediaContent = new ByteArrayContent(MIME_TYPE, data);
Drive.Files.Update update = drive.files().update(file.getId(), file, mediaContent);
update.getRequestHeaders().setIfMatch(file.getEtag());
return update.execute();
}
catch (GoogleJsonResponseException e) {
if (isConflictError(e.getDetails())) {
logger.warn("ETag precondition failed, concurrent modification detected!");
return null;
}
throw e;
}
}
private boolean isConflictError(GoogleJsonError error) {
if (error.getCode() == 412) {
final List<GoogleJsonError.ErrorInfo> errors = error.getErrors();
if (errors != null && errors.size() == 1) {
final GoogleJsonError.ErrorInfo errorInfo = errors.get(0);
if ("header".equals(errorInfo.getLocationType()) &&
"If-Match".equals(errorInfo.getLocation()) &&
"conditionNotMet".equals(errorInfo.getReason()))
return true;
}
}
return false;
}
Upvotes: 0
Reputation: 241
According to here, "If-Match" using etags still works. Not sure if it applies to data, but at least it applies to metadata.
Upvotes: 1