about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2021-12-02 15:07:49 +0300
committerVika <vika@fireburn.ru>2021-12-02 15:07:49 +0300
commit11a57326f17b4f33d8683b9d12aa63b5f3a2d41d (patch)
tree126af0be64583c99aaecfe88c87281d19730e453
parent99d6a56336c8c6e5a3e5fb9f132bb15157fc1525 (diff)
downloadkittybox-11a57326f17b4f33d8683b9d12aa63b5f3a2d41d.tar.zst
Finally finish the migration tool
It works. Launch it using the "kittybox-database-converter" command.
First argument should be the old database URI, second should be the
new one. It will migrate the DB for you.

If you're doing this on a test machine, you can then migrate the
database to production using `rsync -rl` to preserve symbolic links
created by Kittybox's database backend.
-rw-r--r--src/bin/kittybox_database_converter.rs44
1 files changed, 25 insertions, 19 deletions
diff --git a/src/bin/kittybox_database_converter.rs b/src/bin/kittybox_database_converter.rs
index ff28d49..900a5c6 100644
--- a/src/bin/kittybox_database_converter.rs
+++ b/src/bin/kittybox_database_converter.rs
@@ -1,6 +1,5 @@
 use anyhow::{anyhow, Context};
 use redis::{self, AsyncCommands};
-use futures_util::StreamExt;
 use kittybox::database::Storage;
 use kittybox::database::FileStorage;
 use std::collections::HashMap;
@@ -14,26 +13,33 @@ async fn convert_from_redis<S: Storage>(from: String, new_storage: S) -> anyhow:
     // Rebinding to convince the borrow checker we're not smuggling stuff outta scope
     let storage = &new_storage;
     
-    conn.hscan::<_, String>("posts").await?.map(|it| async move {
-        let json = serde_json::from_str(&it);
-        (it, json)
-    }).for_each_concurrent(8, |it| async move {
-        let (orig, res): (String, serde_json::Result<serde_json::Value>) = it.await;
-        match res {
-            Ok(json) => {
-                // XXX this assumes a trusted database that was created with Kittybox that checks for UID matching user token's prefix
-                let user = &(url::Url::parse(json["properties"]["uid"][0].as_str().unwrap()).unwrap().origin().ascii_serialization().clone() + "/");
-                if let Err(err) = storage.clone().put_post(&json, user).await {
-                    eprintln!("Error saving post: {}", err);
-                }
-            },
-            Err(err) => {
-                eprintln!("Error: {} (rejected JSON follows below on stderr)", err);
-                eprintln!("{}", orig);
-            }
+    let mut stream = conn.hscan::<_, String>("posts").await?;
+
+    while let Some(key) = stream.next_item().await {
+        let value = serde_json::from_str::<serde_json::Value>(
+            &stream.next_item().await
+                .ok_or(anyhow!("Failed to find a corresponding value for the key"))?
+        )?;
+
+        println!("{}, {:?}", key, value);
+
+        if value["see_other"].is_string() {
+            continue
         }
-    }).await;
 
+        let user = &(
+            url::Url::parse(
+                value["properties"]["uid"][0]
+                    .as_str().unwrap()
+            ).unwrap().origin().ascii_serialization().clone()
+                + "/"
+        );
+        if let Err(err) = storage.clone().put_post(&value, user).await {
+            eprintln!("Error saving post: {}", err);
+        }
+        
+    }
+    
     let mut stream: redis::AsyncIter<String> = conn.scan_match("settings_*").await?;
     while let Some(key) = stream.next_item().await {
         let mut conn = db.get_async_std_connection().await.context("Failed to connect to Redis")?;