Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
f3a5e61
v1
samcm Mar 20, 2025
b726264
v1
samcm Mar 20, 2025
3aaf73a
v2
samcm Mar 21, 2025
00c74c0
v2
samcm Mar 21, 2025
aaf9591
temporal imple
samcm Mar 21, 2025
d5a7dc8
temporal imple
samcm Mar 21, 2025
e746e02
implement some workflows
samcm Mar 21, 2025
f8a497d
service split
samcm Mar 25, 2025
9b3d398
cook
samcm Mar 25, 2025
2b87dc9
cook
samcm Mar 25, 2025
56d3a92
generating clickhouse table models
samcm Mar 25, 2025
6e42c96
yeet
samcm Mar 27, 2025
9b15d99
yeet
samcm Mar 27, 2025
2228b48
yeet
samcm Mar 27, 2025
3d5cbb4
yeet
samcm Mar 27, 2025
ab4dc56
fix: change xatuNetworks type from pointer to value in NewXatu function
samcm Mar 28, 2025
104386c
feat(storage): add ErrNotFound to storage package
samcm Mar 28, 2025
88a54e2
cook
samcm Apr 8, 2025
7f1d6af
rooclined
samcm Apr 8, 2025
16edf1a
rooclined
samcm Apr 8, 2025
b0095ae
feat: create script to generate new proto files
samcm Apr 8, 2025
bc1bb3a
rooclined
samcm Apr 8, 2025
fee36b7
rooclined
samcm Apr 9, 2025
6b55bb2
rooclined
samcm Apr 9, 2025
5f1af92
rooclined
samcm Apr 11, 2025
034dab3
rooclined
samcm Apr 11, 2025
c05b69d
feat: add clickhouse integration tests
samcm Apr 15, 2025
2d1d412
feat: refactor storage client to accept context and compress data
samcm Apr 15, 2025
708d415
cook
samcm Apr 15, 2025
7cff6a5
cook
samcm Apr 15, 2025
2f576dd
cook
samcm Apr 15, 2025
bfa2454
cook
samcm Apr 15, 2025
bd31864
beacon slots in progress
samcm Apr 15, 2025
ab69b04
feat(config.go): add modules config
samcm Apr 16, 2025
bf090b3
feat(go.mod): add go-eth2-client dependency
samcm Apr 16, 2025
af504ce
add geolocation
samcm Apr 16, 2025
cbd3d0e
```
samcm Apr 16, 2025
6e3701b
cook
samcm Apr 16, 2025
877adc9
feat: overhaul README to reflect Go backend architecture
samcm Apr 16, 2025
89bc791
chore: remove backend readme file
samcm Apr 16, 2025
ea47c46
feat: add labapiFrontendConfigResponse definition to swagger file
samcm Apr 17, 2025
9390cab
feat(server): enhance graceful shutdown and context handling
samcm Apr 17, 2025
3fc9f77
refactor: derive process context from parent context in beacon services
samcm Apr 17, 2025
42414da
feat: remove backend
samcm Apr 17, 2025
c5d6ccf
refactor: Remove redundant nil checks for metricsCollector
samcm Apr 21, 2025
276df28
feat: Add state and age metrics for various services
samcm Apr 21, 2025
df7489a
refactor(beacon_slots): improve error handling and logging in slot pr…
samcm Apr 21, 2025
6076033
feat(api): add CORS support and path prefix configuration
samcm Apr 21, 2025
bf39b31
feat(beacon_slots): add custom JSON marshaling for BlobTimingMap to s…
samcm Apr 21, 2025
e69fa8e
refactor(clickhouse): remove redundant DSN logging
samcm Apr 21, 2025
1bc6e20
refactor: consolidate backend Dockerfiles into a single pkg/Dockerfile
samcm Apr 21, 2025
6ca94cf
mv
samcm Apr 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 23 additions & 146 deletions .cursor/rules/backend.mdc
Original file line number Diff line number Diff line change
@@ -1,149 +1,26 @@
---
description: Whenever touching the backend
globs: *backend*
globs: *backend*,*.go*
alwaysApply: false
---
# Backend Architecture Overview

## Core Components

### Runner
- Main orchestrator that manages module lifecycle
- Initializes storage (S3) and database (ClickHouse)
- Registers and starts all enabled modules
- Handles graceful shutdown via signal handlers

### StateManager
- Generic key-value store for module/processor state
- Persists state to S3 as JSON
- Each module/processor manages its own state format
- Periodic flushing to S3 with configurable interval
- No type constraints - values must be JSON-serializable

### Module System
1. Module
- Top-level component that groups related processors
- Has its own configuration section
- Manages processor lifecycles
- Example modules: beacon_chain_timings, xatu_public_contributors

2. Processor
- Handles specific data processing tasks
- Manages its own state under its name
- Updates state to prevent reprocessing

## Adding New Functionality

### Creating a New Module
1. Create module directory: `backend/lab/modules/your_module_name/`
2. Create files:
- `__init__.py` - Exports module class
- `module.py` - Module implementation
- `config.py` - Module configuration
- `models.py` - Data models
- `processors/` - Directory for processors

3. Module Configuration (config.py):
```python
from pydantic import BaseModel, Field

class YourModuleConfig(BaseModel):
enabled: bool = Field(default=True)
networks: List[str] = Field(default=["mainnet"])
# Add your module-specific configuration here
```

4. Module Implementation (module.py):
```python
from lab.core.module import Module, ModuleContext

class YourModule(Module):
def __init__(self, ctx: ModuleContext):
super().__init__(ctx)
self._processors = {
"processor_name": YourProcessor(ctx)
}
self._tasks: Dict[str, asyncio.Task] = {}

@property
def name(self) -> str:
return "your_module_name"

async def start(self) -> None:
for name, processor in self._processors.items():
self._tasks[name] = asyncio.create_task(
self._run_processor(name, processor)
)

async def stop(self) -> None:
await super().stop()
for task in self._tasks.values():
task.cancel()
```

### Creating a New Processor
1. Create processor file: `processors/your_processor.py`
2. Implement processor:
```python
from .base import BaseProcessor

class YourProcessor(BaseProcessor):
def __init__(self, ctx: ModuleContext):
super().__init__(ctx, "processor_name")

async def process(self) -> None:
if not await self.should_process():
return

# Your processing logic here
await self.update_last_processed()
```

### State Management
- Each processor gets its own state key in the state store
- Basic state format:
```json
{
"last_processed": 0 // Unix timestamp
}
```
- State is automatically initialized if not exists
- Use `should_process()` to check processing needs
- Always update state after successful processing

### Best Practices
1. Error Handling
- Catch and log exceptions at processor level
- Continue processing on error
- Use descriptive error messages

2. Logging
- Use structured logging with context
- Log at appropriate levels (debug/info/warning/error)
- Include relevant metrics (counts, durations)

3. State Management
- Keep state minimal and JSON-serializable
- Update state after successful processing
- Validate state format on load

4. Performance
- Implement efficient database queries
- Process only what's needed using state checks

5. Configuration
- Use type hints and validation
- Provide sensible defaults
- Document configuration options

## Example Module Structure
```
backend/lab/modules/your_module/
├── __init__.py
├── config.py
├── models.py
├── module.py
└── processors/
├── __init__.py
├── base.py
└── your_processor.py
```
# Golang Best Pracices

When developing the Go codebase, you must adhere to industry standard/best practices for backend and Golang.

## Libraries
Use the following libraries:
- sirupsen/logrus for logging

## Structure
- Only use interfaces when absolutely required, or if they're beneficial for testing purposes. Structs should have a clearly defined
seperation of concerns, and be small and testable.
- When you create a new struct, interface, or feature, you should create tests in an equivalent side file.
- E.g. if you create 'store.go', also create 'store_test.go'
- It is VERY important to not stutter in your package and structure naming. For example:
- 'service/store/store.go.Store' - BAD
- 'service/store.go.Store' - GOOD
- NEVER create packages that hold abstract contents. Definitions should live close to their related structs.
- 'package/config/store.go' - DOGSHIT
- 'package/store/{store.go, config.go}' - GOOD
- 'utils/' - DOGSHIT. NEVER do this.
- 'types/' - DOGSHIT. NEVER do this.
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# State files
state/
backend/state/
config.yaml

Expand Down Expand Up @@ -38,10 +37,14 @@ ENV/
*.swp
*.swo
*~
*debug_bin*

# OS
.DS_Store
Thumbs.db

node_modules
config.yaml
config.yaml
docker-compose.override.yaml

deploy/local
39 changes: 39 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.PHONY: build proto run-srv run-api clean create-proto

# Generate protobuf
proto:
@echo "Generating protobuf code..."
buf generate --path pkg/server/proto/beacon_chain_timings
buf generate --path pkg/server/proto/lab
buf generate --path pkg/server/proto/xatu_public_contributors
buf generate --path pkg/server/proto/beacon_slots
buf generate --path pkg/api/proto

buf generate --template buf-api.gen.yaml . --path pkg/api/proto

# Create a new proto file
create-proto:
@echo "Usage: make create-proto PROTO_NAME=<n>"
@if [ -n "$(PROTO_NAME)" ]; then \
./scripts/create_proto.sh $(PROTO_NAME); \
fi

# Run srv service
run-srv:
@echo "Running srv service..."
go run cmd/main.go srv

# Run api service
run-api:
@echo "Running api service..."
go run cmd/main.go api

# Clean
clean:
@echo "Cleaning..."
rm -rf bin
rm -rf pkg/srv/proto/*/*.pb.go
rm -rf pkg/srv/proto/*/*_grpc.pb.go
rm -rf pkg/proto/*/*.pb.go
rm -rf pkg/proto/*/*_grpc.pb.go
rm -rf pkg/api/proto/*.pb.gw.go
Loading