[db/ui] remove instantiations, use plain relations with aliases instead
parent
e47f74f884
commit
00cac1bca1
|
@ -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()))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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
|
||||
};
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue