Refactor database (#63)

This commit is contained in:
BlowaterNostr 2023-07-11 17:49:58 +08:00 committed by GitHub
parent 41eedc0630
commit 52d7f0ed05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 104 additions and 94 deletions

View File

@ -1,7 +1,7 @@
/** @jsx h */
import { h, render } from "https://esm.sh/preact@10.11.3";
import { setup } from "https://esm.sh/twind@0.16.16";
import { NewIndexedDB } from "./db.ts";
import { NewIndexedDB } from "./dexie-db.ts";
import { Start } from "./app.tsx";
setup({
@ -16,7 +16,7 @@ setup({
},
});
const database = await NewIndexedDB();
const database = NewIndexedDB();
if (database instanceof Error) {
console.error(database);
render(

View File

@ -13,7 +13,7 @@ import { EventBus } from "../event-bus.ts";
import { MessagePanel } from "./message-panel.tsx";
import { Setting } from "./setting.tsx";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { getAllUsersInformation, ProfilesSyncer, UserInfo } from "./contact-list.ts";
@ -41,11 +41,13 @@ import { AppList } from "./app-list.tsx";
import { SecondaryBackgroundColor } from "./style/colors.ts";
import { EventSyncer } from "./event_syncer.ts";
import { getRelayURLs } from "./setting.ts";
import { DexieDatabase } from "./dexie-db.ts";
export async function Start(database: Database) {
export async function Start(database: DexieDatabase) {
console.log("Start the application");
const lamport = time.fromEvents(database.filterEvents((_) => true));
const app = new App(database, lamport);
const dbView = await Database_Contextual_View.New(database);
const lamport = time.fromEvents(dbView.filterEvents((_) => true));
const app = new App(dbView, lamport);
const ctx = await getCurrentSignInCtx();
console.log("Start:", ctx);
if (ctx instanceof Error) {
@ -79,7 +81,7 @@ export async function Start(database: Database) {
async function initProfileSyncer(
pool: ConnectionPool,
accountContext: NostrAccountContext,
database: db.Database,
database: db.Database_Contextual_View,
) {
const myPublicKey = accountContext.publicKey;
@ -168,7 +170,7 @@ export class App {
eventSyncer: EventSyncer;
constructor(
public readonly database: Database,
public readonly database: Database_Contextual_View,
public readonly lamport: time.LamportTime,
) {
this.model = initialModel();

View File

@ -1,4 +1,4 @@
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { PublicKey } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts";
import {

View File

@ -4,7 +4,7 @@ import { App } from "./app.tsx";
import { getAllUsersInformation, getGroupOf, ProfilesSyncer, UserInfo } from "./contact-list.ts";
import * as csp from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { convertEventsToChatMessages } from "./dm.ts";
import { get_Kind4_Events_Between, sendDMandImages, sendSocialPost } from "../features/dm.ts";
@ -357,7 +357,7 @@ export async function* UI_Interaction_Update(
}
export function getConversationMessages(args: {
database: Database;
database: Database_Contextual_View;
pub1: string;
pub2: string;
allUserInfo: Map<string, UserInfo>;
@ -416,7 +416,7 @@ export function updateConversation(
//////////////
export async function* Database_Update(
ctx: NostrAccountContext,
database: Database,
database: Database_Contextual_View,
model: Model,
profileSyncer: ProfilesSyncer,
lamport: LamportTime,

View File

@ -4,7 +4,7 @@ import { ContactList } from "./contact-list.tsx";
import { fail } from "https://deno.land/std@0.176.0/testing/asserts.ts";
import { NewIndexedDB } from "./db.ts";
import { NewIndexedDB } from "./dexie-db.ts";
import { EventBus } from "../event-bus.ts";
import { UI_Interaction_Event } from "./app_update.ts";

View File

@ -1,4 +1,4 @@
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { ProfileEvent, ProfileFromNostrEvent, profilesStream } from "../features/profile.ts";
import { Channel } from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
@ -33,7 +33,7 @@ export class ProfilesSyncer {
private chan = new Channel<string[]>();
constructor(
private readonly database: Database,
private readonly database: Database_Contextual_View,
private readonly pool: ConnectionPool,
) {
(async () => {
@ -98,7 +98,7 @@ function socialPostsStream(pubkeys: Iterable<string>, pool: ConnectionPool) {
}
export function getAllUsersInformation(
database: Database,
database: Database_Contextual_View,
myAccountContext: NostrAccountContext,
): Map<string, UserInfo> {
const t = Date.now();

View File

@ -2,7 +2,7 @@
import { Fragment, h } from "https://esm.sh/preact@10.11.3";
import { tw } from "https://esm.sh/twind@0.16.16";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { Avatar } from "./components/avatar.tsx";
import { CenterClass, IconButtonClass, LinearGradientsClass } from "./components/tw.ts";
import { sortUserInfo, UserInfo } from "./contact-list.ts";
@ -22,7 +22,7 @@ import { PrimaryBackgroundColor, PrimaryTextColor } from "./style/colors.ts";
type Props = {
myAccountContext: NostrAccountContext;
database: Database;
database: Database_Contextual_View;
eventEmitter: EventEmitter<ContactUpdate>;
// Model

View File

@ -1,39 +0,0 @@
import * as dexie from "https://unpkg.com/dexie@3.2.3/dist/modern/dexie.mjs";
import { Database, Indices } from "../database.ts";
import { NostrEvent } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
export class Events extends dexie.Dexie {
// 'friends' is added by dexie when declaring the stores()
// We just tell the typing system this is the case
// @ts-ignore
events!: dexie.Table<NostrEvent>;
constructor() {
super("Events");
this.version(6).stores({
events: "&id, created_at, kind, tags, pubkey", // indices
});
}
}
export async function NewIndexedDB(): Promise<Database | Error> {
try {
const db = new Events();
const cache: NostrEvent[] = await db.events.filter((_: any) => true).toArray();
return new Database(
async (event: NostrEvent) => {
await db.events.put(event);
cache.push(event);
},
async (keys: Indices) => {
return db.events.get(keys);
},
(filter: (e: NostrEvent) => boolean) => {
return cache.filter(filter);
},
);
} catch (e) {
return e;
}
}

26
UI/dexie-db.ts Normal file
View File

@ -0,0 +1,26 @@
import * as dexie from "https://unpkg.com/dexie@3.2.3/dist/modern/dexie.mjs";
import { Database_Contextual_View, Indices } from "../database.ts";
import { NostrEvent } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
export class DexieDatabase extends dexie.Dexie {
// 'friends' is added by dexie when declaring the stores()
// We just tell the typing system this is the case
// @ts-ignore
events!: dexie.Table<NostrEvent>;
constructor() {
super("Events");
this.version(6).stores({
events: "&id, created_at, kind, tags, pubkey", // indices
});
}
}
export function NewIndexedDB(): DexieDatabase | Error {
try {
const db = new DexieDatabase();
return db;
} catch (e) {
return e;
}
}

View File

@ -1,4 +1,4 @@
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { getProfiles, ProfileData, ProfileEvent } from "../features/profile.ts";
import { NostrEvent } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
import { getTags, groupImageEvents, reassembleBase64ImageFromEvents } from "../nostr.ts";

View File

@ -2,7 +2,7 @@
import { h, VNode } from "https://esm.sh/preact@10.11.3";
import { tw } from "https://esm.sh/twind@0.16.16";
import * as cl from "./contact-list.tsx";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { MessagePanel, RightPanelModel } from "./message-panel.tsx";
import { EventBus } from "../event-bus.ts";
import { LeftArrowIcon } from "./icons/left-arrow-icon.tsx";
@ -27,7 +27,7 @@ type DirectMessageContainerProps = {
myAccountContext: NostrAccountContext;
pool: ConnectionPool;
eventEmitter: EventBus<UI_Interaction_Event>;
db: Database;
db: Database_Contextual_View;
allUserInfo: Map<string, UserInfo>;
profilesSyncer: ProfilesSyncer;
eventSyncer: EventSyncer;

View File

@ -2,12 +2,12 @@ import {
ConnectionPool,
SubscriptionAlreadyExist,
} from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { NoteID } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nip19.ts";
import { verifyEvent } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
export class EventSyncer {
constructor(private readonly pool: ConnectionPool, private readonly db: Database) {}
constructor(private readonly pool: ConnectionPool, private readonly db: Database_Contextual_View) {}
syncEvent(id: NoteID) {
const iter = Array.from(this.db.filterEvents((e) => e.id == id.hex));
if (iter.length > 0) {

View File

@ -1,7 +1,7 @@
/** @jsx h */
import { h, render } from "https://esm.sh/preact@10.11.3";
import { NewIndexedDB } from "./db.ts";
import { NewIndexedDB } from "./dexie-db.ts";
import { MessagePanel } from "./message-panel.tsx";
import { EventBus } from "../event-bus.ts";
import { PrivateKey, PublicKey } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts";

View File

@ -20,7 +20,7 @@ import { getProfileEvent, ProfileData } from "../features/profile.ts";
import { MessageThread } from "./dm.tsx";
import { UserDetail } from "./user-detail.tsx";
import { MessageThreadPanel } from "./message-thread-panel.tsx";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import {
DividerBackgroundColor,
HoverButtonBackgroudColor,
@ -49,7 +49,7 @@ interface DirectMessagePanelProps {
rightPanelModel: RightPanelModel;
db: Database;
db: Database_Contextual_View;
eventEmitter: EventEmitter<
EditorEvent | DirectMessagePanelUpdate | PinContact | UnpinContact
>;
@ -183,7 +183,7 @@ export function MessagePanel(props: DirectMessagePanelProps) {
interface MessageListProps {
myPublicKey: PublicKey;
threads: MessageThread[];
db: Database;
db: Database_Contextual_View;
eventEmitter: EventEmitter<DirectMessagePanelUpdate>;
profilesSyncer: ProfilesSyncer;
eventSyncer: EventSyncer;
@ -311,7 +311,7 @@ function MessageBoxGroup(props: {
replyCount: number;
}[];
myPublicKey: PublicKey;
db: Database;
db: Database_Contextual_View;
eventEmitter: EventEmitter<DirectMessagePanelUpdate | ViewUserDetail>;
profilesSyncer: ProfilesSyncer;
eventSyncer: EventSyncer;
@ -443,7 +443,7 @@ export function NameAndTime(message: ChatMessage, index: number, myPublicKey: Pu
export function ParseMessageContent(
message: ChatMessage,
db: Database,
db: Database_Contextual_View,
profilesSyncer: ProfilesSyncer,
eventSyncer: EventSyncer,
eventEmitter: EventEmitter<ViewUserDetail>,

View File

@ -12,7 +12,7 @@ import {
import { PublicKey } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts";
import { ChatMessage, groupContinuousMessages } from "./message.ts";
import { Editor, EditorEvent, EditorModel } from "./editor.tsx";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { ProfilesSyncer } from "./contact-list.ts";
import { EventSyncer } from "./event_syncer.ts";
@ -20,7 +20,7 @@ interface MessageThreadProps {
eventEmitter: EventEmitter<DirectMessagePanelUpdate | EditorEvent>;
messages: ChatMessage[];
myPublicKey: PublicKey;
db: Database;
db: Database_Contextual_View;
editorModel: EditorModel;
profilesSyncer: ProfilesSyncer;
eventSyncer: EventSyncer;
@ -63,7 +63,7 @@ export function MessageThreadPanel(props: MessageThreadProps) {
function MessageThreadList(props: {
myPublicKey: PublicKey;
messages: ChatMessage[];
db: Database;
db: Database_Contextual_View;
profilesSyncer: ProfilesSyncer;
eventSyncer: EventSyncer;
eventEmitter: EventEmitter<ViewUserDetail>;
@ -98,7 +98,7 @@ function MessageThreadList(props: {
function MessageThreadBoxGroup(props: {
messages: ChatMessage[];
myPublicKey: PublicKey;
db: Database;
db: Database_Contextual_View;
profilesSyncer: ProfilesSyncer;
eventSyncer: EventSyncer;
eventEmitter: EventEmitter<ViewUserDetail>;

View File

@ -1,7 +1,7 @@
/** @jsx h */
import { h, render } from "https://esm.sh/preact@10.11.3";
import { NewIndexedDB } from "./db.ts";
import { NewIndexedDB } from "./dexie-db.ts";
import * as nav from "./nav.tsx";
import { tw } from "https://esm.sh/twind@0.16.16";

View File

@ -23,7 +23,7 @@ import { SettingIcon } from "./icons2/setting-icon.tsx";
export type Props = {
profilePicURL: string | undefined;
publicKey: PublicKey;
database: db.Database;
database: db.Database_Contextual_View;
pool: ConnectionPool;
AddRelayButtonClickedError: string;
AddRelayInput: string;

View File

@ -1,4 +1,4 @@
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
const damus = "wss://relay.damus.io";
const nos = "wss://nos.lol";
@ -9,6 +9,6 @@ export const defaultRelays = [
"wss://relay.nostr.wirednet.jp",
];
export function getRelayURLs(db: Database): string[] {
export function getRelayURLs(db: Database_Contextual_View): string[] {
return defaultRelays;
}

View File

@ -12,6 +12,7 @@ import {
} from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
import { getTags, Tag } from "./nostr.ts";
import * as csp from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
import { DexieDatabase } from "./UI/dexie-db.ts";
export const NotFound = Symbol("Not Found");
const buffer_size = 1000;
@ -23,18 +24,33 @@ export interface Indices {
readonly pubkey?: string;
}
export class Database {
export class Database_Contextual_View {
private readonly sourceOfChange = csp.chan<NostrEvent>(buffer_size);
private readonly caster = csp.multi<NostrEvent>(this.sourceOfChange);
static async New(database: DexieDatabase) {
const cache: NostrEvent[] = await database.events.filter((_: any) => true).toArray();
return new Database_Contextual_View(database, cache);
}
constructor(
private addToIndexedDB: (event: NostrEvent) => Promise<void>,
public getEvent: (keys: Indices) => Promise<NostrEvent | undefined>,
public filterEvents: (
filter: (e: NostrEvent) => boolean,
) => Iterable<NostrEvent>,
private readonly database: DexieDatabase,
private readonly cache: NostrEvent[],
) {}
public readonly getEvent = async (keys: Indices): Promise<NostrEvent | undefined> => {
return this.database.events.get(keys);
};
public readonly filterEvents = (filter: (e: NostrEvent) => boolean) => {
return this.cache.filter(filter);
};
private readonly addToIndexedDB = async (event: NostrEvent) => {
await this.database.events.put(event);
this.cache.push(event);
};
async addEvent(event: NostrEvent) {
const storedEvent = await this.getEvent({ id: event.id });
if (storedEvent) { // event exist

View File

@ -24,6 +24,7 @@
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts": "93c5c6fe196dc9cae7c0e82ee8057a5350f77e69ae7d395fdb141a25b2664739",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/scure.js": "fbc4be16918272bd167fff1184a7f5bbd1a676bad2a73130bb530d78df893a99",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/vendor/esm.sh/v106/@noble/secp256k1@1.7.1/es2022/secp256k1.js": "69e32f6c686cc651ff2e6d4d22ed6e9b6f86b38311b405b47b2abdf3cb98eb4d",
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/websocket.ts": "d817c40d32fe45e30bfb30255287e76a977930f6709c9585772dc54e077a31ed"
"https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/websocket.ts": "d817c40d32fe45e30bfb30255287e76a977930f6709c9585772dc54e077a31ed",
"https://unpkg.com/dexie@3.2.3/dist/modern/dexie.mjs": "63f0ed30a7ac5698fe88152899fd526ac1294067dc28283505151b436c2ee1ba"
}
}

View File

@ -1,5 +1,5 @@
import * as csp from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
import { Database, NotFound, whoIamTalkingTo } from "../database.ts";
import { Database_Contextual_View, NotFound, whoIamTalkingTo } from "../database.ts";
import {
DecryptionFailure,
decryptNostrEvent,
@ -262,11 +262,11 @@ function merge<T>(...iters: AsyncIterable<T>[]) {
//////////////////
// get the messages send by and received by pubkey
export function getDirectMessageEventsOf(db: Database, pubkey: string) {
export function getDirectMessageEventsOf(db: Database_Contextual_View, pubkey: string) {
return db.filterEvents(filterDMof(pubkey));
}
export function getContactPubkeysOf(db: Database, pubkey: string): Set<string> | Error {
export function getContactPubkeysOf(db: Database_Contextual_View, pubkey: string): Set<string> | Error {
const msgs = getDirectMessageEventsOf(db, pubkey);
const contactList = new Set<string>();
for (const event of msgs) {
@ -279,7 +279,7 @@ export function getContactPubkeysOf(db: Database, pubkey: string): Set<string> |
return contactList;
}
export function getNewestEventOf(db: Database, pubkey: string): NostrEvent | typeof NotFound {
export function getNewestEventOf(db: Database_Contextual_View, pubkey: string): NostrEvent | typeof NotFound {
const events = Array.from(getDirectMessageEventsOf(db, pubkey));
if (events.length === 0) {
return NotFound;
@ -293,7 +293,11 @@ export function getNewestEventOf(db: Database, pubkey: string): NostrEvent | typ
return newest;
}
export function get_Kind4_Events_Between(db: Database, myPubKey: string, contactPubkey: string) {
export function get_Kind4_Events_Between(
db: Database_Contextual_View,
myPubKey: string,
contactPubkey: string,
) {
const events = db.filterEvents(
filterDMBetween(myPubKey, contactPubkey),
);

View File

@ -1,5 +1,5 @@
import * as csp from "https://raw.githubusercontent.com/BlowaterNostr/csp/master/csp.ts";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import {
ConnectionPool,
newSubID,
@ -71,7 +71,7 @@ export async function saveProfile(
pool.sendEvent(event);
}
export function getProfileEvent(db: Database, pubkey: PublicKey): ProfileEvent | undefined {
export function getProfileEvent(db: Database_Contextual_View, pubkey: PublicKey): ProfileEvent | undefined {
const events = Array.from(db.filterEvents((e) => {
return e.kind === NostrKind.META_DATA && e.pubkey === pubkey.hex;
}));
@ -83,7 +83,7 @@ export function getProfileEvent(db: Database, pubkey: PublicKey): ProfileEvent |
return ProfileFromNostrEvent(newest);
}
export function getProfilesByName(db: Database, name: string): ProfileEvent[] {
export function getProfilesByName(db: Database_Contextual_View, name: string): ProfileEvent[] {
const events = Array.from(db.filterEvents((e) => {
return e.kind === NostrKind.META_DATA;
}));
@ -104,7 +104,7 @@ export function getProfilesByName(db: Database, name: string): ProfileEvent[] {
}
export function getProfiles(
db: Database,
db: Database_Contextual_View,
pubkeys: Set<string>,
): Map<string, /*pubkey*/ ProfileEvent | undefined> {
const contacts: Map<string, ProfileEvent | undefined> = new Map();

View File

@ -1,5 +1,5 @@
import { ChatMessage } from "../UI/message.ts";
import { Database } from "../database.ts";
import { Database_Contextual_View } from "../database.ts";
import { NostrKind } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
import { PublicKey } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts";
@ -8,7 +8,7 @@ import { computeThreads, getTags } from "../nostr.ts";
import { MessageThread } from "../UI/dm.tsx";
import { UserInfo } from "../UI/contact-list.ts";
export function getSocialPosts(db: Database, allUsersInfo: Map<string, UserInfo>) {
export function getSocialPosts(db: Database_Contextual_View, allUsersInfo: Map<string, UserInfo>) {
const t = Date.now();
const events = db.filterEvents((e) => {
return e.kind == NostrKind.TEXT_NOTE;