資料模型
bae 的目錄是一般 SQLite,逐表宣告給 coven:同步表帶有衝突時鐘並前往每個裝置;未宣告的表永遠不離開裝置。這個分割是資料模型最承重的決定,因此本頁圍繞它組織。
Schema 中會同步的核心:
artists、albums、works:群組層。專輯聚合其發行版本並指向一個主要版本;作品形成古典結構的父子圖。- **
releases* : 中央实体,每次打印一行,包含打印事实(标签、目录编号、条形码、国家、格式、年份 ) 、 可选元数据来源、导入文件夹的内容哈希值和测量的专辑音量。 没有来源意味着元数据是直接输入的;外部来源指定了准确的源发行日期,而檔案標籤记录了本地快照来源。 - **
release_identities* : 发布版本 * 的确切外部标识。 没有行意味着没有外部标识。 每行都命名一个 MusicBrainz 或 Discogs 发布版本和发布组,一个发布版本可以同时在两个来源中拥有标识。 这是与来源分开的:标识可以改变,而不声称当前可编辑的元数据是从该来源重置的。 tracks搭配track_artists,以及release_artist_roles與track_artist_roles:曲目清單與名單,每個名單都標記其來源。track_works、work_parts、work_artists:錄音連到它們演出的作品。audio_formats與audio_format_segments:播放規格。每曲:編解碼器、取樣率、位元深度、聲道、測得響度與峰值,以及 pregap 長度。Segments 將曲目映射到其來源檔案中有序的位元組與樣本區段;這就是 CUE 擷取的曲目(包含 pregap)能跨越一個大型檔案或多個檔案區域的方式。release_files、covers、artist_images:帶有 blob 的表。列是目錄項目;位元組存在 coven 的 blob 層中(見下方)。
同步、受門控、本機
Section titled “同步、受門控、本機”以上全都會同步,但不是無條件同步。releases 以其 remote 欄位宣告為 gated root:發行版本列與其整個子樹(曲目、檔案、名單、格式、封面)只在 remote 為 true 時同步,也就是發行版本由雲端管理時。將發行版本切到受管理會發布子樹;不受管理的發行版本即使其 schema 會同步,也會完全留在匯入裝置上。祖先表(artists、albums、works)只在仍有某個已同步發行版本引用它們時同步,因此裝置永遠不會收到下面沒有任何內容的藝人。
完全本機且永不宣告給 coven 的表:
playback_state:目前曲目、位置、佇列、音量、隨機播放與重複播放。播放是裝置事實。imports:匯入操作追蹤。- **
source_release_payloads** : 从MusicBrainz和Discogs存档的原始JSON, 按提供商发布而不是本地发布键入,支持在不更改同步目录图形的情况下进行精确重置和重新解释。
每個同步表都帶有 _updated_at hybrid-logical-clock 欄位,也就是 coven 逐欄合併並行編輯時排序的 register;測試會強制同步表集合與帶有 clock 的表集合完全相等。
音訊與圖片會經過 coven 的 blob 層,位於三個 namespace,各自有裝置快取預算:release_files(20 GiB)、covers(512 MiB)、artist_images(256 MiB)。
發行版本檔案由使用者提供並延遲快取:不受管理發行版本的 blob 是對使用者原始路徑檔案的外部引用;受管理發行版本則是上傳物件,在第一次讀取時抓入快取。封面與藝人圖片由主機提供並主動快取:bae 產生位元組(封面會重新算圖為最寬 600px 的 JPEG 縮圖),每個裝置在 取得時抓取它們,讓格狀清單可在本機呈現。
在不透明主目錄上,blob 會以無意義內容 key 上傳。在可瀏覽主目錄上,每個 blob 列都記錄可讀的雲端路徑(音訊為 {artist}/{album}/{filename},封面為 {album}/{release}/cover.{ext}),並在上傳時計算一次,因此稍後重新命名不會移動物件。
releases.content_hash 是對匯入資料夾檔案結構(相對路徑與大小)的 SHA-256,與資料夾在磁碟上的位置無關。這讓 bae 能在同一份擷取再次出現在監看資料夾時辨識它,也讓重新匯入找到應替換的發行版本。