new api service and logic implemented

This commit is contained in:
2025-01-23 22:27:25 +03:00
parent d91ecda9df
commit 32022ca521
245 changed files with 28004 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
# Improvements Documentation
This directory contains documentation and example implementations for various system improvements.
## Directory Structure
```
improvements/
├── detailed_improvement_plan.md # Overall improvement plan
├── language_service/ # Language service implementation
│ ├── backend/
│ │ ├── language_service.py # Basic language service
│ │ └── zod_messages.py # Zod validation messages
│ └── frontend/
│ └── languageService.ts # Frontend language service
└── validation_service/ # Validation service implementation
├── backend/
│ └── schema_converter.py # Pydantic to Zod converter
└── frontend/
└── dynamicSchema.ts # Dynamic Zod schema builder
```
## Components
### Language Service
The language service provides internationalization support with:
- Backend API for serving translations
- Frontend service for managing translations
- Integration with Zod for validation messages
### Validation Service
The validation service provides dynamic form validation with:
- Automatic conversion of Pydantic models to Zod schemas
- Frontend builder for dynamic schema creation
- Integration with language service for messages
## Implementation Status
These are example implementations that demonstrate the proposed improvements. To implement in the actual system:
1. Create appropriate service directories
2. Copy and adapt the code
3. Add tests
4. Update dependencies
5. Integrate with existing systems
## Next Steps
1. Review the implementations
2. Decide on integration approach
3. Create implementation tickets
4. Plan phased rollout
5. Add monitoring and metrics
For detailed implementation plans and timelines, see [detailed_improvement_plan.md](./detailed_improvement_plan.md).

View File

