001/* 002 * Copyright © 2025 CUI-OpenSource-Software (info@cuioss.de) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.http.client.result; 017 018import java.util.Set; 019 020import static de.cuioss.tools.collect.CollectionLiterals.immutableSet; 021 022/** 023 * HTTP-specific result states that extend the basic CUI result pattern with semantics 024 * tailored for HTTP operations, particularly ETag-aware caching and retry scenarios. 025 * 026 * <h2>State Overview</h2> 027 * <ul> 028 * <li>{@link #FRESH} - Successfully loaded new content from server</li> 029 * <li>{@link #CACHED} - Using cached content (ETag indicates not modified)</li> 030 * <li>{@link #STALE} - Using cached content but it may be outdated</li> 031 * <li>{@link #RECOVERED} - Succeeded after retry attempts</li> 032 * <li>{@link #ERROR} - All attempts failed, using fallback if available</li> 033 * </ul> 034 * 035 * <h2>Usage Patterns</h2> 036 * 037 * <h3>1. ETag-Aware Caching</h3> 038 * <pre> 039 * HttpResultObject<String> result = etagHandler.load(); 040 * if (result.isFresh()) { 041 * // New content loaded, update cache 042 * updateCache(result.getResult(), result.getETag()); 043 * } else if (result.isCached()) { 044 * // Content unchanged, use existing cache 045 * useExistingContent(result.getResult()); 046 * } 047 * </pre> 048 * 049 * <h3>2. Retry Flow Control</h3> 050 * <pre> 051 * if (result.isRecovered()) { 052 * // Succeeded after retries, log for monitoring 053 * logger.info("HTTP operation recovered after {} attempts", 054 * result.getRetryMetrics().getTotalAttempts()); 055 * } else if (result.getState() == ERROR) { 056 * // All retries failed, handle gracefully 057 * handleFailureWithFallback(result); 058 * } 059 * </pre> 060 * 061 * <h2>State Semantics</h2> 062 * <ul> 063 * <li><strong>FRESH</strong>: Content was loaded from server, ETag updated</li> 064 * <li><strong>CACHED</strong>: Server returned 304 Not Modified, content unchanged</li> 065 * <li><strong>STALE</strong>: Using cached content due to error, may be outdated</li> 066 * <li><strong>RECOVERED</strong>: Succeeded after 1+ retry attempts</li> 067 * <li><strong>ERROR</strong>: All retry attempts failed, using default/fallback result</li> 068 * </ul> 069 * 070 * @author Implementation based on CUI result pattern 071 * @see HttpResultObject 072 * @see de.cuioss.uimodel.result.ResultState 073 * @since 1.0 074 */ 075public enum HttpResultState { 076 077 /** 078 * Successfully loaded fresh content from the server. 079 * This indicates the content is new or has been updated since the last request. 080 * ETag has been updated to reflect the current content version. 081 */ 082 FRESH, 083 084 /** 085 * Using cached content because server indicated it hasn't changed. 086 * This is the optimal case for ETag-aware operations where the server 087 * returned HTTP 304 Not Modified, confirming cached content is current. 088 */ 089 CACHED, 090 091 /** 092 * Using cached/fallback content because fresh content couldn't be retrieved. 093 * The cached content may be outdated but provides graceful degradation. 094 * This state indicates potential service degradation that should be monitored. 095 */ 096 STALE, 097 098 /** 099 * Operation succeeded but only after retry attempts. 100 * This indicates temporary network/server issues that were successfully overcome. 101 * Retry metrics should be available for observability. 102 */ 103 RECOVERED, 104 105 /** 106 * All retry attempts failed. 107 * A default or cached result may be available for graceful degradation, 108 * but the primary operation could not be completed successfully. 109 */ 110 ERROR; 111 112 /** 113 * States that indicate successful content retrieval from cache. 114 * These states mean the result can be used reliably for business logic. 115 */ 116 public static final Set<HttpResultState> CACHE_STATES = immutableSet(CACHED, STALE); 117 118 /** 119 * States that indicate successful operation completion. 120 * Content is available and can be used, though STALE and RECOVERED 121 * may warrant logging for monitoring purposes. 122 */ 123 public static final Set<HttpResultState> SUCCESS_STATES = immutableSet(FRESH, CACHED, RECOVERED); 124 125 /** 126 * States that indicate content freshness concerns. 127 * These states suggest monitoring or validation may be appropriate. 128 */ 129 public static final Set<HttpResultState> DEGRADED_STATES = immutableSet(STALE, RECOVERED); 130 131 /** 132 * States that must be handled before accessing the result. 133 * Overrides the base ResultState behavior to include STALE state 134 * as it may require special handling in some contexts. 135 */ 136 public static final Set<HttpResultState> MUST_BE_HANDLED = immutableSet(ERROR, STALE); 137}