Skip to content

Commit fca6ec6

Browse files
feature: redis
1 parent 8629dda commit fca6ec6

File tree

4 files changed

+193
-181
lines changed

4 files changed

+193
-181
lines changed

backend/src/infrastructure/adapters/outbound_redis_adapter.py

Lines changed: 92 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,11 @@
1010
from src.domain.dto.formation import Formation
1111
from src.domain.dto.project import Project
1212
from src.domain.dto.social_media import SocialMedia
13-
from src.infrastructure.ports.repository_interface import RepositoryInterface
13+
from src.infrastructure.ports.cache_provider_interface import CacheProvider
1414
from src.infrastructure.utils.logger import logger
1515

1616

17-
class RedisAdapter(RepositoryInterface):
18-
"""
19-
Adaptador para o Redis que implementa a interface RepositoryInterface.
20-
Este adaptador fornece um cache em memória com fallback para outro repositório.
21-
"""
22-
17+
class RedisAdapter(CacheProvider):
2318
# Configurações padrão do Redis
2419
REDIS_HOST = os.getenv("REDIS_HOST", "localhost")
2520
REDIS_PORT = int(os.getenv("REDIS_PORT", "6379"))
@@ -36,194 +31,117 @@ class RedisAdapter(RepositoryInterface):
3631
COMPANY_DURATION_KEY = "portfolio:company_duration"
3732
TOTAL_EXPERIENCE_KEY = "portfolio:total_experience"
3833

39-
def __init__(self, fallback_repository: Optional[RepositoryInterface] = None, **redis_kwargs) -> None:
40-
"""
41-
Inicializa o adaptador do Redis.
42-
43-
Args:
44-
fallback_repository: Repositório de fallback opcional para buscar dados quando não estiverem em cache
45-
**redis_kwargs: Argumentos adicionais para a conexão com o Redis
46-
"""
47-
self.fallback_repository = fallback_repository
34+
def __init__(self) -> None:
4835
self.redis = redis.Redis(
4936
host=self.REDIS_HOST,
5037
port=self.REDIS_PORT,
5138
password=self.REDIS_PASSWORD,
5239
db=self.REDIS_DB,
53-
decode_responses=True,
54-
**redis_kwargs
40+
decode_responses=True
5541
)
56-
57-
# Testa a conexão com o Redis
42+
5843
try:
5944
self.redis.ping()
6045
except RedisError as e:
61-
logger.error(f"Erro ao conectar ao Redis: {e}")
62-
if not fallback_repository:
63-
raise RuntimeError("Falha ao conectar ao Redis e nenhum repositório de fallback fornecido")
64-
65-
def get_all_projects(self) -> List[Project]:
66-
"""Obtém todos os projetos do cache ou do repositório de fallback."""
67-
68-
try:
69-
projects_data_from_cache = self.redis.get(self.PROJECTS_KEY)
46+
logger.error(f"Redis Connection Error: {e}")
47+
raise
48+
49+
def get_cache_data_by_key(self, key: str):
50+
try:
51+
data = self.redis.get(key)
52+
if not data:
53+
return []
54+
return json.loads(data)
7055
except RedisError as e:
71-
logger.error(f"Erro ao acessar o Redis: {e}")
72-
if self.fallback_repository:
73-
return self.fallback_repository.get_all_projects()
56+
logger.error(f"Redis GET Key Error: {e}")
7457
raise
75-
76-
if projects_data_from_cache:
77-
project_data = json.loads(projects_data_from_cache)
78-
return [Project(**project) if isinstance(project, dict) else project
79-
for project in (project_data or [])]
80-
else:
81-
project_data = self.fallback_repository.get_all_projects() if self.fallback_repository else []
82-
self.redis.setex(
83-
self.PROJECTS_KEY,
84-
self.REDIS_TTL,
85-
json.dumps(project_data, default=str)
86-
)
87-
return project_data
88-
58+
59+
def get_all_projects(self) -> List[Project]:
60+
projects_data = self.get_cache_data_by_key(self.PROJECTS_KEY)
61+
62+
return [Project(**project) for project in projects_data]
63+
8964
def get_all_formations(self) -> List[Formation]:
90-
"""Obtém todas as formações do cache ou do repositório de fallback."""
91-
try:
92-
formations_data_from_cache = self.redis.get(self.FORMATIONS_KEY)
65+
formations_data = self.get_cache_data_by_key(self.FORMATIONS_KEY)
66+
67+
return [Formation(**project) for project in formations_data]
68+
69+
def get_all_certifications(self) -> List[Certification]:
70+
certifications_data = self.get_cache_data_by_key(self.CERTIFICATIONS_KEY)
71+
72+
return [Certification(**project) for project in certifications_data]
73+
74+
def get_all_experiences(self) -> List[Experience]:
75+
experiences_data = self.get_cache_data_by_key(self.EXPERIENCES_KEY)
76+
77+
return [Experience(**project) for project in experiences_data]
78+
79+
def get_all_social_media(self) -> List[SocialMedia]:
80+
social_media_data = self.get_cache_data_by_key(self.SOCIAL_MEDIA_KEY)
81+
82+
return [SocialMedia(**project) for project in social_media_data]
83+
84+
def get_company_duration(self) -> List[CompanyDuration]:
85+
company_duration_data = self.get_cache_data_by_key(self.COMPANY_DURATION_KEY)
86+
87+
return [CompanyDuration(**project) for project in company_duration_data]
88+
89+
def get_total_experience(self) -> Dict[str, Any]:
90+
total_experience_data = self.get_cache_data_by_key(self.TOTAL_EXPERIENCE_KEY)
91+
92+
return total_experience_data
93+
94+
def set_projects(self, list_projects: List[Project]):
95+
try:
96+
data = [project.to_dict() for project in list_projects]
97+
self.redis.set(self.PROJECTS_KEY, json.dumps(data), ex=self.REDIS_TTL)
9398
except RedisError as e:
94-
logger.error(f"Erro ao acessar o Redis: {e}")
95-
if self.fallback_repository:
96-
return self.fallback_repository.get_all_formations()
99+
logger.error(f"Redis setting Key -> {self.PROJECTS_KEY} Error: {e}")
97100
raise
98-
99-
if formations_data_from_cache:
100-
formations_data = json.loads(formations_data_from_cache)
101-
return [Formation(**formation) if isinstance(formation, dict) else formation
102-
for formation in (formations_data or [])]
103-
else:
104-
formations_data = self.fallback_repository.get_all_formations() if self.fallback_repository else []
105-
self.redis.setex(
106-
self.FORMATIONS_KEY,
107-
self.REDIS_TTL,
108-
json.dumps(formations_data, default=str)
109-
)
110-
return [Formation(**formation) if isinstance(formation, dict) else formation
111-
for formation in (formations_data or [])]
112-
113-
def get_all_certifications(self) -> List[Certification]:
114-
"""Obtém todas as certificações do cache ou do repositório de fallback."""
115-
try:
116-
certs_data_from_cache = self.redis.get(self.CERTIFICATIONS_KEY)
101+
102+
def set_formations(self, list_formations: List[Formation]):
103+
try:
104+
data = [formation.to_dict() for formation in list_formations]
105+
self.redis.set(self.FORMATIONS_KEY, json.dumps(data), ex=self.REDIS_TTL)
117106
except RedisError as e:
118-
logger.error(f"Erro ao acessar o Redis: {e}")
119-
if self.fallback_repository:
120-
return self.fallback_repository.get_all_certifications()
107+
logger.error(f"Redis setting Key -> {self.FORMATIONS_KEY} Error: {e}")
121108
raise
122-
123-
if certs_data_from_cache:
124-
certs_data = json.loads(certs_data_from_cache)
125-
return [Certification(**cert) if isinstance(cert, dict) else cert
126-
for cert in (certs_data or [])]
127-
else:
128-
certs_data = self.fallback_repository.get_all_certifications() if self.fallback_repository else []
129-
self.redis.setex(
130-
self.CERTIFICATIONS_KEY,
131-
self.REDIS_TTL,
132-
json.dumps(certs_data, default=str)
133-
)
134-
return [Certification(**cert) if isinstance(cert, dict) else cert
135-
for cert in (certs_data or [])]
136-
137-
def get_all_experiences(self) -> List[Experience]:
138-
"""Obtém todas as experiências do cache ou do repositório de fallback."""
139-
try:
140-
exp_data_from_cache = self.redis.get(self.EXPERIENCES_KEY)
109+
110+
def set_certifications(self, list_certifications: List[Certification]):
111+
try:
112+
data = [certification.to_dict() for certification in list_certifications]
113+
self.redis.set(self.CERTIFICATIONS_KEY, json.dumps(data), ex=self.REDIS_TTL)
141114
except RedisError as e:
142-
logger.error(f"Erro ao acessar o Redis: {e}")
143-
if self.fallback_repository:
144-
return self.fallback_repository.get_all_experiences()
115+
logger.error(f"Redis setting Key -> {self.CERTIFICATIONS_KEY} Error: {e}")
145116
raise
146-
147-
if exp_data_from_cache:
148-
exp_data = json.loads(exp_data_from_cache)
149-
return [Experience(**exp) if isinstance(exp, dict) else exp
150-
for exp in (exp_data or [])]
151-
else:
152-
exp_data = self.fallback_repository.get_all_experiences() if self.fallback_repository else []
153-
self.redis.setex(
154-
self.EXPERIENCES_KEY,
155-
self.REDIS_TTL,
156-
json.dumps(exp_data, default=str)
157-
)
158-
return [Experience(**exp) if isinstance(exp, dict) else exp
159-
for exp in (exp_data or [])]
160-
161-
def get_all_social_media(self) -> List[SocialMedia]:
162-
"""Obtém todas as redes sociais do cache ou do repositório de fallback."""
163-
try:
164-
sm_data_from_cache = self.redis.get(self.SOCIAL_MEDIA_KEY)
117+
118+
def set_experiences(self, list_experiences: List[Experience]):
119+
try:
120+
data = [experience.to_dict() for experience in list_experiences]
121+
self.redis.set(self.EXPERIENCES_KEY, json.dumps(data), ex=self.REDIS_TTL)
165122
except RedisError as e:
166-
logger.error(f"Erro ao acessar o Redis: {e}")
167-
if self.fallback_repository:
168-
return self.fallback_repository.get_all_social_media()
123+
logger.error(f"Redis setting Key -> {self.EXPERIENCES_KEY} Error: {e}")
169124
raise
170-
171-
if sm_data_from_cache:
172-
sm_data = json.loads(sm_data_from_cache)
173-
return [SocialMedia(**sm) if isinstance(sm, dict) else sm
174-
for sm in (sm_data or [])]
175-
else:
176-
sm_data = self.fallback_repository.get_all_social_media() if self.fallback_repository else []
177-
self.redis.setex(
178-
self.SOCIAL_MEDIA_KEY,
179-
self.REDIS_TTL,
180-
json.dumps(sm_data, default=str)
181-
)
182-
return [SocialMedia(**sm) if isinstance(sm, dict) else sm
183-
for sm in (sm_data or [])]
184-
185-
def get_company_duration(self) -> List[CompanyDuration]:
186-
"""Obtém a duração nas empresas do cache ou do repositório de fallback."""
187-
try:
188-
cd_data_from_cache = self.redis.get(self.COMPANY_DURATION_KEY)
125+
126+
def set_social_media(self, list_social_media: List[SocialMedia]):
127+
try:
128+
data = [social_media.to_dict() for social_media in list_social_media]
129+
self.redis.set(self.SOCIAL_MEDIA_KEY, json.dumps(data), ex=self.REDIS_TTL)
189130
except RedisError as e:
190-
logger.error(f"Erro ao acessar o Redis: {e}")
191-
if self.fallback_repository:
192-
return self.fallback_repository.get_company_duration()
131+
logger.error(f"Redis setting Key -> {self.SOCIAL_MEDIA_KEY} Error: {e}")
193132
raise
194-
195-
if cd_data_from_cache:
196-
cd_data = json.loads(cd_data_from_cache)
197-
return [CompanyDuration(**cd) if isinstance(cd, dict) else cd
198-
for cd in (cd_data or [])]
199-
else:
200-
cd_data = self.fallback_repository.get_company_duration() if self.fallback_repository else []
201-
self.redis.setex(
202-
self.COMPANY_DURATION_KEY,
203-
self.REDIS_TTL,
204-
json.dumps(cd_data, default=str)
205-
)
206-
return [CompanyDuration(**cd) if isinstance(cd, dict) else cd
207-
for cd in (cd_data or [])]
208-
209-
def get_total_experience(self) -> Dict[str, Any]:
210-
"""Obtém o tempo total de experiência do cache ou do repositório de fallback."""
211-
try:
212-
te_data_from_cache = self.redis.get(self.TOTAL_EXPERIENCE_KEY)
133+
134+
def set_company_duration(self, list_company_duration: List[CompanyDuration]):
135+
try:
136+
data = [company_duration.to_dict() for company_duration in list_company_duration]
137+
self.redis.set(self.COMPANY_DURATION_KEY, json.dumps(data), ex=self.REDIS_TTL)
213138
except RedisError as e:
214-
logger.error(f"Erro ao acessar o Redis: {e}")
215-
if self.fallback_repository:
216-
return self.fallback_repository.get_total_experience()
139+
logger.error(f"Redis setting Key -> {self.COMPANY_DURATION_KEY} Error: {e}")
217140
raise
218-
219-
if te_data_from_cache:
220-
te_data = json.loads(te_data_from_cache)
221-
return te_data or {}
222-
else:
223-
te_data = self.fallback_repository.get_total_experience() if self.fallback_repository else {}
224-
self.redis.setex(
225-
self.TOTAL_EXPERIENCE_KEY,
226-
self.REDIS_TTL,
227-
json.dumps(te_data, default=str)
228-
)
229-
return te_data or {}
141+
142+
def set_total_experience(self, total_experience: Dict[str, Any]):
143+
try:
144+
self.redis.set(self.TOTAL_EXPERIENCE_KEY, json.dumps(total_experience), ex=self.REDIS_TTL)
145+
except RedisError as e:
146+
logger.error(f"Redis setting Key -> {self.TOTAL_EXPERIENCE_KEY} Error: {e}")
147+
raise

