Skip to content

Commit 5e3a035

Browse files
committed
Deduplicate Unity instance discovery by port
1 parent e6f9c4f commit 5e3a035

File tree

2 files changed

+48
-12
lines changed

2 files changed

+48
-12
lines changed

MCPForUnity/UnityMcpServer~/src/port_discovery.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from datetime import datetime
2020
from pathlib import Path
2121
import socket
22-
from typing import Optional, List
22+
from typing import Optional, List, Dict
2323

2424
from models import UnityInstanceInfo
2525

@@ -228,7 +228,7 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
228228
Returns:
229229
List of UnityInstanceInfo objects for all discovered instances
230230
"""
231-
instances = []
231+
instances_by_port: Dict[int, tuple[UnityInstanceInfo, datetime]] = {}
232232
base = PortDiscovery.get_registry_dir()
233233

234234
# Scan all status files
@@ -237,7 +237,10 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
237237

238238
for status_file_path in status_files:
239239
try:
240-
with open(status_file_path, 'r') as f:
240+
status_path = Path(status_file_path)
241+
file_mtime = datetime.fromtimestamp(status_path.stat().st_mtime)
242+
243+
with status_path.open('r') as f:
241244
data = json.load(f)
242245

243246
# Extract hash from filename: unity-mcp-status-{hash}.json
@@ -266,6 +269,19 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
266269
logger.debug(f"Instance {project_name}@{hash_value} has heartbeat but port {port} not responding")
267270
continue
268271

272+
freshness = last_heartbeat or file_mtime
273+
274+
existing = instances_by_port.get(port)
275+
if existing:
276+
_, existing_time = existing
277+
if existing_time >= freshness:
278+
logger.debug(
279+
"Skipping stale status entry %s in favor of more recent data for port %s",
280+
status_path.name,
281+
port,
282+
)
283+
continue
284+
269285
# Create instance info
270286
instance = UnityInstanceInfo(
271287
id=f"{project_name}@{hash_value}",
@@ -278,12 +294,14 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
278294
unity_version=data.get('unity_version') # May not be available in current version
279295
)
280296

281-
instances.append(instance)
297+
instances_by_port[port] = (instance, freshness)
282298
logger.debug(f"Discovered Unity instance: {instance.id} on port {instance.port}")
283299

284300
except Exception as e:
285301
logger.debug(f"Failed to parse status file {status_file_path}: {e}")
286302
continue
287303

288-
logger.info(f"Discovered {len(instances)} Unity instances")
289-
return instances
304+
deduped_instances = [entry[0] for entry in sorted(instances_by_port.values(), key=lambda item: item[1], reverse=True)]
305+
306+
logger.info(f"Discovered {len(deduped_instances)} Unity instances (after de-duplication by port)")
307+
return deduped_instances

Server/port_discovery.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from datetime import datetime
2020
from pathlib import Path
2121
import socket
22-
from typing import Optional, List
22+
from typing import Optional, List, Dict
2323

2424
from models import UnityInstanceInfo
2525

@@ -228,7 +228,7 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
228228
Returns:
229229
List of UnityInstanceInfo objects for all discovered instances
230230
"""
231-
instances = []
231+
instances_by_port: Dict[int, tuple[UnityInstanceInfo, datetime]] = {}
232232
base = PortDiscovery.get_registry_dir()
233233

234234
# Scan all status files
@@ -237,7 +237,10 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
237237

238238
for status_file_path in status_files:
239239
try:
240-
with open(status_file_path, 'r') as f:
240+
status_path = Path(status_file_path)
241+
file_mtime = datetime.fromtimestamp(status_path.stat().st_mtime)
242+
243+
with status_path.open('r') as f:
241244
data = json.load(f)
242245

243246
# Extract hash from filename: unity-mcp-status-{hash}.json
@@ -266,6 +269,19 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
266269
logger.debug(f"Instance {project_name}@{hash_value} has heartbeat but port {port} not responding")
267270
continue
268271

272+
freshness = last_heartbeat or file_mtime
273+
274+
existing = instances_by_port.get(port)
275+
if existing:
276+
_, existing_time = existing
277+
if existing_time >= freshness:
278+
logger.debug(
279+
"Skipping stale status entry %s in favor of more recent data for port %s",
280+
status_path.name,
281+
port,
282+
)
283+
continue
284+
269285
# Create instance info
270286
instance = UnityInstanceInfo(
271287
id=f"{project_name}@{hash_value}",
@@ -278,12 +294,14 @@ def discover_all_unity_instances() -> List[UnityInstanceInfo]:
278294
unity_version=data.get('unity_version') # May not be available in current version
279295
)
280296

281-
instances.append(instance)
297+
instances_by_port[port] = (instance, freshness)
282298
logger.debug(f"Discovered Unity instance: {instance.id} on port {instance.port}")
283299

284300
except Exception as e:
285301
logger.debug(f"Failed to parse status file {status_file_path}: {e}")
286302
continue
287303

288-
logger.info(f"Discovered {len(instances)} Unity instances")
289-
return instances
304+
deduped_instances = [entry[0] for entry in sorted(instances_by_port.values(), key=lambda item: item[1], reverse=True)]
305+
306+
logger.info(f"Discovered {len(deduped_instances)} Unity instances (after de-duplication by port)")
307+
return deduped_instances

0 commit comments

Comments
 (0)