穩定 Ollama embedding GCP 失敗熔斷
All checks were successful
CD Pipeline / deploy (push) Successful in 1m5s

This commit is contained in:
OoO
2026-05-25 12:28:44 +08:00
parent e1c9499c1c
commit 0ade55469e
9 changed files with 140 additions and 11 deletions

View File

@@ -200,6 +200,21 @@ def test_get_ollama_host_falls_back_to_resolve_without_env(monkeypatch):
assert host.startswith('http://')
def test_config_ollama_compat_constants_do_not_probe_network(monkeypatch):
monkeypatch.setenv('OLLAMA_HOST', 'http://192.168.0.188:11434')
monkeypatch.setenv('HERMES_URL', 'http://192.168.0.188:11434')
monkeypatch.setenv('EMBEDDING_HOST', 'http://192.168.0.188:11434')
monkeypatch.setenv('OLLAMA_HOST_PRIMARY', 'http://34.143.170.20:11434')
with patch('services.ollama_service.requests.get') as mock_get:
import config
importlib.reload(config)
mock_get.assert_not_called()
assert config.OLLAMA_HOST == 'http://34.143.170.20:11434'
assert config.HERMES_URL == 'http://34.143.170.20:11434'
assert config.EMBEDDING_HOST == 'http://34.143.170.20:11434'
def test_get_embedding_host_prefers_env(monkeypatch):
monkeypatch.setenv('EMBEDDING_HOST', 'http://192.168.0.111:11434')
import config

View File

@@ -31,11 +31,13 @@ def _reset_state():
oss._resolved_host_cache['host'] = None
oss._resolved_host_cache['ts'] = 0
oss._fallback_111_circuit_cache.update({'blocked': False, 'reason': '', 'ts': 0})
oss._embedding_gcp_failure_circuit.update({'blocked_until': 0.0, 'notice_ts': 0.0, 'tried': ()})
yield
oss._unhealthy_marks.clear()
oss._resolved_host_cache['host'] = None
oss._resolved_host_cache['ts'] = 0
oss._fallback_111_circuit_cache.update({'blocked': False, 'reason': '', 'ts': 0})
oss._embedding_gcp_failure_circuit.update({'blocked_until': 0.0, 'notice_ts': 0.0, 'tried': ()})
# ═══════════════════════════════════════════════════════════════════════════
@@ -407,6 +409,37 @@ def test_embedding_fallback_disabled_uses_gcp_chain_when_resolver_returns_111():
assert oss.OLLAMA_HOST_FALLBACK not in posted_hosts
def test_embedding_fallback_disabled_opens_short_gcp_failure_circuit():
"""GCP-A/GCP-B 全掛時,背景 embedding 短暫熔斷,避免下一筆立刻重打兩台。"""
import requests
from services import ollama_service as oss
from services.ollama_service import OllamaService
svc = OllamaService()
with patch('services.ollama_service.EMBED_GCP_FAILURE_COOLDOWN_SEC', 60), \
patch('services.ollama_service.resolve_ollama_host', side_effect=[
oss.OLLAMA_HOST_PRIMARY,
oss.OLLAMA_HOST_SECONDARY,
oss.OLLAMA_HOST_PRIMARY,
]), \
patch.dict('os.environ', {}, clear=False), \
patch(
'services.ollama_service.requests.post',
side_effect=requests.Timeout('gcp timeout'),
) as mock_post:
import os
os.environ.pop('EMBEDDING_HOST', None)
first = svc.generate_embedding('test text', allow_111_fallback=False)
second = svc.generate_embedding('another text', allow_111_fallback=False)
posted_hosts = [call.args[0].split('/api/embed')[0] for call in mock_post.call_args_list]
assert first == []
assert second == []
assert posted_hosts == [oss.OLLAMA_HOST_PRIMARY, oss.OLLAMA_HOST_SECONDARY]
assert oss._embedding_gcp_failure_circuit['blocked_until'] > 0
def test_embedding_ignores_111_embedding_host_when_fallback_disabled():
"""EMBEDDING_HOST 若誤設 111背景 embedding 仍回 GCP resolver不直接棄跑。"""
from services import ollama_service as oss