@@ -3231,6 +3231,62 @@ HttpTransact::handle_cache_write_lock(State *s)
32313231 }
32323232}
32333233
3234+ // /////////////////////////////////////////////////////////////////////////////
3235+ // Name : handle_deferred_cache_write_complete
3236+ // Description: Called after cache write opens for deferred cache write.
3237+ // We already have the server response headers, so we continue
3238+ // with cache write handling.
3239+ //
3240+ // Possible Next States From Here:
3241+ // - handle_cache_operation_on_forward_server_response (if cache write succeeded)
3242+ // - handle_no_cache_operation_on_forward_server_response (if cache write failed)
3243+ //
3244+ // /////////////////////////////////////////////////////////////////////////////
3245+ void
3246+ HttpTransact::handle_deferred_cache_write_complete (State *s)
3247+ {
3248+ TxnDbg (dbg_ctl_http_trans, " handle_deferred_cache_write_complete" );
3249+ TxnDbg (dbg_ctl_http_seq, " Entering handle_deferred_cache_write_complete" );
3250+
3251+ ink_assert (s->cache_info .action == CacheAction_t::PREPARE_TO_WRITE);
3252+
3253+ switch (s->cache_info .write_lock_state ) {
3254+ case CacheWriteLock_t::SUCCESS:
3255+ // Cache write lock acquired successfully
3256+ TxnDbg (dbg_ctl_http_trans, " [hdcwc] cache write lock acquired" );
3257+ SET_UNPREPARE_CACHE_ACTION (s->cache_info );
3258+ // Now we have WRITE action, handle the response with caching
3259+ handle_cache_operation_on_forward_server_response (s);
3260+ return ;
3261+
3262+ case CacheWriteLock_t::FAIL:
3263+ // Could not get cache write lock, continue without caching
3264+ TxnDbg (dbg_ctl_http_trans, " [hdcwc] cache write lock failed, continuing without cache" );
3265+ Metrics::Counter::increment (http_rsb.cache_open_write_fail_count );
3266+ s->cache_info .action = CacheAction_t::NO_ACTION;
3267+ s->cache_info .write_status = CacheWriteStatus_t::LOCK_MISS;
3268+ break ;
3269+
3270+ case CacheWriteLock_t::READ_RETRY:
3271+ // This shouldn't happen for deferred write since we don't have an object to read
3272+ TxnDbg (dbg_ctl_http_trans, " [hdcwc] unexpected READ_RETRY for deferred write" );
3273+ s->cache_info .action = CacheAction_t::NO_ACTION;
3274+ s->cache_info .write_status = CacheWriteStatus_t::LOCK_MISS;
3275+ break ;
3276+
3277+ case CacheWriteLock_t::INIT:
3278+ default :
3279+ ink_release_assert (0 );
3280+ break ;
3281+ }
3282+
3283+ // If we get here, cache write failed - continue without caching
3284+ // The original handle_no_cache_operation_on_forward_server_response will be called
3285+ // but we need to skip the deferred cache write check since we just tried it
3286+ // s->cache_open_write_deferred is already false from the first call
3287+ handle_no_cache_operation_on_forward_server_response (s);
3288+ }
3289+
32343290// /////////////////////////////////////////////////////////////////////////////
32353291// Name : HandleCacheOpenReadMiss
32363292// Description: cache looked up, miss or hit, but needs authorization
@@ -3276,6 +3332,13 @@ HttpTransact::HandleCacheOpenReadMiss(State *s)
32763332 s->cache_info .action = CacheAction_t::NO_ACTION;
32773333 } else if (s->api_server_response_no_store ) { // plugin may have decided not to cache the response
32783334 s->cache_info .action = CacheAction_t::NO_ACTION;
3335+ } else if (s->txn_conf ->cache_defer_write_on_miss ) {
3336+ // Defer cache open write until after response headers are received.
3337+ // This avoids cache overhead for non-cacheable responses but may
3338+ // affect read-while-write and request coalescing for popular URLs.
3339+ s->cache_open_write_deferred = true ;
3340+ s->cache_info .action = CacheAction_t::NO_ACTION;
3341+ TxnDbg (dbg_ctl_http_trans, " [HandleCacheOpenReadMiss] deferring cache open write until response" );
32793342 } else {
32803343 HttpTransact::set_cache_prepare_write_action_for_new_request (s);
32813344 }
@@ -4677,6 +4740,24 @@ HttpTransact::handle_no_cache_operation_on_forward_server_response(State *s)
46774740 TxnDbg (dbg_ctl_http_trans, " (hncoofsr)" );
46784741 TxnDbg (dbg_ctl_http_seq, " Entering handle_no_cache_operation_on_forward_server_response" );
46794742
4743+ // Check if we deferred the cache open write and the response is cacheable.
4744+ // If so, we need to open the cache for write now.
4745+ if (s->cache_open_write_deferred && s->txn_conf ->cache_http ) {
4746+ bool cacheable = is_response_cacheable (s, &s->hdr_info .client_request , &s->hdr_info .server_response );
4747+ TxnDbg (dbg_ctl_http_trans, " [hncoofsr] deferred cache write, response %s cacheable" , cacheable ? " is" : " is not" );
4748+
4749+ if (cacheable) {
4750+ // Response is cacheable - open the cache for write now
4751+ s->cache_open_write_deferred = false ;
4752+ s->cache_info .action = CacheAction_t::PREPARE_TO_WRITE;
4753+ s->cache_info .write_lock_state = CacheWriteLock_t::INIT;
4754+ // After cache write opens, continue with handle_cache_operation_on_forward_server_response
4755+ TRANSACT_RETURN (StateMachineAction_t::CACHE_ISSUE_WRITE, handle_deferred_cache_write_complete);
4756+ }
4757+ // Not cacheable - continue with no-cache operation
4758+ s->cache_open_write_deferred = false ;
4759+ }
4760+
46804761 bool keep_alive = s->current .server ->keep_alive == HTTPKeepAlive::KEEPALIVE;
46814762 const char *warn_text = nullptr ;
46824763
0 commit comments