Files
spacedrive/core/prisma/schema.prisma
Ericson "Fogo" Soares 1d30850c21 Resumable Jobs + Lefthook Integration (#344)
* Introducing Lefthook for git hooks automation
* TypeScript typechecking and linting
* Rust formatting and linting
* Spellchecking (also corrected spell errors in some files)
* Check links in md files

* Introducing resumable jobs
* Abstractions to pause and resume jobs automatically when application exits and is started
* Changing database to use Bytes for UUID fields
* Changing uuid fields on core to use uuid::Uuid instead of String
* Updating some dependencies and introducing msg_pack serialization to save job state on database

* Fixing some clippy warnings

* Fixing a regression introduced on identifier job, doing too much db accesses concurrently
2022-07-27 00:06:34 -07:00

359 lines
11 KiB
Plaintext

datasource db {
provider = "sqlite"
url = "file:dev.db"
}
generator client {
provider = "cargo prisma"
output = "../src/prisma.rs"
}
model Migration {
id Int @id @default(autoincrement())
name String
checksum String @unique
steps_applied Int @default(0)
applied_at DateTime @default(now())
@@map("_migrations")
}
model SyncEvent {
id Int @id @default(autoincrement())
node_id Int
timestamp String
// individual record pub id OR compound many-to-many pub ids
record_id Bytes
// the type of operation, I.E: CREATE, UPDATE, DELETE as an enum
kind Int
// the column name for atomic update operations
column String?
// the new value for create/update operations, msgpack encoded
value String
node Node @relation(fields: [node_id], references: [id])
@@map("sync_events")
}
model Statistics {
id Int @id @default(autoincrement())
date_captured DateTime @default(now())
total_file_count Int @default(0)
library_db_size String @default("0")
total_bytes_used String @default("0")
total_bytes_capacity String @default("0")
total_unique_bytes String @default("0")
total_bytes_free String @default("0")
preview_media_bytes String @default("0")
@@map("statistics")
}
model Node {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String
platform Int @default(0)
version String?
last_seen DateTime @default(now())
timezone String?
date_created DateTime @default(now())
sync_events SyncEvent[]
jobs Job[]
Location Location[]
@@map("nodes")
}
model Volume {
id Int @id @default(autoincrement())
node_id Int
name String
mount_point String
total_bytes_capacity String @default("0")
total_bytes_available String @default("0")
disk_type String?
filesystem String?
is_system Boolean @default(false)
date_modified DateTime @default(now())
@@unique([node_id, mount_point, name])
@@map("volumes")
}
model Location {
id Int @id @default(autoincrement())
pub_id Bytes @unique
node_id Int?
name String?
local_path String?
total_capacity Int?
available_capacity Int?
filesystem String?
disk_type Int?
is_removable Boolean?
is_online Boolean @default(true)
date_created DateTime @default(now())
node Node? @relation(fields: [node_id], references: [id])
file_paths FilePath[]
@@map("locations")
}
model File {
id Int @id @default(autoincrement())
// content addressable storage id - sha256 sampled checksum
cas_id String @unique
// full byte contents digested into sha256 checksum
integrity_checksum String? @unique
// basic metadata
kind Int @default(0)
size_in_bytes String
key_id Int?
// handy ways to mark a file
hidden Boolean @default(false)
favorite Boolean @default(false)
important Boolean @default(false)
// if we have generated preview media for this file
has_thumbnail Boolean @default(false)
has_thumbstrip Boolean @default(false)
has_video_preview Boolean @default(false)
// integration with ipfs
ipfs_id String?
// plain text note
note String?
// the original known creation date of this file
date_created DateTime @default(now())
// the last time this file was modified
date_modified DateTime @default(now())
// when this file was first indexed
date_indexed DateTime @default(now())
tags TagOnFile[]
labels LabelOnFile[]
albums FileInAlbum[]
spaces FileInSpace[]
paths FilePath[]
comments Comment[]
media_data MediaData?
key Key? @relation(fields: [key_id], references: [id])
@@map("files")
}
model FilePath {
id Int @id @default(autoincrement())
is_dir Boolean @default(false)
// location that owns this path
location_id Int?
// a path generated from local file_path ids eg: "34/45/67/890"
materialized_path String
// the name and extension
name String
extension String?
// the unique File for this file path
file_id Int?
// the parent in the file tree
parent_id Int?
key_id Int? // replacement for encryption
// permissions String?
// temp_cas_id String? // so a filepath can be created without its File, as they're created lazily
date_created DateTime @default(now())
date_modified DateTime @default(now())
date_indexed DateTime @default(now())
file File? @relation(fields: [file_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
location Location? @relation(fields: [location_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
// NOTE: this self relation for the file tree was causing SQLite to go to forever bed, disabling until workaround
// parent FilePath? @relation("directory_file_paths", fields: [parent_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
// children FilePath[] @relation("directory_file_paths")
key Key? @relation(fields: [key_id], references: [id])
@@unique([location_id, materialized_path, name, extension])
@@index([location_id])
@@map("file_paths")
}
// if there is a conflicting cas_id, the conficting file should be updated to have a larger cas_id as the field is unique, however this record is kept to tell the indexer (upon discovering this CAS) that there is alternate versions of the file and to check by a full integrity hash to define for which to associate with.
model FileConflict {
original_file_id Int @unique
detactched_file_id Int @unique
@@map("file_conflicts")
}
// keys allow us to know exactly which files can be decrypted with a given key
// they can be "mounted" to a client, and then used to decrypt files automatically
model Key {
id Int @id @default(autoincrement())
// used to identify the key when it is entered by user
checksum String @unique
name String?
// nullable if concealed for security
date_created DateTime? @default(now())
// so we know which algorithm to use, can be null if user must select
algorithm Int? @default(0)
files File[]
file_paths FilePath[]
@@map("keys")
}
model MediaData {
id Int @id
pixel_width Int?
pixel_height Int?
longitude Float?
latitude Float?
fps Int?
capture_device_make String? // eg: "Apple"
capture_device_model String? // eg: "iPhone 12"
capture_device_software String? // eg: "12.1.1"
duration_seconds Int?
codecs String? // eg: "h264,acc"
streams Int?
// change this relation to File after testing
files File? @relation(fields: [id], references: [id], onDelete: Cascade, onUpdate: Cascade)
@@map("media_data")
}
model Tag {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
color String?
total_files Int? @default(0)
redundancy_goal Int? @default(1)
date_created DateTime @default(now())
date_modified DateTime @default(now())
tag_files TagOnFile[]
@@map("tags")
}
model TagOnFile {
date_created DateTime @default(now())
tag_id Int
tag Tag @relation(fields: [tag_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
file_id Int
file File @relation(fields: [file_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
@@id([tag_id, file_id])
@@map("tags_on_file")
}
model Label {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
date_created DateTime @default(now())
date_modified DateTime @default(now())
label_files LabelOnFile[]
@@map("labels")
}
model LabelOnFile {
date_created DateTime @default(now())
label_id Int
label Label @relation(fields: [label_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
file_id Int
file File @relation(fields: [file_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
@@id([label_id, file_id])
@@map("label_on_file")
}
model Space {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String?
description String?
date_created DateTime @default(now())
date_modified DateTime @default(now())
files FileInSpace[]
@@map("spaces")
}
model FileInSpace {
date_created DateTime @default(now())
space_id Int
space Space @relation(fields: [space_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
file_id Int
file File @relation(fields: [file_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
@@id([space_id, file_id])
@@map("file_in_space")
}
model Job {
id Bytes @id
name String
node_id Int
action Int
status Int @default(0)
data Bytes?
task_count Int @default(1)
completed_task_count Int @default(0)
date_created DateTime @default(now())
date_modified DateTime @default(now())
seconds_elapsed Int @default(0)
nodes Node @relation(fields: [node_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
@@map("jobs")
}
model Album {
id Int @id @default(autoincrement())
pub_id Bytes @unique
name String
is_hidden Boolean @default(false)
date_created DateTime @default(now())
date_modified DateTime @default(now())
files FileInAlbum[]
@@map("albums")
}
model FileInAlbum {
date_created DateTime @default(now())
album_id Int
album Album @relation(fields: [album_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
file_id Int
file File @relation(fields: [file_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
@@id([album_id, file_id])
@@map("files_in_albums")
}
model Comment {
id Int @id @default(autoincrement())
pub_id Bytes @unique
content String
date_created DateTime @default(now())
date_modified DateTime @default(now())
file_id Int?
file File? @relation(fields: [file_id], references: [id])
@@map("comments")
}