backend/src/infrastructure/dependencie_injection.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ def __new__(cls):
1616

1717
try:
1818
logger.info("🔄 Inicializando PostgresAdapter...")
19-
postgres_adapter = PostgresAdapter()
20-
cls._instance.data_repository = RedisAdapter(fallback_repository=postgres_adapter)
19+
cls._instance.data_repository = PostgresAdapter()
2120
logger.info("✅ PostgresAdapter inicializado com sucesso!")
22-
21+
logger.info("🔄 Inicializando RedisAdapter...")
22+
cls._instance.cache_provider = RedisAdapter()
23+
logger.info("✅ RedisAdapter inicializado com sucesso!")
2324
logger.info("🔄 Inicializando PortfolioDataService...")
2425
cls._instance.portfolio_data_service = PortfolioDataService(
25-
cls._instance.data_repository
26+
cls._instance.data_repository, cls._instance.cache_provider
2627
)
2728
logger.info("✅ PortfolioDataService inicializado com sucesso!")
2829

@@ -32,6 +33,6 @@ def __new__(cls):
3233

3334
logger.info("🎉 ApplicationDependencies inicializado com sucesso!")
3435
else:
35-
logger.info("♻️ Reutilizando instância existente de ApplicationDependencies")
36+
logger.info("♻️Reutilizando instância existente de ApplicationDependencies")
3637

3738
return cls._instance

0 commit comments

Comments
 (0)