Pigeon-Ruby/lib/pigeon/database.rb

216 lines
4.7 KiB
Ruby
Raw Normal View History

module Pigeon
class Database
attr_reader :who_am_i
2020-04-18 15:30:35 +00:00
def initialize(path: PIGEON_DB_PATH)
@store = Pigeon::Storage.new(path: path)
2020-04-18 15:51:08 +00:00
init_ident
end
2020-04-19 15:26:21 +00:00
# === PEERS
2020-04-25 15:11:25 +00:00
def add_peer(p)
store.add_peer(p)
end
def block_peer(p)
store.block_peer(p)
end
def remove_peer(p)
store.remove_peer(p)
end
def peer_blocked?(p)
store.peer_blocked?(p)
end
def all_blocks
store.all_blocks
end
def all_peers
store.all_peers
end
2020-04-19 15:26:21 +00:00
# === MESSAGES
2020-04-25 15:11:25 +00:00
def all_messages(mhash = nil)
store.all_messages(mhash)
end
2020-04-26 13:51:14 +00:00
def have_message?(multihash)
store.have_message?(multihash)
2020-04-25 15:11:25 +00:00
end
2020-04-18 14:59:56 +00:00
def _save_message(msg_obj)
2020-04-18 14:59:56 +00:00
store.insert_message(Helpers.verify_message(self, msg_obj))
end
2020-04-25 15:11:25 +00:00
def read_message(multihash)
store.read_message(multihash)
end
2020-04-17 13:55:18 +00:00
def get_message_count_for(multihash)
store.get_message_count_for(multihash)
end
def get_message_by_depth(multihash, depth)
store.get_message_by_depth(multihash, depth)
end
def add_message(kind, params)
2020-04-19 21:27:09 +00:00
publish_draft(new_draft(kind: kind, body: params))
end
2020-04-19 15:26:21 +00:00
# Store a message that someone (not the LocalIdentity)
# has authored.
def _ingest_message(author:,
body:,
depth:,
kind:,
lipmaa:,
prev:,
signature:)
2020-04-19 15:26:21 +00:00
msg = Message.new(author: RemoteIdentity.new(author),
kind: kind,
body: body,
prev: prev,
lipmaa: lipmaa,
signature: signature,
depth: depth)
_save_message(msg)
end
2020-04-19 15:26:21 +00:00
# === DRAFTS
2020-04-26 13:51:14 +00:00
def delete_current_draft
_add_config(CURRENT_DRAFT, nil)
2020-04-25 15:11:25 +00:00
end
2020-04-19 21:27:09 +00:00
def new_draft(kind:, body: {})
old = _get_config(CURRENT_DRAFT)
2020-05-14 13:25:02 +00:00
if old
raise STILL_HAVE_DRAFT % old.kind
end
2020-04-26 13:51:14 +00:00
_replace_draft(Draft.new(kind: kind, body: body))
end
2020-04-26 13:51:14 +00:00
def _replace_draft(draft)
_add_config(CURRENT_DRAFT, draft)
draft
end
def get_draft
draft = store._get_config(CURRENT_DRAFT)
2020-04-25 15:11:25 +00:00
unless draft
2020-05-14 13:25:02 +00:00
raise MISSING_DRAFT
2020-04-19 21:27:09 +00:00
end
2020-04-25 15:11:25 +00:00
draft
end
2020-04-25 15:11:25 +00:00
def update_draft(k, v)
Helpers.update_draft(self, k, v)
end
2020-04-19 21:27:09 +00:00
2020-04-26 13:51:14 +00:00
def delete_current_draft
_add_config(CURRENT_DRAFT, nil)
2020-04-18 14:13:53 +00:00
end
# Author a new message.
2020-04-25 15:11:25 +00:00
def publish_draft(draft = get_draft)
2020-04-18 14:13:53 +00:00
Helpers.publish_draft(self, draft)
end
2020-04-19 15:26:21 +00:00
# === BUNDLES
2020-04-24 11:20:02 +00:00
def export_bundle(file_path = DEFAULT_BUNDLE_PATH)
Helpers.mkdir_p(file_path)
# Fetch messages for all peers
peers = all_peers + [who_am_i.multihash]
messages = peers.map do |peer|
all_messages(peer)
.map { |multihash| read_message(multihash) }
.sort_by(&:depth)
end.flatten
# Attach blobs for all messages in bundle.
2020-04-22 13:21:55 +00:00
messages
.map(&:collect_blobs)
.flatten
.uniq
.map do |mhash|
2020-04-25 14:47:58 +00:00
blob = get_blob(mhash)
2020-04-25 15:31:32 +00:00
Helpers.write_to_disk(file_path, mhash, blob)
end
# Render messages for all peers.
content = messages
2020-04-25 15:11:25 +00:00
.map(&:render)
.join(BUNDLE_MESSAGE_SEPARATOR)
2020-05-14 13:25:02 +00:00
File.write(File.join(file_path, MESSAGE_FILE), content + CR)
2020-04-19 15:26:21 +00:00
end
2020-04-24 11:20:02 +00:00
def import_bundle(file_path = DEFAULT_BUNDLE_PATH)
2020-05-14 13:25:02 +00:00
bundle = File.read(File.join(file_path, MESSAGE_FILE))
2020-04-19 15:26:21 +00:00
tokens = Pigeon::Lexer.tokenize(bundle)
messages = Pigeon::Parser.parse(self, tokens)
messages
.map(&:collect_blobs)
.flatten
.uniq
2020-05-07 12:30:32 +00:00
.map do |mhash|
rel_path = Helpers.hash2file_path(mhash)
from = File.join([file_path] + rel_path)
to = File.join([PIGEON_BLOB_PATH] + rel_path)
if (File.file?(from) && !File.file?(to))
data = File.read(from)
Helpers.write_to_disk(PIGEON_BLOB_PATH, mhash, data)
end
end
messages
2020-04-18 14:37:43 +00:00
end
2020-04-19 15:26:21 +00:00
# === BLOBS
2020-04-25 15:11:25 +00:00
def get_blob(b)
store.get_blob(b)
end
def add_blob(b)
store.add_blob(b)
end
2020-04-19 15:26:21 +00:00
def have_blob?(b)
store.have_blob?(b)
end
2020-04-19 15:26:21 +00:00
# === DB Management
def _get_config(k)
store._get_config(k)
2020-04-25 15:11:25 +00:00
end
def _add_config(k, v)
store._add_config(k, v)
2020-04-25 15:11:25 +00:00
end
def reset_database
store.reset
init_ident
end
2020-04-19 15:26:21 +00:00
private
attr_reader :store
2020-04-18 15:30:35 +00:00
def init_ident
secret = _get_config(SEED_CONFIG_KEY)
2020-04-18 15:30:35 +00:00
if secret
@who_am_i = LocalIdentity.new(secret)
else
2020-04-18 15:30:35 +00:00
new_seed = SecureRandom.random_bytes(Ed25519::KEY_SIZE)
_add_config(SEED_CONFIG_KEY, new_seed)
@who_am_i = LocalIdentity.new(new_seed)
end
end
end
end