-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from ovnanova/repo_and_mst
Blockstore and other repo building blocks
- Loading branch information
Showing
34 changed files
with
679 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# Used by "mix format" | ||
[ | ||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], | ||
locals_without_parens: [from: 2], | ||
locals_without_parens: [from: 2] | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,49 @@ | ||
defmodule Hexpds.BlockStore do | ||
@callback put_block(key :: binary(), value :: binary()) :: :ok | {:error, term()} | ||
@callback put_block(value :: binary()) :: :ok | {:error, term()} | ||
@callback get_block(key :: binary()) :: {:ok, binary()} | {:error, term()} | ||
@callback del_block(key :: binary()) :: :ok | {:error, term()} | ||
end | ||
|
||
defmodule BlocksTable do | ||
defmodule Hexpds.BlocksTable do | ||
use Ecto.Schema | ||
|
||
schema "blocks" do | ||
field(:key, :string) | ||
field(:value, :binary) | ||
field(:block_cid, :string) # A CID | ||
field(:block_value, :binary) # A Dag-CBOR blob | ||
|
||
timestamps() | ||
end | ||
end | ||
|
||
defmodule Hexpds.EctoBlockStore do | ||
import Ecto.Query | ||
@behaviour Hexpds.BlockStore | ||
|
||
def init(_type, config) do | ||
{:ok, Keyword.put(config, :database, :memory)} | ||
end | ||
|
||
def put_block(key, value) do | ||
case Hexpds.Database.get_by(BlocksTable, key: key) do | ||
nil -> | ||
case Hexpds.Database.insert!(%BlocksTable{key: key, value: value}) do | ||
{:ok, _} -> :ok | ||
{:error, _} -> {:error, :insert_failed} | ||
end | ||
|
||
{:ok, res} when res == value -> | ||
:ok | ||
|
||
{:ok, _} -> | ||
{:error, :different_value} | ||
|
||
{:error, _} -> | ||
{:error, :get_failed} | ||
alias Hexpds.{BlockStore, DagCBOR, BlocksTable} | ||
@behaviour BlockStore | ||
|
||
@impl BlockStore | ||
def put_block(value) do | ||
cid = Hexpds.Repo.Helpers.term_to_dagcbor_cid(value) | ||
case get_block(cid) do | ||
{:error, :not_found} -> | ||
%BlocksTable{ | ||
block_cid: cid, | ||
block_value: DagCBOR.encode!(value) | ||
} | ||
|> Hexpds.User.Sqlite.insert!() | ||
anything_else -> anything_else | ||
end | ||
end | ||
|
||
@impl BlockStore | ||
def get_block(key) do | ||
case Hexpds.Database.get_by(BlocksTable, key: key) do | ||
case Hexpds.User.Sqlite.get_by(BlocksTable, block_cid: key) do | ||
nil -> {:error, :not_found} | ||
block -> {:ok, block.value} | ||
%BlocksTable{} = block -> block | ||
end | ||
end | ||
|
||
@impl BlockStore | ||
def del_block(key) do | ||
Hexpds.Database.delete_all(from(b in BlocksTable, where: b.key == ^key)) | ||
Hexpds.User.Sqlite.delete_all(from(b in BlocksTable, where: b.block_cid == ^key)) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
defmodule Hexpds.User.Sqlite do | ||
@moduledoc """ | ||
Users' repos will be stored in individual sqlite DBs | ||
""" | ||
|
||
use Ecto.Repo, | ||
otp_app: :hexpds, | ||
adapter: Ecto.Adapters.SQLite3 | ||
|
||
def get_for_user(%Hexpds.User{did: did}) do | ||
repo_path = "repos/#{did}/repo.db" | ||
{:ok, db} = start_link(name: nil, database: repo_path) | ||
db | ||
end | ||
|
||
|
||
def migrate(migrations) do | ||
order_migrations = | ||
migrations | ||
|> Enum.with_index() | ||
|> Enum.map(fn {m, i} -> {i, m} end) | ||
Ecto.Migrator.run(__MODULE__, order_migrations, :up, all: true, dynamic_repo: get_dynamic_repo()) | ||
end | ||
|
||
def exec(user, callback) do | ||
repo = get_for_user(user) | ||
try do | ||
put_dynamic_repo(repo) | ||
callback.() | ||
after | ||
Supervisor.stop(repo) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
defmodule Hexpds.User.Sqlite.Migrations.Macros do | ||
defmacro migration(migration_name, do: change_block) do | ||
# need to satisfy my DSL addiction - sj | ||
quote do | ||
@migrations __MODULE__.unquote(migration_name) | ||
defmodule unquote(migration_name) do | ||
use Ecto.Migration | ||
|
||
def change do | ||
unquote(change_block) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
defmodule Hexpds.User.Sqlite.Migrations do | ||
Module.register_attribute(__MODULE__, :migrations, accumulate: true) | ||
|
||
import __MODULE__.Macros | ||
|
||
migration SetupBlockstore do | ||
create table(:blocks) do | ||
add(:block_cid, :string, primary_key: true, null: false) | ||
add(:block_value, :binary, null: false) | ||
|
||
timestamps() # Maybe will be helpful if we do special sync APIs | ||
end | ||
end | ||
|
||
migration CommitsAndRecords do | ||
create table(:commits) do | ||
add :seq, :integer, primary_key: true, null: false | ||
add :cid, :string, null: false | ||
|
||
timestamps() # Probably not strictly necessary, but why not? Better safe than sorry, can easily remove later | ||
end | ||
create table(:records) do | ||
add :record_path, :text, primary_key: true, null: false | ||
add :collection, :string, null: false | ||
add :record_cid, :string, null: false | ||
|
||
timestamps() # Will help with sorting for e.g. listRecords | ||
end | ||
end | ||
|
||
migration MstNodes do | ||
# Have probably gotten some of this wrong and may need to change implementation | ||
create table(:mst_nodes) do | ||
add :cid, :string, primary_key: true, null: false | ||
add :left, :string, comment: "CID link, optional: link to sub-tree Node on a lower level and with all keys sorting before keys at this node" | ||
add :parent_node_cid, :string | ||
add :depth, :int, null: false | ||
end | ||
create table(:tree_entries) do | ||
add :tree_entry_key, :text, primary_key: true, null: false # This is equivalent to record path | ||
add :parent_node_cid, :string, null: false | ||
add :value, :string, null: false # CID link to the record data (CBOR) for this entry | ||
add :right, :string # link to a sub-tree Node at a lower level which has keys sorting after this TreeEntry's key (to the "right"), but before the next TreeEntry's key in this Node (if any) | ||
end | ||
end | ||
|
||
migration SomeUsefulIndices do | ||
# Admittedly I might also be getting this wrong | ||
create index(:tree_entries, :parent_node_cid) | ||
create index(:mst_nodes, :parent_node_cid) | ||
create unique_index(:records, :record_cid) | ||
create index(:records, :collection) | ||
create unique_index(:tree_entries, :value) | ||
create index(:mst_nodes, :depth) | ||
end | ||
|
||
def all, do: Enum.reverse(@migrations) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
defmodule Hexpds.Firehose do | ||
defp cbor_concat(header, op) do | ||
[header, op] | ||
|> Enum.map(&Hexpds.DagCBOR.encode!/1) | ||
|> Enum.reverse() | ||
|> Enum.reduce(&<>/2) | ||
end | ||
|
||
def error(type, message \\ nil) do | ||
cbor_concat(%{op: -1}, optional_join(%{error: type}, if(message, do: %{message: message}))) | ||
end | ||
|
||
defp optional_join(map, nil), do: map | ||
defp optional_join(map1, map2), do: Map.merge(map1, map2) | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
defmodule Hexpds.Firehose.Websocket do | ||
@behaviour WebSock | ||
|
||
@impl WebSock | ||
def init(_params) do | ||
# We can ignore the params for now but we should use them for backfilling later | ||
pid = self() | ||
:syn.join(:firehose, :websockets, pid) | ||
{:ok, nil} | ||
end | ||
|
||
@impl WebSock | ||
def handle_info({:firehose_message, bindata}, _) do | ||
{:push, {:binary, bindata}, nil} | ||
end | ||
|
||
@impl WebSock | ||
def handle_in(_, _) do | ||
# Ignore incoming messages | ||
{:ok, nil} | ||
end | ||
|
||
def push_frame(frame) do | ||
:syn.publish(:firehose, :websockets, {:firehose_message, frame}) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.