@@ -214,8 +214,117 @@ def test_missing_serving_data_is_collected_without_query(self):
214214 "missing SERVING metadata should be removed and become writable" ,
215215 )
216216
217+ def test_event_report_host_down_is_collected_by_intent_lane (self ):
218+ """HOST_DOWN is reconciled by the metadata-only intent lane."""
219+ self .worker_manager .stop_worker (0 )
220+ self .assertTrue (
221+ self .worker_manager .start_worker (
222+ 0 ,
223+ ** {
224+ "kvcm.cache_gc.enabled" : "true" ,
225+ "kvcm.cache_gc.event_report_cleanup_enabled" : "true" ,
226+ "kvcm.cache_gc.scan_interval_ms" : 25 ,
227+ "kvcm.cache_gc.round_pause_ms" : 100 ,
228+ "kvcm.cache_gc.scan_batch_size" : 8 ,
229+ "kvcm.cache_gc.orphan_writing_grace_period_ms" : self ._GRACE_MS ,
230+ "kvcm.cache_gc.max_inflight_delete_requests" : 2 ,
231+ },
232+ )
233+ )
234+ self ._admin_client .close ()
235+ self ._client .close ()
236+ self ._admin_client , self ._client = self ._get_manager_clients ()
237+
238+ event_storage_name = "cache_gc_event_report"
239+ self ._admin_client .add_storage (
240+ {
241+ "trace_id" : f"{ self ._trace_id } _event_storage" ,
242+ "storage" : {
243+ "global_unique_name" : event_storage_name ,
244+ "storage_type" : "ST_EVENT_REPORT_L2" ,
245+ "event_report" : {
246+ "heartbeat_timeout_ms" : 60_000 ,
247+ "cleanup_grace_ms" : 60_000 ,
248+ "liveness_check_interval_ms" : 1_000 ,
249+ },
250+ "check_storage_available_when_open" : False ,
251+ },
252+ }
253+ )
254+ self ._create_topology (
255+ event_report_storage_candidates = [event_storage_name ]
256+ )
257+ instance_id = "cache_gc_event_report_instance"
258+ self ._register_instance (instance_id )
259+ host = "192.168.80.1:8080"
260+ location_uri = f"vineyard://{ host } /mem?source=cache_gc_e2e"
261+ self ._client .report_event (
262+ {
263+ "trace_id" : f"{ self ._trace_id } _event_add" ,
264+ "instance_id" : instance_id ,
265+ "host_ip_port" : host ,
266+ "storage_type" : "ST_EVENT_REPORT_L2" ,
267+ "events" : [
268+ {
269+ "event_type" : "EVENT_NODE_REGISTER" ,
270+ "node_register" : {"mediums" : ["mem" ]},
271+ },
272+ {
273+ "event_type" : "EVENT_BLOCK_ADD" ,
274+ "block_add" : {
275+ "block_key" : str (self ._block_key ),
276+ "medium" : "mem" ,
277+ "specs" : [{"name" : "tp0" , "uri" : location_uri }],
278+ },
279+ },
280+ ],
281+ }
282+ )
283+ visible = self ._client .get_cache_location (
284+ {
285+ "trace_id" : f"{ self ._trace_id } _event_visible" ,
286+ "instance_id" : instance_id ,
287+ "query_type" : "QT_BATCH_GET" ,
288+ "block_keys" : [self ._block_key ],
289+ "block_mask" : {"offset" : 0 },
290+ }
291+ )
292+ self .assertTrue (visible .get ("locations" ))
293+
294+ self ._client .report_event (
295+ {
296+ "trace_id" : f"{ self ._trace_id } _event_down" ,
297+ "instance_id" : instance_id ,
298+ "host_ip_port" : host ,
299+ "storage_type" : "ST_EVENT_REPORT_L2" ,
300+ "events" : [
301+ {"event_type" : "EVENT_HOST_DOWN" , "host_down" : {}}
302+ ],
303+ }
304+ )
305+ self ._wait_metric_at_least (
306+ "cache_gc.event_report_delete_location_count" ,
307+ 1 ,
308+ tags = {"reason" : "down_host" , "status" : "deleted" },
309+ timeout_s = 10 ,
310+ )
311+ self .assertGreaterEqual (
312+ self ._metric_value ("cache_gc.event_report_scan_batch_count" ), 1
313+ )
314+ self .assertEqual (
315+ 0 ,
316+ self ._metric_value (
317+ "cache_gc.event_report_intent_count" ,
318+ tags = {"reason" : "down_host" },
319+ ),
320+ )
321+ self .assertEqual (0 , self ._metric_value ("cache_gc.delete_target_count" ))
322+
217323 def _create_topology (
218- self , meta_storage_type = "dummy" , data_storage_type = "nfs"
324+ self ,
325+ meta_storage_type = "dummy" ,
326+ data_storage_type = "nfs" ,
327+ event_report_storage_candidates = None ,
219328 ):
220329 metadata_uri = (
221330 f"file://{ self .get_workdir ()} /cache_gc_metadata"
@@ -247,6 +356,9 @@ def _create_topology(
247356 "instance_group" : {
248357 "name" : self ._group_name ,
249358 "storage_candidates" : [self ._storage_name ],
359+ "event_report_storage_candidates" : (
360+ event_report_storage_candidates or []
361+ ),
250362 "global_quota_group_name" : "cache_gc_quota" ,
251363 "max_instance_count" : 8 ,
252364 "quota" : {
0 commit comments