@@ -0,0 +1,311 @@
# Detailed Improvement Plan
## 1. Infrastructure & Deployment
### Service Isolation and Containerization
- **Microservices Architecture**
```
/services
├── auth-service/
│ ├── Dockerfile
│ └── docker-compose.yml
├── event-service/
│ ├── Dockerfile
│ └── docker-compose.yml
└── validation-service/
├── Dockerfile
└── docker-compose.yml
```
- **Service Discovery**
- Implement Consul for service registry
- Add health check endpoints
- Create service mesh with Istio
### API Gateway Implementation
```yaml
# api-gateway.yml
services:
gateway:
routes:
- id: auth-service
uri: lb://auth-service
predicates:
- Path=/api/auth/**
filters:
- RateLimit=100,1s
- CircuitBreaker=3,10s
```
### Monitoring Stack
- **Distributed Tracing**
```python
from opentelemetry import trace
from opentelemetry.exporter import jaeger
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("operation") as span:
span.set_attribute("attribute", value)
```
- **Metrics Collection**
- Prometheus for metrics
- Grafana for visualization
- Custom dashboards for each service
### Configuration Management
```python
# config_service.py
class ConfigService:
def __init__(self):
self.consul_client = Consul()
def get_config(self, service_name: str) -> Dict:
return self.consul_client.kv.get(f"config/{service_name}")
def update_config(self, service_name: str, config: Dict):
self.consul_client.kv.put(f"config/{service_name}", config)
```
## 2. Performance & Scaling
### Enhanced Caching Strategy
```python
# redis_cache.py
class RedisCache:
def __init__(self):
self.client = Redis(cluster_mode=True)
async def get_or_set(self, key: str, callback: Callable):
if value := await self.client.get(key):
return value
value = await callback()
await self.client.set(key, value, ex=3600)
return value
```
### Database Optimization
```sql
-- Sharding Example
CREATE TABLE users_shard_1 PARTITION OF users
FOR VALUES WITH (modulus 3, remainder 0);
CREATE TABLE users_shard_2 PARTITION OF users
FOR VALUES WITH (modulus 3, remainder 1);
```
### Event System Enhancement
```python
# event_publisher.py
class EventPublisher:
def __init__(self):
self.kafka_producer = KafkaProducer()
async def publish(self, topic: str, event: Dict):
await self.kafka_producer.send(
topic,
value=event,
headers=[("version", "1.0")]
)
```
### Background Processing
```python
# job_processor.py
class JobProcessor:
def __init__(self):
self.celery = Celery()
self.connection_pool = ConnectionPool(max_size=100)
@celery.task
async def process_job(self, job_data: Dict):
async with self.connection_pool.acquire() as conn:
await conn.execute(job_data)
```
## 3. Security & Reliability
### API Security Enhancement
```python
# security.py
class SecurityMiddleware:
def __init__(self):
self.rate_limiter = RateLimiter()
self.key_rotator = KeyRotator()
async def process_request(self, request: Request):
await self.rate_limiter.check(request.client_ip)
await self.key_rotator.validate(request.api_key)
```
### Error Handling System
```python
# error_handler.py
class ErrorHandler:
def __init__(self):
self.sentry_client = Sentry()
self.circuit_breaker = CircuitBreaker()
async def handle_error(self, error: Exception):
await self.sentry_client.capture_exception(error)
await self.circuit_breaker.record_error()
```
### Testing Framework
```python
# integration_tests.py
class IntegrationTests:
async def setup(self):
self.containers = await TestContainers.start([
"postgres", "redis", "kafka"
])
async def test_end_to_end(self):
await self.setup()
# Test complete user journey
await self.cleanup()
```
### Audit System
```python
# audit.py
class AuditLogger:
def __init__(self):
self.elastic = Elasticsearch()
async def log_action(
self,
user_id: str,
action: str,
resource: str,
changes: Dict
):
await self.elastic.index({
"user_id": user_id,
"action": action,
"resource": resource,
"changes": changes,
"timestamp": datetime.utcnow()
})
```
## 4. Development Experience
### Domain-Driven Design
```
/src
├── domain/
│ ├── entities/
│ ├── value_objects/
│ └── aggregates/
├── application/
│ ├── commands/
│ └── queries/
└── infrastructure/
├── repositories/
└── services/
```
### API Documentation
```python
# main.py
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
app = FastAPI()
def custom_openapi():
return get_openapi(
title="WAG Management API",
version="4.0.0",
description="Complete API documentation",
routes=app.routes
)
app.openapi = custom_openapi
```
### Translation Management
```python
# i18n.py
class TranslationService:
def __init__(self):
self.translations = {}
self.fallback_chain = ["tr", "en"]
async def get_translation(
self,
key: str,
lang: str,
fallback: bool = True
) -> str:
if translation := self.translations.get(f"{lang}.{key}"):
return translation
if fallback:
for lang in self.fallback_chain:
if translation := self.translations.get(f"{lang}.{key}"):
return translation
return key
```
### Developer Tools
```python
# debug_toolkit.py
class DebugToolkit:
def __init__(self):
self.profiler = cProfile.Profile()
self.debugger = pdb.Pdb()
def profile_function(self, func: Callable):
def wrapper(*args, **kwargs):
self.profiler.enable()
result = func(*args, **kwargs)
self.profiler.disable()
return result
return wrapper
```
## Implementation Priority
1. **Phase 1 - Foundation** (1-2 months)
- Service containerization
- Basic monitoring
- API gateway setup
- Security enhancements
2. **Phase 2 - Scaling** (2-3 months)
- Caching implementation
- Database optimization
- Event system upgrade
- Background jobs
3. **Phase 3 - Reliability** (1-2 months)
- Error handling
- Testing framework
- Audit system
- Performance monitoring
4. **Phase 4 - Developer Experience** (1-2 months)
- Documentation
- Development tools
- Translation system
- Code organization
## Success Metrics
- **Performance**
- Response time < 100ms for 95% of requests
- Cache hit rate > 80%
- Zero downtime deployments
- **Reliability**
- 99.99% uptime
- < 0.1% error rate
- < 1s failover time
- **Security**
- Zero critical vulnerabilities
- 100% audit log coverage
- < 1hr security incident response time
- **Development**
- 80% test coverage
- < 24hr PR review time
- < 1 day developer onboarding

View File

@@ -0,0 +1,6 @@
# Original content from ApiEvents/LanguageServiceApi/language_service.py
from typing import Dict, List, Optional
from fastapi import APIRouter, Header
from pydantic import BaseModel
# ... rest of the file content ...

View File

@@ -0,0 +1,7 @@
# Original content from ApiEvents/LanguageServiceApi/zod_messages.py
from typing import Dict
from fastapi import APIRouter, Header
from pydantic import BaseModel
from typing import Optional
# ... rest of the file content ...

View File

@@ -0,0 +1,4 @@
// Original content from frontend/src/services/languageService.ts
import axios from 'axios';
// ... rest of the file content ...

View File

@@ -0,0 +1,9 @@
# Original content from ApiEvents/ValidationServiceApi/schema_converter.py
from typing import Dict, Any, Type, get_type_hints, get_args, get_origin
from pydantic import BaseModel, Field, EmailStr
from enum import Enum
import inspect
from fastapi import APIRouter
from datetime import datetime
# ... rest of the file content ...

View File

@@ -0,0 +1,146 @@
from typing import Dict, Any, Type, Optional
from pydantic import BaseModel
from fastapi import APIRouter, Header
class ValidationMessages(BaseModel):
"""Messages for Zod validation"""
required: str
invalid_type: str
invalid_string: Dict[str, str] # email, url, etc
too_small: Dict[str, str] # string, array, number
too_big: Dict[str, str] # string, array, number
invalid_date: str
invalid_enum: str
custom: Dict[str, str]
class SchemaField(BaseModel):
"""Schema field definition"""
type: str
items: Optional[str] = None # For arrays
values: Optional[list] = None # For enums
validations: Optional[Dict[str, Any]] = None
class SchemaDefinition(BaseModel):
"""Complete schema definition"""
name: str
fields: Dict[str, SchemaField]
messages: ValidationMessages
class UnifiedSchemaService:
def __init__(self):
self.messages = {
"tr": ValidationMessages(
required="Bu alan zorunludur",
invalid_type="Geçersiz tip",
invalid_string={
"email": "Geçerli bir e-posta adresi giriniz",
"url": "Geçerli bir URL giriniz",
"uuid": "Geçerli bir UUID giriniz"
},
too_small={
"string": "{min} karakterden az olamaz",
"array": "En az {min} öğe gereklidir",
"number": "En az {min} olmalıdır"
},
too_big={
"string": "{max} karakterden fazla olamaz",
"array": "En fazla {max} öğe olabilir",
"number": "En fazla {max} olabilir"
},
invalid_date="Geçerli bir tarih giriniz",
invalid_enum="Geçersiz seçim",
custom={
"password_match": "Şifreler eşleşmiyor",
"strong_password": "Şifre güçlü değil"
}
),
"en": ValidationMessages(
required="This field is required",
invalid_type="Invalid type",
invalid_string={
"email": "Please enter a valid email",
"url": "Please enter a valid URL",
"uuid": "Please enter a valid UUID"
},
too_small={
"string": "Must be at least {min} characters",
"array": "Must contain at least {min} items",
"number": "Must be at least {min}"
},
too_big={
"string": "Must be at most {max} characters",
"array": "Must contain at most {max} items",
"number": "Must be at most {max}"
},
invalid_date="Please enter a valid date",
invalid_enum="Invalid selection",
custom={
"password_match": "Passwords do not match",
"strong_password": "Password is not strong enough"
}
)
}
def get_schema_with_messages(
self,
model: Type[BaseModel],
lang: str = "tr"
) -> SchemaDefinition:
"""Get schema definition with validation messages"""
fields: Dict[str, SchemaField] = {}
for field_name, field in model.__fields__.items():
field_info = SchemaField(
type=self._get_field_type(field.outer_type_),
items=self._get_items_type(field.outer_type_),
values=self._get_enum_values(field.outer_type_),
validations=self._get_validations(field)
)
fields[field_name] = field_info
return SchemaDefinition(
name=model.__name__,
fields=fields,
messages=self.messages[lang]
)
def _get_field_type(self, type_: Type) -> str:
# Implementation similar to SchemaConverter
pass
def _get_items_type(self, type_: Type) -> Optional[str]:
# Implementation similar to SchemaConverter
pass
def _get_enum_values(self, type_: Type) -> Optional[list]:
# Implementation similar to SchemaConverter
pass
def _get_validations(self, field) -> Optional[Dict[str, Any]]:
# Implementation similar to SchemaConverter
pass
router = APIRouter(prefix="/api/schema", tags=["Schema"])
schema_service = UnifiedSchemaService()
@router.get("/model/{model_name}")
async def get_model_schema(
model_name: str,
accept_language: Optional[str] = Header(default="tr")
) -> SchemaDefinition:
"""Get model schema with validation messages"""
# You'd need to implement model lookup
models = {
"User": UserModel,
"Product": ProductModel,
# Add your models here
}
if model_name not in models:
raise ValueError(f"Model {model_name} not found")
lang = accept_language.split(",")[0][:2]
return schema_service.get_schema_with_messages(
models[model_name],
lang if lang in ["tr", "en"] else "tr"
)

View File

@@ -0,0 +1,6 @@
// Original content from frontend/src/validation/dynamicSchema.ts
import { z } from 'zod';
import axios from 'axios';
import { zodMessages } from './zodMessages';
// ... rest of the file content ...

View File

