[db/ui] remove instantiations, use plain relations with aliases instead

feat/vaults
Tomáš Mládek 2021-10-29 18:05:03 +02:00
parent e47f74f884
commit 00cac1bca1
4 changed files with 52 additions and 91 deletions

View File

@ -24,7 +24,6 @@ use log::{error, info, warn};
use once_cell::unsync::Lazy;
use rayon::prelude::*;
use serde_json::Value;
use uuid::Uuid;
use walkdir::WalkDir;
const DIR_TYPE: &str = "FS_DIR";
@ -38,9 +37,7 @@ lazy_static! {
}
const BLOB_TYPE: &str = "BLOB";
const FILE_TYPE: &str = "FS_FILE";
const FILE_IDENTITY_KEY: &str = "FILE_IS";
const FILENAME_KEY: &str = "FILE_NAME";
const ALIAS_KEY: &str = "ALIAS";
const FILE_MIME_KEY: &str = "FILE_MIME";
const FILE_MTIME_KEY: &str = "FILE_MTIME";
const FILE_SIZE_KEY: &str = "FILE_SIZE";
@ -50,11 +47,6 @@ lazy_static! {
value: EntryValue::Value(Value::from(BLOB_TYPE)),
};
static ref BLOB_TYPE_ADDR: Address = BLOB_TYPE_INVARIANT.entity().unwrap();
static ref FILE_TYPE_INVARIANT: InvariantEntry = InvariantEntry {
attribute: String::from(TYPE_IS_ATTR),
value: EntryValue::Value(Value::from(FILE_TYPE)),
};
static ref FILE_TYPE_ADDR: Address = FILE_TYPE_INVARIANT.entity().unwrap();
}
fn initialize_types(pool: &DbPool) -> Result<()> {
@ -65,24 +57,6 @@ fn initialize_types(pool: &DbPool) -> Result<()> {
upend_insert_val!(&pool.get()?, BLOB_TYPE_ADDR, TYPE_HAS_ATTR, FILE_SIZE_KEY);
upend_insert_val!(&pool.get()?, BLOB_TYPE_ADDR, TYPE_HAS_ATTR, FILE_MIME_KEY);
// FILE_TYPE
insert_entry(&pool.get()?, Entry::try_from(&*FILE_TYPE_INVARIANT)?)?;
upend_insert_addr!(&pool.get()?, FILE_TYPE_ADDR, IS_OF_TYPE_ATTR, TYPE_ADDR);
upend_insert_val!(
&pool.get()?,
FILE_TYPE_ADDR,
TYPE_INSTANCES_ATTR,
FILE_IDENTITY_KEY
);
upend_insert_val!(&pool.get()?, FILE_TYPE_ADDR, TYPE_ID_ATTR, FILENAME_KEY);
upend_insert_val!(
&pool.get()?,
FILE_TYPE_ADDR,
TYPE_REQUIRES_ATTR,
FILE_IDENTITY_KEY
);
upend_insert_val!(&pool.get()?, FILE_TYPE_ADDR, TYPE_HAS_ATTR, FILE_MIME_KEY);
// DIR_TYPE
insert_entry(&pool.get()?, Entry::try_from(&*DIR_TYPE_INVARIANT)?)?;
upend_insert_addr!(&pool.get()?, DIR_TYPE_ADDR, IS_OF_TYPE_ATTR, TYPE_ADDR);
@ -240,7 +214,7 @@ fn _process_directory_entry<P: AsRef<Path>>(
let normalized_path = path.strip_prefix(&directory_path)?;
let normalized_path_str = normalized_path.to_str().expect("path not valid unicode?!");
let digest = Lazy::new(|| path.hash());
let file_hash = Lazy::new(|| path.hash());
// Get size & mtime for quick comparison
let metadata = fs::metadata(&path)?;
@ -267,7 +241,7 @@ fn _process_directory_entry<P: AsRef<Path>>(
if let Some((idx, existing_file)) = maybe_existing_file {
if (size == existing_file.size && mtime == existing_file.mtime)
|| ((*digest).is_ok() && &existing_file.hash == (*digest).as_ref().unwrap())
|| ((*file_hash).is_ok() && &existing_file.hash == (*file_hash).as_ref().unwrap())
{
if !existing_file.valid {
file_set_valid(&db_pool.write().unwrap().get()?, existing_file.id, true)?;
@ -279,14 +253,14 @@ fn _process_directory_entry<P: AsRef<Path>>(
}
// If not, add it!
if let Err(err) = &*digest {
if let Err(err) = &*file_hash {
return Err(anyhow!(format!("Error hashing: {}", err)));
}
let digest = (*digest).as_ref().unwrap().clone();
let file_hash = (*file_hash).as_ref().unwrap().clone();
let new_file = models::NewFile {
path: normalized_path_str.to_string(),
hash: (digest.clone()).0,
hash: (file_hash.clone()).0,
added: NaiveDateTime::from_timestamp(Utc::now().timestamp(), 0),
size,
mtime,
@ -296,29 +270,21 @@ fn _process_directory_entry<P: AsRef<Path>>(
// Insert metadata
let type_entry = Entry {
entity: Address::Hash(digest.clone()),
entity: Address::Hash(file_hash.clone()),
attribute: String::from(IS_OF_TYPE_ATTR),
value: EntryValue::Address(BLOB_TYPE_ADDR.clone()),
};
insert_entry(&db_pool.write().unwrap().get()?, type_entry)?;
let size_entry = Entry {
entity: Address::Hash(digest.clone()),
entity: Address::Hash(file_hash.clone()),
attribute: FILE_SIZE_KEY.to_string(),
value: EntryValue::Value(Value::from(size)),
};
insert_entry(&db_pool.write().unwrap().get()?, size_entry)?;
if let Some(mtime) = mtime {
let mtime_entry = Entry {
entity: Address::Hash(digest.clone()),
attribute: FILE_MTIME_KEY.to_string(),
value: EntryValue::Value(Value::from(mtime.timestamp())),
};
insert_entry(&db_pool.write().unwrap().get()?, mtime_entry)?;
}
let mime_entry = Entry {
entity: Address::Hash(digest.clone()),
entity: Address::Hash(file_hash.clone()),
attribute: FILE_MIME_KEY.to_string(),
value: EntryValue::Value(Value::String(tree_magic::from_filepath(&path))),
};
@ -341,37 +307,22 @@ fn _process_directory_entry<P: AsRef<Path>>(
let _pool = &db_pool.write().unwrap();
let connection = _pool.get()?;
connection.transaction::<_, Error, _>(|| {
let file_address = Address::Uuid(Uuid::new_v4());
let type_entry = Entry {
entity: file_address.clone(),
attribute: String::from(IS_OF_TYPE_ATTR),
value: EntryValue::Address(FILE_TYPE_ADDR.clone()),
let dir_has_entry = Entry {
entity: parent_dir.clone(),
attribute: HIER_HAS_ATTR.to_string(),
value: EntryValue::Address(Address::Hash(file_hash.clone())),
};
insert_entry(&connection, type_entry)?;
let dir_has_entry_addr = insert_entry(&connection, dir_has_entry)?;
let name_entry = Entry {
entity: file_address.clone(),
attribute: FILENAME_KEY.to_string(),
entity: dir_has_entry_addr,
attribute: ALIAS_KEY.to_string(),
value: EntryValue::Value(Value::String(
filename.as_os_str().to_string_lossy().to_string(),
)),
};
insert_entry(&connection, name_entry)?;
let identity_entry = Entry {
entity: file_address.clone(),
attribute: FILE_IDENTITY_KEY.to_string(),
value: EntryValue::Address(Address::Hash(digest.clone())),
};
insert_entry(&connection, identity_entry)?;
let dir_has_entry = Entry {
entity: parent_dir.clone(),
attribute: HIER_HAS_ATTR.to_string(),
value: EntryValue::Address(file_address),
};
insert_entry(&connection, dir_has_entry)?;
Ok(UpdatePathOutcome::Added(path.clone()))
})
}

View File

@ -47,8 +47,8 @@ export default defineComponent({
},
setup(props) {
// Identification
const { attributes } = useEntity(props.address, () => props.resolve);
const inferredEntries = identify(attributes);
const { attributes, backlinks } = useEntity(props.address, () => props.resolve);
const inferredEntries = identify(attributes, backlinks);
const inferredIds: ComputedRef<string[]> = computed(() => {
return inferredEntries.value.map((eid) => eid.value);
});

View File

@ -87,8 +87,32 @@ interface EntityIdentification {
}
export function identify(
attributes: ComputedRef<[string, IEntry][]>
attributes: ComputedRef<[string, IEntry][]>,
backlinks: ComputedRef<[string, IEntry][]>
): ComputedRef<EntityIdentification[]> {
// Get all entries where the object is linked
const hasEntries = computed(() => {
return backlinks.value
.filter(([_, entry]) => entry.attribute === "HAS")
.map(([addr, _]) => addr);
});
// Out of those relations, retrieve their ALIAS attrs
const { data: hasListing } = query(() => {
return (
hasEntries.value &&
`(matches (in ${hasEntries.value
.map(e => `"${e}"`)
.join(" ")}) "ALIAS" ?)`
);
});
const aliasValues: ComputedRef<string[]> = computed(() => {
return Object.values(hasListing.value || {}).map(entry => {
return entry.value.c;
});
});
// Get all identities of the object
const isEntries = computed(() => {
return attributes.value
@ -128,7 +152,15 @@ export function identify(
};
});
})
.flat();
.flat()
.concat(
aliasValues.value.map(value => {
return {
type: "ALIAS",
value
};
})
);
});
}

View File

@ -36,17 +36,6 @@
<div v-else class="error">
{{ error }}
</div>
<template v-if="referredAddress">
<div class="hr">
<hr />
<div class="hr-label">
<sl-icon name="chevron-double-down" />
Instantiates
<sl-icon name="chevron-double-down" />
</div>
</div>
<inspect :address="referredAddress" />
</template>
</div>
</template>
@ -158,16 +147,6 @@ export default defineComponent({
);
});
const referredAddress = computed(() => {
const fileIsAttr = attributes.value.find(
([_, entry]) => entry.attribute === "FILE_IS"
)?.[1];
if (fileIsAttr) {
return fileIsAttr.value.c;
}
});
return {
typedAttributes,
untypedAttributes: filteredUntypedAttributes,
@ -175,7 +154,6 @@ export default defineComponent({
error,
mutate,
types: allTypes,
referredAddress,
};
},
});