Portable Reed-Solomon shard recovery and integrity envelopes
moon add oyjh0381/moonerasure@0.1.0import {
"oyjh0381/moonerasure",
}moon check --target all --deny-warn
moon build --target all --deny-warn
moon test --target all --deny-warn
moon run cmd/main --target wasm-gclet codec = try! @moonerasure.Codec::new(3, 2)
let object = try! @moonerasure.encode_object(
codec,
b"backup bytes",
123,
stripe_payload_limit=64,
)
let retained : Array[@moonerasure.ShardEnvelope] = []
for frame in object.frames() {
if frame.shard_index() != 1 && frame.shard_index() != 4 {
retained.push(frame)
}
}
let recovered = try! @moonerasure.recover_object(object.manifest(), retained)
assert_eq(recovered.payload(), b"backup bytes")
let replacements = try! @moonerasure.repair_object(object.manifest(), retained)| Command | Demonstrated need |
|---|---|
| moon run cmd/main | Backup recovery and replacement frame generation after two placements disappear. |
| moon run examples/transfer | Out-of-order packets, one absent data packet and one checksum-failed parity packet per stripe. |
| moon run examples/scrub | Frame inventory, health inspection, and persisted-slot repair. |
| moon run examples/range | Recover a byte range by fetching only overlapping stripes. |
| moon run examples/stream | Encode arbitrary input chunks and decode one stripe at a time. |
| moon run examples/maintenance | Admit a frame batch atomically and plan reads over currently recoverable byte ranges. |
| moon run examples/benchmark --target native | Verified fixed workload for local timing of repeated loss patterns. |
pub(all) suberror ErasureError {
InvalidConfiguration(String)
InvalidShardCount(expected~ : Int, actual~ : Int)
InvalidShardLength(index~ : Int, expected~ : Int, actual~ : Int)
EmptyShard
NotEnoughShards(required~ : Int, available~ : Int)
SingularMatrix
InvalidIndex(Int)
DuplicateIndex(Int)
InconsistentShard(Int)
InvalidRange
InvalidEnvelope(String)
UnsupportedVersion(Int)
ChecksumMismatch(Int)
ResourceLimit(String)
InvalidManifest(String)
}fn BundleStream::new(max_input_bytes? : Int, max_object_bytes? : Int, max_encoded_bytes? : Int) -> BundleStream raise ErasureErrorfn BundleStream::push(self : BundleStream, chunk : Bytes) -> Array[ShardEnvelope] raise ErasureErrorfn Codec::new(data_count : Int, parity_count : Int, max_encoded_bytes? : Int) -> Codec raise ErasureErrorfn FrameCatalog::add_bytes(self : FrameCatalog, wire : Bytes, max_encoded_bytes? : Int) -> Unit raise ErasureErrorfn FrameCatalog::add_many(self : FrameCatalog, frames : Array[ShardEnvelope], max_frames? : Int) -> Int raise ErasureErrorfn FrameCatalog::get(self : FrameCatalog, stripe_index : Int, shard_index : Int) -> ShardEnvelope? raise ErasureErrorfn FrameCatalog::invalidate(self : FrameCatalog, stripe_index : Int, shard_index : Int) -> Bool raise ErasureErrorfn FrameCatalog::missing_indices(self : FrameCatalog, stripe_index : Int) -> Array[Int] raise ErasureErrorfn FrameCatalog::recover_range(self : FrameCatalog, start : Int, length : Int, max_encoded_bytes? : Int) -> Bytes raise ErasureErrorfn FrameCatalog::recover_stripe(self : FrameCatalog, stripe_index : Int, max_encoded_bytes? : Int) -> StripeRecovery raise ErasureErrorfn FrameCatalog::recoverable_ranges(self : FrameCatalog, max_ranges? : Int) -> Array[RecoverableRange] raise ErasureErrorfn FrameCatalog::stripe_frames(self : FrameCatalog, stripe_index : Int) -> Array[ShardEnvelope] raise ErasureErrorfn FrameCatalog::stripe_recoverable(self : FrameCatalog, stripe_index : Int) -> Bool raise ErasureErrorpub struct FrameIssue {
source_position : Int
code : String
}pub struct Manifest {
set_id : Int
data_count : Int
parity_count : Int
stripe_payload_limit : Int
stripe_count : Int
total_length : Int
}fn Manifest::from_bytes(input : Bytes, max_object_bytes? : Int, max_encoded_bytes? : Int) -> Manifest raise ErasureErrorfn Manifest::new(codec : Codec, set_id : Int, stripe_payload_limit : Int, total_length : Int, max_object_bytes? : Int) -> Manifest raise ErasureErrorfn ObjectDecoder::new(manifest : Manifest, max_encoded_bytes? : Int) -> ObjectDecoder raise ErasureErrorfn ObjectDecoder::push_stripe(self : ObjectDecoder, frames : Array[ShardEnvelope]) -> Bytes raise ErasureErrorfn ObjectEncoder::new(codec : Codec, set_id : Int, total_length : Int, stripe_payload_limit? : Int, max_object_bytes? : Int) -> ObjectEncoder raise ErasureErrorfn ObjectEncoder::push(self : ObjectEncoder, chunk : Bytes) -> Array[ShardEnvelope] raise ErasureErrorpub struct ObjectHealth {
stripes : Array[StripeHealth]
healthy_count : Int
repairable_count : Int
unrecoverable_count : Int
invalid_count : Int
}pub struct ObjectRecovery {
payload : Bytes
repaired_shard_count : Int
stripe_count : Int
}pub struct RecoverableRange {
start : Int
end : Int
}pub struct RecoverySession {
codec : Codec
entries : Array[DecoderEntry]
capacity : Int
next_evict : Int
hits : Int
misses : Int
}fn RecoverySession::reconstruct(self : RecoverySession, shards : Array[Bytes?]) -> Array[Bytes] raise ErasureErrorpub struct ShardEnvelope {
set_id : Int
stripe_index : Int
shard_index : Int
data_count : Int
parity_count : Int
original_length : Int
payload : Bytes
}fn ShardEnvelope::from_bytes(input : Bytes, max_encoded_bytes? : Int) -> ShardEnvelope raise ErasureErrorfn ShardEnvelope::new(codec : Codec, set_id : Int, stripe_index : Int, shard_index : Int, original_length : Int, payload : Bytes) -> ShardEnvelope raise ErasureErrorpub struct StripeHealth {
stripe_index : Int
status : StripeStatus
present_count : Int
missing_indices : Array[Int]
reason_code : String?
}pub struct StripeRecovery {
payload : Bytes
shards : Array[ShardEnvelope]
missing_indices : Array[Int]
provided_count : Int
}pub(all) enum StripeStatus {
Healthy
Repairable
Unrecoverable
InvalidInput
}fn encode_object(codec : Codec, payload : Bytes, set_id : Int, stripe_payload_limit? : Int, max_object_bytes? : Int, max_output_bytes? : Int) -> EncodedObject raise ErasureErrorfn encode_stripe(codec : Codec, payload : Bytes, set_id : Int, stripe_index : Int) -> Array[ShardEnvelope] raise ErasureErrorfn import_bundle(input : Bytes, max_input_bytes? : Int, max_object_bytes? : Int, max_encoded_bytes? : Int) -> EncodedObject raise ErasureErrorfn inspect_object(manifest : Manifest, frames : Array[ShardEnvelope], max_encoded_bytes? : Int) -> ObjectHealth raise ErasureErrorfn inspect_serialized_object(manifest : Manifest, inputs : Array[Bytes], max_encoded_bytes? : Int, max_total_bytes? : Int) -> ScannedObjectHealth raise ErasureErrorfn inspect_stripe(codec : Codec, frames : Array[ShardEnvelope], set_id : Int, stripe_index : Int) -> StripeHealthfn recover_object(manifest : Manifest, frames : Array[ShardEnvelope], max_encoded_bytes? : Int) -> ObjectRecovery raise ErasureErrorfn recover_object_range(manifest : Manifest, frames : Array[ShardEnvelope], start : Int, length : Int, max_encoded_bytes? : Int) -> Bytes raise ErasureErrorfn recover_serialized_object(manifest : Manifest, inputs : Array[Bytes], max_encoded_bytes? : Int, max_total_bytes? : Int) -> ScannedObjectRecovery raise ErasureErrorfn recover_serialized_range(manifest : Manifest, inputs : Array[Bytes], start : Int, length : Int, max_encoded_bytes? : Int, max_total_bytes? : Int) -> ScannedRangeRecovery raise ErasureErrorfn recover_serialized_stripe(codec : Codec, inputs : Array[Bytes], set_id : Int, stripe_index : Int) -> ScannedRecovery raise ErasureErrorfn recover_stripe(codec : Codec, frames : Array[ShardEnvelope], set_id : Int, stripe_index : Int) -> StripeRecovery raise ErasureErrorfn repair_object(manifest : Manifest, frames : Array[ShardEnvelope], max_encoded_bytes? : Int) -> ObjectRepair raise ErasureErrorfn repair_serialized_object(manifest : Manifest, inputs : Array[Bytes], max_encoded_bytes? : Int, max_total_bytes? : Int) -> ScannedObjectRepair raise ErasureErrorfn scan_frames(inputs : Array[Bytes], max_frames? : Int, max_encoded_bytes? : Int, max_total_bytes? : Int) -> FrameScan raise ErasureErrorInstall
Download zipPortable Reed-Solomon shard recovery and integrity envelopes