Skip to main content

v0.29.0 Release Notes

EnerOS v0.29.0 Release Notes

Release Date: 2025-12-07 Codename: Distributed Git Tag: v0.29.0 Support Status: Stable Total Crates: 78 (4 new) Test Cases: 10000+ (500+ new)

Overview

EnerOS v0.29.0 “Distributed” is a distributed-deployment-focused release that enables EnerOS to run across multiple nodes. Provincial dispatch centers can have grid scales reaching tens of thousands of nodes, which a single machine cannot support with complete topology, power flow, and timeseries workloads. v0.29.0 upgrades EnerOS from a single-node system to a distributed system, achieving horizontal scaling through four capabilities: node discovery, data sharding, distributed transactions, and consistency guarantees.

This release introduces five core capabilities: Distributed Deployment, Node Discovery, Data Sharding, Distributed Transaction, and Consistency Guarantee. The cluster can scale from 3 nodes to 64 nodes, supporting real-time operation of 100,000-scale grid nodes.

In terms of design philosophy, v0.29.0 adheres to “partition tolerance first” — prioritizing availability during network partitions (AP), with critical operations ensuring consistency through quorum; “data locality” — sharding by electrical topology so most computation completes locally; “transparent scaling” — application-layer APIs remain unchanged, with distributed details handled by the kernel.

Key Metrics

MetricValueDescription
Max cluster size64 nodesHorizontal scaling
Node discovery latency< 2sNew node joining
Shard migration time< 30sPer shard
Distributed transaction latency15ms2PC
Data locality92%Local access rate
New Crates4Distributed-related

New Features

1. Distributed Deployment

Introduces the eneros-distributed Crate, providing distributed cluster management. Multiple nodes form a cluster, sharing topology, power flow, and timeseries data.

Cluster Creation

use eneros_distributed::{Cluster, ClusterConfig, NodeRole};

let cluster = Cluster::new("dispatch-cluster")
    .config(ClusterConfig {
        seed_nodes: vec!["node-1:7946", "node-2:7946"],
        data_dir: "/var/lib/eneros",
        replication_factor: 3,
        shard_count: 32,
    })
    .join("node-1:7946").await?;

// View cluster status
let status = cluster.status().await?;
println!("Node count: {}", status.node_count);
println!("Shard count: {}", status.shard_count);
println!("Healthy nodes: {}", status.healthy_nodes);

Node Roles

RoleResponsibilityCountDescription
CoordinatorTransaction coordination3-5Elected
DataNodeShard storageAllCarries data
ComputeNodeCompute nodeAllExecutes computation
GatewayEntry gateway2+Load balancing

2. Node Discovery

Introduces the eneros-distributed-discovery Crate, providing automatic node discovery and membership management. Based on the SWIM protocol (Gossip improvement), it achieves efficient membership maintenance.

Node Joining

use eneros_distributed_discovery::{Discovery, NodeInfo};

let discovery = Discovery::new(&cluster)
    .gossip_interval(Duration::milliseconds(200))
    .probe_timeout(Duration::milliseconds(500));

// New node joining
let node = NodeInfo::new("node-5")
    .address("10.0.1.5:7946")
    .roles(vec![NodeRole::DataNode, NodeRole::ComputeNode])
    .capacity(Capacity {
        cpu: 32,
        memory_gb: 128,
        disk_gb: 2000,
    });

discovery.join(node).await?;
// Auto-broadcast to entire cluster, all nodes感知 within 2s

Failure Detection

// SWIM protocol failure detection
discovery.on_node_failure(|node| async move {
    log::warn!("Node {} lost contact", node.id);

    // Auto-trigger shard migration
    cluster.rebalance_on_failure(node).await?;

    // Notify agents to reschedule
    swarm.on_node_failure(node).await?;
});

Discovery Protocol Comparison

ProtocolDetection LatencyNetwork OverheadApplicable Scale
Heartbeat3-15sO(n)< 10 nodes
Gossip1-5sO(log n)< 100 nodes
SWIM1-3sO(log n)< 1000 nodes

3. Data Sharding

Introduces the eneros-distributed-sharding Crate, providing data sharding capabilities. Sharding by electrical topology ensures most computation completes locally.

Sharding Strategy

use eneros_distributed_sharding::{ShardManager, ShardStrategy};

let sharding = ShardManager::new(&cluster)
    .strategy(ShardStrategy::TopologyBased)
    .shard_count(32);

// Shard by electrical region
sharding.assign(&network).await?;
// Region A devices → shards 0-7
// Region B devices → shards 8-15
// ...

// Query shard location
let location = sharding.locate(BusId::from(42))?;
println!("Bus 42 is in shard {} (node {})", location.shard, location.node);

Shard Migration

// Auto-migrate shards when node fails
sharding.migrate(
    from: "node-3",
    to: "node-5",
    shards: vec![8, 9, 10],
).await?;

// Online migration, no service interruption

Sharding Strategy Comparison

StrategyData LocalityMigration FrequencyApplicable Scenario
Hash sharding50%LowGeneral
Range sharding70%MediumTimeseries
Topology sharding92%HighPower grid
Consistent hashing60%LowElastic

4. Distributed Transaction

Introduces the eneros-distributed-tx Crate, providing cross-node transaction guarantees. Supports both 2PC (Two-Phase Commit) and Saga modes.

2PC Transaction

use eneros_distributed_tx::{Transaction, TxCoordinator};

let coordinator = TxCoordinator::new(&cluster);

// Cross-node transaction: operate on multiple shards simultaneously
let mut tx = Transaction::new();
tx.add(Operation::UpdateBus(42, voltage: 1.02));  // Shard 3
tx.add(Operation::OpenSwitch(15));                  // Shard 7
tx.add(Operation::AdjustGen(1, mw: 200.0));        // Shard 2

match coordinator.commit_2pc(tx).await {
    Ok(_) => println!("Transaction committed successfully"),
    Err(TxError::ParticipantAbort { node, reason }) => {
        println!("Node {} rejected: {}", node, reason);
        // Auto-rollback
    }
}

Saga Mode

// Long transaction: Saga mode (compensating transactions)
let saga = Saga::new("fault-recovery")
    .step(Step::new("isolate")
        .action(|ctx| isolate_fault(ctx))
        .compensation(|ctx| restore_isolated(ctx)))
    .step(Step::new("transfer")
        .action(|ctx| transfer_load(ctx))
        .compensation(|ctx| restore_load(ctx)))
    .step(Step::new("restore")
        .action(|ctx| restore_power(ctx))
        .compensation(|ctx| cut_power(ctx)));

saga.execute().await?;

Transaction Characteristics

ModeConsistencyLatencyAvailabilityApplicable Scenario
2PCStrong15msLowCritical operations
SagaEventual5msHighLong workflows
TCCStrong8msMediumResource reservation

5. Consistency Guarantee

Introduces the eneros-distributed-consistency Crate, providing multi-level consistency guarantees. Different data types use different consistency levels.

Consistency Levels

use eneros_distributed_consistency::{Consistency, ReadOptions};

// Strong consistency read (always read latest value)
let bus = cluster.read(BusId::from(42), ReadOptions {
    consistency: Consistency::Strong,
}).await?;

// Causal consistency read (read causally latest value)
let event = cluster.read_event(event_id, ReadOptions {
    consistency: Consistency::Causal,
}).await?;

// Eventual consistency read (read any replica)
let metric = cluster.read_metric("load", ReadOptions {
    consistency: Consistency::Eventual,
}).await?;

Replication Strategy

// Data replication
let replication = Replication::new()
    .factor(3)  // 3 replicas
    .mode(ReplicationMode::Sync)  // Synchronous replication
    .placement(PlacementPolicy::rack_aware());  // Cross-rack

cluster.set_replication(replication).await?;

Consistency Matrix

Data TypeConsistencyReplicationWrite LatencyApplicable Scenario
Topology dataStrongSync 3 replicas15msSwitch state
Power flow resultsStrongSync 3 replicas15msComputation results
Timeseries dataEventualAsync 3 replicas1msTelemetry data
Audit logsStrongSync 3 replicas15msCompliance requirements
CacheEventualSingle replica0.1msPerformance priority

Improvements

  • Network Layer: Switched from TCP to QUIC, multiplexing reduces connection establishment latency by 60%
  • Serialization: Switched from JSON to MessagePack, serialization size reduced by 50%
  • Compression: Zstandard compression enabled for timeseries data transmission, bandwidth usage reduced by 70%
  • Load Balancing: Added adaptive load balancer that dynamically adjusts shards based on node load

Bug Fixes

  • Fixed eneros-distributed-discovery split-brain issue during network partition (#2908)
  • Fixed eneros-distributed-sharding data loss risk during shard migration (#2913)
  • Fixed eneros-distributed-tx transaction suspension when 2PC coordinator failed (#2918)
  • Fixed eneros-distributed-consistency synchronous replication timeout with slow nodes (#2923)

Breaking Changes

  • Cluster::new: Added ClusterConfig parameter; shard and replica configuration must be provided
  • read/write API: Added ReadOptions/WriteOptions parameters to specify consistency level

Upgrade Guide

  1. Run cargo update -p eneros-distributed
  2. Provide ClusterConfig for Cluster::new
  3. Add consistency level parameters to read/write operations
  4. Refer to docs/migration/v0.29.0.md for detailed migration steps