update follows table, rename importer
This commit is contained in:
parent
88b870031e
commit
3caefad767
5 changed files with 41 additions and 37 deletions
|
@ -12,8 +12,13 @@ create table if not exists users (
|
||||||
last_seen int,
|
last_seen int,
|
||||||
pwhash blob not null,
|
pwhash blob not null,
|
||||||
invited_by blob not null,
|
invited_by blob not null,
|
||||||
last_updated int not null default (unixepoch())
|
is_active int not null default 1,
|
||||||
|
last_updated int not null default (unixepoch()),
|
||||||
|
foreign key (invited_by) references users (id)
|
||||||
);
|
);
|
||||||
|
create index if not exists users_username_dex on users (lower(username));
|
||||||
|
create index if not exists users_email_dex on users (lower(email));
|
||||||
|
create index if not exists users_invited_by_dex on users (invited_by);
|
||||||
|
|
||||||
-- invitations
|
-- invitations
|
||||||
create table if not exists invites (
|
create table if not exists invites (
|
||||||
|
@ -24,6 +29,8 @@ create table if not exists invites (
|
||||||
last_updated int not null default (unixepoch()),
|
last_updated int not null default (unixepoch()),
|
||||||
foreign key (owner) references users (id) on delete cascade on update no action
|
foreign key (owner) references users (id) on delete cascade on update no action
|
||||||
);
|
);
|
||||||
|
create index if not exists invites_owner_dex on invites (owner);
|
||||||
|
|
||||||
|
|
||||||
-- table of things to watch
|
-- table of things to watch
|
||||||
create table if not exists watches (
|
create table if not exists watches (
|
||||||
|
@ -37,6 +44,7 @@ create table if not exists watches (
|
||||||
last_updated int not null default (unixepoch()),
|
last_updated int not null default (unixepoch()),
|
||||||
foreign key (added_by) references users (id)
|
foreign key (added_by) references users (id)
|
||||||
);
|
);
|
||||||
|
create index if not exists watches_title_dex on watches (lower(title));
|
||||||
|
|
||||||
-- table of what people want to watch
|
-- table of what people want to watch
|
||||||
create table if not exists watch_quests (
|
create table if not exists watch_quests (
|
||||||
|
@ -52,15 +60,18 @@ create table if not exists watch_quests (
|
||||||
foreign key (watch) references watches (id) on delete cascade on update no action,
|
foreign key (watch) references watches (id) on delete cascade on update no action,
|
||||||
primary key (user, watch)
|
primary key (user, watch)
|
||||||
);
|
);
|
||||||
|
create index if not exists quests_user_dex on watch_quests (user);
|
||||||
|
create index if not exists quests_watch_dex on watch_quests (watch);
|
||||||
|
|
||||||
|
|
||||||
-- friend lists; created by trigger at the same time as the user, so no created_at needed
|
|
||||||
create table if not exists follows (
|
create table if not exists follows (
|
||||||
user blob not null primary key,
|
follower blob not null,
|
||||||
follows blob, -- possibly empty friends list in some app-specific format
|
followee blob not null,
|
||||||
last_updated int not null default (unixepoch()),
|
created_at int not null default (unixepoch()),
|
||||||
foreign key (user) references users (id) on delete cascade on update no action
|
foreign key (follower) references users (id) on delete cascade on update no action
|
||||||
|
foreign key (followee) references users (id) on delete cascade on update no action
|
||||||
);
|
);
|
||||||
|
create index if not exists follows_follower_dex on follows (follower);
|
||||||
|
create index if not exists follows_followee_dex on follows (followee);
|
||||||
|
|
||||||
create table if not exists watch_notes (
|
create table if not exists watch_notes (
|
||||||
id blob not null primary key default (julid_new()), -- a user can have multiple notes about the same thing
|
id blob not null primary key default (julid_new()), -- a user can have multiple notes about the same thing
|
||||||
|
@ -72,13 +83,7 @@ create table if not exists watch_notes (
|
||||||
foreign key (user) references users (id) on delete cascade on update no action,
|
foreign key (user) references users (id) on delete cascade on update no action,
|
||||||
foreign key (watch) references watches (id) on delete cascade on update no action
|
foreign key (watch) references watches (id) on delete cascade on update no action
|
||||||
);
|
);
|
||||||
|
|
||||||
-- indices, not needed for follows
|
|
||||||
create index if not exists users_username_dex on users (lower(username));
|
|
||||||
create index if not exists users_email_dex on users (lower(email));
|
|
||||||
create index if not exists watches_title_dex on watches (lower(title));
|
|
||||||
create index if not exists watches_added_by_dex on watches (added_by);
|
|
||||||
create index if not exists quests_user_dex on watch_quests (user);
|
|
||||||
create index if not exists quests_watch_dex on watch_quests (watch);
|
|
||||||
create index if not exists notes_user_dex on watch_notes (user);
|
create index if not exists notes_user_dex on watch_notes (user);
|
||||||
create index if not exists notes_watch_dex on watch_notes (watch);
|
create index if not exists notes_watch_dex on watch_notes (watch);
|
||||||
|
|
||||||
|
-- indices
|
||||||
|
|
|
@ -12,18 +12,6 @@ BEGIN
|
||||||
update invites set last_updated = (select unixepoch()) where id=NEW.id;
|
update invites set last_updated = (select unixepoch()) where id=NEW.id;
|
||||||
END;
|
END;
|
||||||
|
|
||||||
create trigger if not exists insert_user_follows
|
|
||||||
after insert on users
|
|
||||||
BEGIN
|
|
||||||
insert into follows (user) values (NEW.id);
|
|
||||||
END;
|
|
||||||
|
|
||||||
create trigger if not exists delete_user_follows
|
|
||||||
after delete on users
|
|
||||||
BEGIN
|
|
||||||
delete from follows where user = OLD.id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
create trigger if not exists update_last_updated_watches
|
create trigger if not exists update_last_updated_watches
|
||||||
after update on watches
|
after update on watches
|
||||||
when OLD.last_updated = NEW.last_updated or OLD.last_updated is null
|
when OLD.last_updated = NEW.last_updated or OLD.last_updated is null
|
||||||
|
@ -38,13 +26,6 @@ BEGIN
|
||||||
update watch_quests set last_updated = (select unixepoch()) where watch=NEW.watch and user=NEW.user;
|
update watch_quests set last_updated = (select unixepoch()) where watch=NEW.watch and user=NEW.user;
|
||||||
END;
|
END;
|
||||||
|
|
||||||
create trigger if not exists update_last_updated_follows
|
|
||||||
after update on follows
|
|
||||||
when OLD.last_updated = NEW.last_updated or OLD.last_updated is null
|
|
||||||
BEGIN
|
|
||||||
update follows set last_updated = (select unixepoch()) where id=NEW.id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
create trigger if not exists update_last_updated_watch_notes
|
create trigger if not exists update_last_updated_watch_notes
|
||||||
after update on watch_notes
|
after update on watch_notes
|
||||||
when OLD.last_updated = NEW.last_updated or OLD.last_updated is null
|
when OLD.last_updated = NEW.last_updated or OLD.last_updated is null
|
||||||
|
|
|
@ -196,7 +196,6 @@ pub(crate) async fn create_user(
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let invitation = Julid::from_str(invitation).map_err(|_| CreateUserErrorKind::BadInvitation)?;
|
let invitation = Julid::from_str(invitation).map_err(|_| CreateUserErrorKind::BadInvitation)?;
|
||||||
|
|
||||||
let invited_by = validate_invitation(invitation, &mut tx).await?;
|
let invited_by = validate_invitation(invitation, &mut tx).await?;
|
||||||
|
|
||||||
let user = sqlx::query_as(CREATE_QUERY)
|
let user = sqlx::query_as(CREATE_QUERY)
|
||||||
|
@ -444,7 +443,7 @@ mod test {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
std::thread::sleep(Duration::from_millis(500));
|
||||||
|
|
||||||
let username = "too slow";
|
let username = "too slow";
|
||||||
|
|
||||||
|
|
21
src/users.rs
21
src/users.rs
|
@ -16,7 +16,7 @@ const LAST_SEEN_QUERY: &str = "update users set last_seen = (select unixepoch())
|
||||||
const INSERT_QUERY: &str =
|
const INSERT_QUERY: &str =
|
||||||
"insert into users (id, username, displayname, email, pwhash, invited_by) values ($1, $2, $3, $4, $5, $6)";
|
"insert into users (id, username, displayname, email, pwhash, invited_by) values ($1, $2, $3, $4, $5, $6)";
|
||||||
|
|
||||||
#[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: Julid,
|
pub id: Julid,
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
@ -25,6 +25,7 @@ pub struct User {
|
||||||
pub last_seen: Option<i64>,
|
pub last_seen: Option<i64>,
|
||||||
pub pwhash: String,
|
pub pwhash: String,
|
||||||
pub invited_by: Julid,
|
pub invited_by: Julid,
|
||||||
|
pub is_active: bool,
|
||||||
pub digest: String,
|
pub digest: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +40,29 @@ impl sqlx::FromRow<'_, SqliteRow> for User {
|
||||||
email: row.try_get("email")?,
|
email: row.try_get("email")?,
|
||||||
last_seen: row.try_get("last_seen")?,
|
last_seen: row.try_get("last_seen")?,
|
||||||
invited_by: row.try_get("invited_by")?,
|
invited_by: row.try_get("invited_by")?,
|
||||||
|
is_active: row.try_get("is_active")?,
|
||||||
pwhash,
|
pwhash,
|
||||||
digest,
|
digest,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for User {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
is_active: true,
|
||||||
|
id: Default::default(),
|
||||||
|
username: Default::default(),
|
||||||
|
displayname: Default::default(),
|
||||||
|
email: Default::default(),
|
||||||
|
last_seen: Default::default(),
|
||||||
|
pwhash: Default::default(),
|
||||||
|
invited_by: Default::default(),
|
||||||
|
digest: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Debug for User {
|
impl Debug for User {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("User")
|
f.debug_struct("User")
|
||||||
|
@ -55,6 +73,7 @@ impl Debug for User {
|
||||||
.field("last_seen", &self.last_seen)
|
.field("last_seen", &self.last_seen)
|
||||||
.field("digest", &self.digest)
|
.field("digest", &self.digest)
|
||||||
.field("invited_by", &self.invited_by.as_string())
|
.field("invited_by", &self.invited_by.as_string())
|
||||||
|
.field("is_active", &self.is_active)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue