Socle V004 – Guides Pratiques

Socle V004 - Guides Pratiques

17 – How-To Guides

Version : 4.0.0 Date : 2025-12-09

1. Comment créer un nouveau Worker

1.1 Worker simple

package com.myapp.worker;

import eu.lmvi.socle.worker.Worker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class MyWorker implements Worker {

    private static final Logger log = LoggerFactory.getLogger(MyWorker.class);
    private volatile boolean running = false;

    @Override
    public String getName() {
        return "my-worker";
    }

    @Override
    public void initialize() {
        log.info("[{}] Initializing", getName());
    }

    @Override
    public void start() {
        log.info("[{}] Starting", getName());
        running = true;
    }

    @Override
    public void doWork() {
        if (!running) return;
        // Votre logique ici
    }

    @Override
    public void stop() {
        log.info("[{}] Stopping", getName());
        running = false;
    }

    @Override
    public boolean isHealthy() {
        return running;
    }

    @Override
    public Map<String, Object> getStats() {
        return Map.of("running", running);
    }
}

1.2 Worker avec priorité

@Override
public int getStartPriority() {
    return 10;  // Démarre en premier
}

@Override
public int getStopPriority() {
    return 90;  // S'arrête en dernier
}

1.3 Worker schedulé

@Override
public String getSchedule() {
    return "0 0 6 * * ?";  // Tous les jours à 6h
}

@Override
public boolean isScheduled() {
    return true;
}

2. Comment utiliser KvBus

2.1 Opérations basiques

@Service
public class MyService {

    @Autowired
    private KvBus kvBus;

    public void example() {
        // Stocker
        kvBus.put("key", "value");
        kvBus.put("key-with-ttl", "value", Duration.ofHours(1));

        // Récupérer
        Optional<String> value = kvBus.get("key");

        // Supprimer
        kvBus.delete("key");

        // Compteur atomique
        long count = kvBus.increment("counter");
    }
}

2.2 JSON

// Stocker un objet
kvBus.putJson("order:123", order);

// Récupérer un objet
Optional<Order> order = kvBus.getJson("order:123", Order.class);

2.3 Lock distribué

public boolean tryLock(String resource) {
    return kvBus.putIfAbsent("lock:" + resource, "locked", Duration.ofMinutes(5));
}

public void unlock(String resource) {
    kvBus.delete("lock:" + resource);
}

3. Comment utiliser SharedDataRegistry

3.1 Key-Value

@Service
public class MyService {

    @Autowired
    private SharedDataRegistry registry;

    public void example() {
        // Stocker avec niveau de santé
        registry.put("database.connected", true, HealthLevel.CRITICAL);

        // Récupérer
        boolean connected = registry.getBoolean("database.connected").orElse(false);
    }
}

3.2 Compteurs

// Créer une séquence
registry.createSequence("orders.processed", 0, HealthLevel.NORMAL);

// Incrémenter
long count = registry.incrementSequence("orders.processed");

// Lire
long total = registry.getSequence("orders.processed");

4. Comment utiliser TechDB (V4)

4.1 Offsets

@Service
public class MyService {

    @Autowired
    private TechDbManager techDb;

    public void example() {
        // Sauvegarder un offset
        techDb.saveOffset("kafka", "my-topic-0", 123456L, null);

        // Récupérer un offset
        OptionalLong offset = techDb.getOffset("kafka", "my-topic-0");
    }
}

4.2 État des workers

// Sauvegarder l'état
techDb.saveWorkerState("my-worker", "RUNNING", Map.of("progress", 50));

// Récupérer l'état
Optional<WorkerState> state = techDb.getWorkerState("my-worker");

4.3 Événements techniques

// Logger un événement
techDb.logEvent("ERROR", Map.of(
    "message", "Connection failed",
    "target", "database"
));

// Récupérer les événements
List<TechEvent> events = techDb.getEvents("ERROR", Instant.now().minus(1, ChronoUnit.HOURS), 100);

5. Comment implémenter un Pipeline

5.1 Pipeline simple

Pipeline<Order, ProcessedOrder> pipeline = PipelineBuilder
    .<Order, ProcessedOrder>create("order-processing")
    .addStep("validate", this::validateOrder)
    .addStep("enrich", this::enrichOrder)
    .addStep("process", this::processOrder)
    .build();

PipelineResult<ProcessedOrder> result = pipelineEngine.execute(pipeline, order);

5.2 Étape personnalisée

public class ValidationStep implements PipelineStep<Order, ValidatedOrder> {