@@ -0,0 +1,219 @@
import { z } from 'zod';
import axios from 'axios';
interface ValidationMessages {
required: string;
invalid_type: string;
invalid_string: Record<string, string>;
too_small: Record<string, string>;
too_big: Record<string, string>;
invalid_date: string;
invalid_enum: string;
custom: Record<string, string>;
}
interface SchemaField {
type: string;
items?: string;
values?: any[];
validations?: Record<string, any>;
}
interface SchemaDefinition {
name: string;
fields: Record<string, SchemaField>;
messages: ValidationMessages;
}
class UnifiedSchemaBuilder {
private static instance: UnifiedSchemaBuilder;
private schemaCache: Map<string, z.ZodSchema> = new Map();
private constructor() {}
static getInstance(): UnifiedSchemaBuilder {
if (!UnifiedSchemaBuilder.instance) {
UnifiedSchemaBuilder.instance = new UnifiedSchemaBuilder();
}
return UnifiedSchemaBuilder.instance;
}
async getSchema(modelName: string): Promise<z.ZodSchema> {
// Check cache first
if (this.schemaCache.has(modelName)) {
return this.schemaCache.get(modelName)!;
}
// Fetch schema definition with messages from backend
const response = await axios.get<SchemaDefinition>(
`/api/schema/model/${modelName}`,
{
headers: {
'Accept-Language': navigator.language || 'tr'
}
}
);
const schema = this.buildSchema(response.data);
this.schemaCache.set(modelName, schema);
return schema;
}
private buildSchema(definition: SchemaDefinition): z.ZodSchema {
const shape: Record<string, z.ZodTypeAny> = {};
for (const [fieldName, field] of Object.entries(definition.fields)) {
shape[fieldName] = this.buildField(field, definition.messages);
}
return z.object(shape);
}
private buildField(
field: SchemaField,
messages: ValidationMessages
): z.ZodTypeAny {
let zodField: z.ZodTypeAny;
switch (field.type) {
case 'string':
zodField = z.string({
required_error: messages.required,
invalid_type_error: messages.invalid_type
});
break;
case 'email':
zodField = z.string().email(messages.invalid_string.email);
break;
case 'number':
zodField = z.number({
required_error: messages.required,
invalid_type_error: messages.invalid_type
});
break;
case 'boolean':
zodField = z.boolean({
required_error: messages.required,
invalid_type_error: messages.invalid_type
});
break;
case 'date':
zodField = z.date({
required_error: messages.required,
invalid_type_error: messages.invalid_date
});
break;
case 'array':
zodField = z.array(
this.buildField({ type: field.items! }, messages)
);
break;
case 'enum':
zodField = z.enum(field.values as [string, ...string[]], {
required_error: messages.required,
invalid_type_error: messages.invalid_enum
});
break;
default:
zodField = z.any();
}
// Apply validations if any
if (field.validations) {
zodField = this.applyValidations(zodField, field.validations, messages);
}
return zodField;
}
private applyValidations(
field: z.ZodTypeAny,
validations: Record<string, any>,
messages: ValidationMessages
): z.ZodTypeAny {
let result = field;
if ('min_length' in validations) {
result = (result as z.ZodString).min(
validations.min_length,
messages.too_small.string.replace(
'{min}',
validations.min_length.toString()
)
);
}
if ('max_length' in validations) {
result = (result as z.ZodString).max(
validations.max_length,
messages.too_big.string.replace(
'{max}',
validations.max_length.toString()
)
);
}
if ('pattern' in validations) {
result = (result as z.ZodString).regex(
new RegExp(validations.pattern),
messages.custom[validations.pattern_message] || 'Invalid format'
);
}
if ('gt' in validations) {
result = (result as z.ZodNumber).gt(
validations.gt,
messages.too_small.number.replace(
'{min}',
(validations.gt + 1).toString()
)
);
}
if ('lt' in validations) {
result = (result as z.ZodNumber).lt(
validations.lt,
messages.too_big.number.replace(
'{max}',
(validations.lt - 1).toString()
)
);
}
return result;
}
}
// Export singleton instance
export const schemaBuilder = UnifiedSchemaBuilder.getInstance();
// Usage example:
/*
import { schemaBuilder } from './validation/unifiedSchemaBuilder';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
function UserForm() {
const [schema, setSchema] = useState<z.ZodSchema | null>(null);
useEffect(() => {
async function loadSchema() {
const userSchema = await schemaBuilder.getSchema('User');
setSchema(userSchema);
}
loadSchema();
}, []);
const form = useForm({
resolver: schema ? zodResolver(schema) : undefined
});
if (!schema) return <div>Loading...</div>;
return (
<form onSubmit={form.handleSubmit(data => console.log(data))}>
{/* Your form fields */}
</form>
);
}
*/