服务器 元数据:SQLite 与 Postgres
元数据:SQLite 与 Postgres
存储桶没有文件夹、所有者、权限或回收站的概念。这些信息存放在旁边的元数据存储中,它只写入改动的部分,每次一个改动。
本页内容
各种存储
| 存储 | 适用于 |
|---|---|
| memoryMetadata() | 测试和演示:进程结束后即消失。 |
| sqliteMetadata(path) | 运行在单台服务器上的应用:一个文件,使用 Node 自带的 node:sqlite。 |
| postgresMetadata(pool) | 多台服务器,或没有磁盘的托管环境:使用你自己的驱动,每次改动都会加数据库锁。 |
使用 Postgres
import pg from 'pg';
import { postgresMetadata } from '@rebofiles/server';
metadata: await postgresMetadata(new pg.Pool({ connectionString: process.env.DATABASE_URL })),它接受任何带有 query(text, values) 并返回 { rows } 的对象:pg、Neon 的 Pool、PGlite。传入连接池时,每次改动在读写期间都会持有数据库锁,因此两台服务器永远不会同时修改网盘;没有连接池时,同一时刻创建的两个文件夹可能都会被命名为 “(2)”。用 { table: 'acme_files' } 可以指定其他表名。
保存的内容
- 条目:每个一行,以 JSON 形式保存。
- 网盘和每个人的设置,以及经 scrypt 处理后的链接密码。
- 动态记录:每条一行,可按条目及其所在文件夹查找。
- 每个文件的文字:SQLite 的全文搜索,或 Postgres 中的 tsvector。
- 一个随每次改动递增的修订号,让每个进程知道何时需要重新读取网盘。
你自己的存储
MetadataStore 只需实现 load() 和 save(changes);revision、lock、设置、record/activity 以及 keepText/findText 都是可选的,缺少时服务器会把这些信息保存在进程中。数据库结构一页列出了所有表。
按需读取
SQLite、Postgres 和内存存储只回答每个请求所需的内容:一个条目及其上层文件夹、文件夹中的内容、某个文件夹下的全部内容、按名称搜索、回收站、与某人共享的内容。网盘从不整体加载,每次更改只写入涉及的部分。其他进程的更改从它们保存的动态中读取。
| 一百个人,每人两千个文件 | 耗时 |
|---|---|
| 自己网盘的最顶层 | 13 ms |
| 包含 2,000 个文件的文件夹 | 22 ms |
| 按名称搜索 | 35 ms |
| 移动一个文件 | 8 ms |
查询所用的列和表会在首次打开旧数据库时添加,并一次性填充已有的行。自定义存储通过 scoped 实现同样的功能;没有它时,仍像以前一样整体保存在内存中。