Każdy zasób ma pole wersji, które zmienia się za każdym razem, gdy zasób ulega zmianie – pole etag
. Etagi są standardową częścią protokołu HTTP i są obsługiwane w interfejsie API kalendarza w 2 przypadkach:
- modyfikacji zasobów, aby mieć pewność, że w międzyczasie nie nastąpiła żadna inna operacja zapisu do tego zasobu (modyfikacja warunkowa);
- na pobieranie zasobów, aby pobierać dane zasobu tylko wtedy, gdy zasób się zmienił (warunkowe pobieranie);
Modyfikacja warunkowa
Jeśli chcesz zaktualizować lub usunąć zasób tylko wtedy, gdy nie zmienił się od ostatniego pobrania, możesz określić nagłówek If-Match
, który zawiera wartość etaga z poprzedniego pobrania. Jest to bardzo przydatne, aby zapobiec przypadkowym modyfikacjom zasobów. Klienci mogą ponownie pobrać zasób i ponownie zastosować zmiany.
Jeśli wpis (i jego etag) nie zmienił się od ostatniego pobrania, modyfikacja się powiedzie i zwrócona zostanie nowa wersja zasobu z nowym tagiem etag. W przeciwnym razie otrzymasz kod odpowiedzi 412 (Warunek wstępny nie spełniony).
Poniżej znajduje się fragment kodu, który pokazuje, jak wykonywać modyfikacje warunkowe za pomocą biblioteki klienta Java.
private static void run() throws IOException { // Create a test event. Event event = Utils.createTestEvent(client, "Test Event"); System.out.println(String.format("Event created: %s", event.getHtmlLink())); // Pause while the user modifies the event in the Calendar UI. System.out.println("Modify the event's description and hit enter to continue."); System.in.read(); // Modify the local copy of the event. event.setSummary("Updated Test Event"); // Update the event, making sure that we don't overwrite other changes. int numAttempts = 0; boolean isUpdated = false; do { Calendar.Events.Update request = client.events().update("primary", event.getId(), event); request.setRequestHeaders(new HttpHeaders().setIfMatch(event.getEtag())); try { event = request.execute(); isUpdated = true; } catch (GoogleJsonResponseException e) { if (e.getStatusCode() == 412) { // A 412 status code, "Precondition failed", indicates that the etag values didn't // match, and the event was updated on the server since we last retrieved it. Use // {@link Calendar.Events.Get} to retrieve the latest version. Event latestEvent = client.events().get("primary", event.getId()).execute(); // You may want to have more complex logic here to resolve conflicts. In this sample we're // simply overwriting the summary. latestEvent.setSummary(event.getSummary()); event = latestEvent; } else { throw e; } } numAttempts++; } while (!isUpdated && numAttempts <= MAX_UPDATE_ATTEMPTS); if (isUpdated) { System.out.println("Event updated."); } else { System.out.println(String.format("Failed to update event after %d attempts.", numAttempts)); } }
Wybieranie warunkowe
Jeśli chcesz pobrać zasób tylko wtedy, gdy zmienił się od ostatniego pobrania, możesz określić nagłówek If-None-Match
, który zawiera wartość etaga z poprzedniego pobrania. Jeśli wpis (a zatem jego etag) zmienił się od ostatniego pobrania, zwrócona zostanie nowa wersja zasobu z nowym etagem. W przeciwnym razie otrzymasz kod odpowiedzi 304 (nie zmodyfikowano).
Poniżej znajduje się fragment kodu, który pokazuje, jak wykonać wyszukiwanie warunkowe za pomocą biblioteki klienta Java.
private static void run() throws IOException { // Create a test event. Event event = Utils.createTestEvent(client, "Test Event"); System.out.println(String.format("Event created: %s", event.getHtmlLink())); // Pause while the user modifies the event in the Calendar UI. System.out.println("Modify the event's description and hit enter to continue."); System.in.read(); // Fetch the event again if it's been modified. Calendar.Events.Get getRequest = client.events().get("primary", event.getId()); getRequest.setRequestHeaders(new HttpHeaders().setIfNoneMatch(event.getEtag())); try { event = getRequest.execute(); System.out.println("The event was modified, retrieved latest version."); } catch (GoogleJsonResponseException e) { if (e.getStatusCode() == 304) { // A 304 status code, "Not modified", indicates that the etags match, and the event has // not been modified since we last retrieved it. System.out.println("The event was not modified, using local version."); } else { throw e; } } }