Skip to content

Commit f4bba30

Browse files
committed
example: migration
1 parent e4aa089 commit f4bba30

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed

Diff for: examples/migration/.run

Whitespace-only changes.

Diff for: examples/migration/Cargo.toml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "migration"
3+
version = "0.0.1"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
fjall = { path = "../../" }
10+
rmp-serde = "1.1.2"
11+
serde = { version = "1.0.193", features = ["derive"] }

Diff for: examples/migration/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# migration
2+
3+
This example uses `fjall`, `serde` and `rmp-serde` to store and load persistent, structured data, then migrate it from one schema version to the next using `ingest`.

Diff for: examples/migration/src/main.rs

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use fjall::Config;
2+
use serde::{Deserialize, Serialize};
3+
4+
#[derive(Debug, Deserialize, Serialize)]
5+
pub struct PlanetV1 {
6+
/// ID
7+
id: String,
8+
9+
/// Name
10+
name: String,
11+
}
12+
13+
#[derive(Debug, Deserialize, Serialize)]
14+
pub struct PlanetV2 {
15+
/// ID
16+
id: String,
17+
18+
/// Name
19+
name: String,
20+
21+
/// Mass
22+
mass: Option<u128>,
23+
24+
/// Radius
25+
radius: Option<u128>,
26+
}
27+
28+
impl From<PlanetV1> for PlanetV2 {
29+
fn from(value: PlanetV1) -> Self {
30+
Self {
31+
id: value.id,
32+
name: value.name,
33+
mass: None,
34+
radius: None,
35+
}
36+
}
37+
}
38+
39+
#[derive(Debug, Deserialize, Serialize)]
40+
pub enum Planet {
41+
V1(PlanetV1),
42+
V2(PlanetV2),
43+
}
44+
45+
impl std::fmt::Display for Planet {
46+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47+
write!(f, "{:?}", self)
48+
}
49+
}
50+
51+
fn main() -> fjall::Result<()> {
52+
let path = std::path::Path::new(".fjall_data");
53+
54+
let keyspace = Config::new(path).temporary(true).open()?;
55+
let planets_v1 = keyspace.open_partition("v1_planets", Default::default())?;
56+
57+
for (id, name) in [
58+
("p:earth", "Earth"),
59+
("p:jupiter", "Jupiter"),
60+
("p:neptune", "Mars"),
61+
("p:neptune", "Mercury"),
62+
("p:neptune", "Neptune"),
63+
("p:saturn", "Saturn"),
64+
("p:uranus", "Uranus"),
65+
("p:venus", "Venus"),
66+
] {
67+
planets_v1.insert(
68+
id,
69+
rmp_serde::to_vec(&Planet::V1(PlanetV1 {
70+
id: id.into(),
71+
name: name.into(),
72+
}))
73+
.unwrap(),
74+
)?;
75+
}
76+
77+
eprintln!("--- v1 ---");
78+
for kv in planets_v1.iter() {
79+
let (_, v) = kv?;
80+
let planet = rmp_serde::from_slice::<Planet>(&v).unwrap();
81+
eprintln!("{planet:?}");
82+
}
83+
84+
// Do migration from V1 -> V2
85+
let planets_v2 = keyspace.open_partition("v2_planets", Default::default())?;
86+
87+
let stream = planets_v1.iter().map(|kv| {
88+
let (k, v) = kv.unwrap();
89+
let planet = rmp_serde::from_slice::<Planet>(&v).unwrap();
90+
91+
if let Planet::V1(planet) = planet {
92+
let v2: PlanetV2 = planet.into();
93+
let v2 = Planet::V2(v2);
94+
(k, rmp_serde::to_vec(&v2).unwrap())
95+
} else {
96+
unreachable!("v1 does not contain other versions");
97+
}
98+
});
99+
planets_v2.ingest(stream)?;
100+
101+
eprintln!("--- v2 ---");
102+
for kv in planets_v2.iter() {
103+
let (_, v) = kv?;
104+
let planet = rmp_serde::from_slice::<Planet>(&v).unwrap();
105+
eprintln!("{planet:?}");
106+
}
107+
108+
assert_eq!(planets_v1.len()?, planets_v2.len()?);
109+
110+
// Delete old data
111+
keyspace.delete_partition(planets_v1)?;
112+
113+
Ok(())
114+
}

0 commit comments

Comments
 (0)