    @Override
    public String getName() {
        return "validation";
    }

    @Override
    public StepResult<ValidatedOrder> execute(Order input, PipelineContext context) {
        // Validation...
        return StepResult.success(getName(), new ValidatedOrder(input), Duration.ZERO);
    }

    @Override
    public boolean isRetryable() {
        return false;
    }
}

6. Comment configurer le logging (V4)

6.1 Log4j2 basique

<!-- src/main/resources/log4j2.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{ISO8601} %-5level [%thread] %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

6.2 Avec LogForwarder

# application.yml
socle:
  logging:
    forwarder:
      enabled: true
      transport-mode: http
      log-hub-url: https://logs.mycompany.com/api/ingest

7. Comment utiliser l’authentification JWT (V4)

7.1 Configuration

socle:
  auth:
    enabled: true
    server-url: https://auth.mycompany.com
    api-key: ${API_KEY}

7.2 Utilisation

@Service
public class SecuredService {

    @Autowired(required = false)
    private SocleAuthClient authClient;

    public void callSecuredApi() {
        if (authClient == null) {
            throw new IllegalStateException("Auth not configured");
        }

        String token = authClient.getValidAccessToken();

        // Utiliser le token dans les requêtes HTTP
        Request request = new Request.Builder()
            .url("https://api.mycompany.com/data")
            .header("Authorization", "Bearer " + token)
            .build();
    }
}

8. Comment ajouter des métriques personnalisées

8.1 Counter

@Component
public class MyMetrics {

    private final Counter ordersProcessed;

    public MyMetrics(MeterRegistry registry) {
        this.ordersProcessed = Counter.builder("my_orders_processed_total")
            .description("Total orders processed")
            .register(registry);
    }

    public void orderProcessed() {
        ordersProcessed.increment();
    }
}

8.2 Timer

private final Timer processingTime;

public MyMetrics(MeterRegistry registry) {
    this.processingTime = Timer.builder("my_processing_duration_seconds")
        .description("Processing duration")
        .publishPercentiles(0.5, 0.95, 0.99)
        .register(registry);
}

public void process() {
    Timer.Sample sample = Timer.start();
    try {
        doProcess();
    } finally {
        sample.stop(processingTime);
    }
}

9. Comment gérer la résilience

9.1 Retry

@Autowired
private RetryTemplate retryTemplate;

public Data fetchData() {
    return retryTemplate.execute(() -> httpClient.get("/api/data"));
}

9.2 Circuit Breaker

@Autowired
private CircuitBreakerRegistry cbRegistry;

public Data fetchData() {
    CircuitBreaker cb = cbRegistry.getOrCreate("external-api");

    return cb.executeWithFallback(
        () -> httpClient.get("/api/data"),
        () -> getCachedData()
    );
}

10. Comment déployer sur Kubernetes

10.1 Build de l’image

# Build
mvn clean package -DskipTests
docker build -t my-app:1.0.0 .

# Push
docker push my-registry/my-app:1.0.0

10.2 Déploiement

# Appliquer les manifests
kubectl apply -f k8s/

# Ou avec Helm
helm install my-app ./chart -n my-namespace

10.3 Vérification

# Logs
kubectl logs -f deployment/my-app

# Port forward
kubectl port-forward svc/my-app 8080:80

# Health check
curl http://localhost:8080/admin/health

11. Comment migrer de V3 à V4

11.1 Dépendances Maven

<!-- Remplacer Logback par Log4j2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

<!-- Ajouter H2 -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>

11.2 Configuration

# Ajouter à application.yml
socle:
  techdb:
    enabled: true
  logging:
    forwarder:
      enabled: false
  auth:
    enabled: false
  worker-registry:
    enabled: false

logging:
  config: classpath:log4j2.xml

11.3 Fichiers Log4j2

Créer src/main/resources/log4j2.xml et log4j2.component.properties.

Voir 25-MIGRATION-V3-V4 pour le guide complet.

12. Comment debugger

12.1 H2 Console

socle:
  techdb:
    console:
      enabled: true
      path: /h2-console

Accéder à http://localhost:8080/h2-console

12.2 Endpoints Admin

# État de santé
curl http://localhost:8080/admin/health

# Workers
curl http://localhost:8080/admin/workers

# Registry
curl http://localhost:8080/admin/registry

# Métriques
curl http://localhost:8080/actuator/prometheus

12.3 Logs

// Activer le debug pour le Socle
logging.level.eu.lmvi.socle=DEBUG

13. Références

Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *