schema: add v3, rename nameplates.id to .name
This commit is contained in:
parent
6d00576ee4
commit
74a1902fcd
|
@ -16,7 +16,7 @@ def get_upgrader(new_version):
|
||||||
"db-schemas/upgrade-to-v%d.sql" % new_version)
|
"db-schemas/upgrade-to-v%d.sql" % new_version)
|
||||||
return schema_bytes.decode("utf-8")
|
return schema_bytes.decode("utf-8")
|
||||||
|
|
||||||
TARGET_VERSION = 2
|
TARGET_VERSION = 3
|
||||||
|
|
||||||
def dict_factory(cursor, row):
|
def dict_factory(cursor, row):
|
||||||
d = {}
|
d = {}
|
||||||
|
|
105
src/wormhole/server/db-schemas/v3.sql
Normal file
105
src/wormhole/server/db-schemas/v3.sql
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
|
||||||
|
-- note: anything which isn't an boolean, integer, or human-readable unicode
|
||||||
|
-- string, (i.e. binary strings) will be stored as hex
|
||||||
|
|
||||||
|
CREATE TABLE `version`
|
||||||
|
(
|
||||||
|
`version` INTEGER -- contains one row, set to 3
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
-- Wormhole codes use a "nameplate": a short name which is only used to
|
||||||
|
-- reference a specific (long-named) mailbox. The codes only use numeric
|
||||||
|
-- nameplates, but the protocol and server allow can use arbitrary strings.
|
||||||
|
CREATE TABLE `nameplates`
|
||||||
|
(
|
||||||
|
`app_id` VARCHAR,
|
||||||
|
`name` VARCHAR,
|
||||||
|
`mailbox_id` VARCHAR, -- really a foreign key
|
||||||
|
`side1` VARCHAR, -- side name, or NULL
|
||||||
|
`side2` VARCHAR, -- side name, or NULL
|
||||||
|
`request_id` VARCHAR, -- from 'allocate' message, for future deduplication
|
||||||
|
`crowded` BOOLEAN, -- at some point, three or more sides were involved
|
||||||
|
`updated` INTEGER, -- time of last activity, used for pruning
|
||||||
|
-- timing data
|
||||||
|
`started` INTEGER, -- time when nameplace was opened
|
||||||
|
`second` INTEGER -- time when second side opened
|
||||||
|
);
|
||||||
|
CREATE INDEX `nameplates_idx` ON `nameplates` (`app_id`, `name`);
|
||||||
|
CREATE INDEX `nameplates_updated_idx` ON `nameplates` (`app_id`, `updated`);
|
||||||
|
CREATE INDEX `nameplates_mailbox_idx` ON `nameplates` (`app_id`, `mailbox_id`);
|
||||||
|
CREATE INDEX `nameplates_request_idx` ON `nameplates` (`app_id`, `request_id`);
|
||||||
|
|
||||||
|
-- Clients exchange messages through a "mailbox", which has a long (randomly
|
||||||
|
-- unique) identifier and a queue of messages.
|
||||||
|
CREATE TABLE `mailboxes`
|
||||||
|
(
|
||||||
|
`app_id` VARCHAR,
|
||||||
|
`id` VARCHAR,
|
||||||
|
`side1` VARCHAR, -- side name, or NULL
|
||||||
|
`side2` VARCHAR, -- side name, or NULL
|
||||||
|
`crowded` BOOLEAN, -- at some point, three or more sides were involved
|
||||||
|
`first_mood` VARCHAR,
|
||||||
|
-- timing data for the mailbox itself
|
||||||
|
`started` INTEGER, -- time when opened
|
||||||
|
`second` INTEGER -- time when second side opened
|
||||||
|
);
|
||||||
|
CREATE INDEX `mailboxes_idx` ON `mailboxes` (`app_id`, `id`);
|
||||||
|
|
||||||
|
CREATE TABLE `messages`
|
||||||
|
(
|
||||||
|
`app_id` VARCHAR,
|
||||||
|
`mailbox_id` VARCHAR,
|
||||||
|
`side` VARCHAR,
|
||||||
|
`phase` VARCHAR, -- numeric or string
|
||||||
|
`body` VARCHAR,
|
||||||
|
`server_rx` INTEGER,
|
||||||
|
`msg_id` VARCHAR
|
||||||
|
);
|
||||||
|
CREATE INDEX `messages_idx` ON `messages` (`app_id`, `mailbox_id`);
|
||||||
|
|
||||||
|
CREATE TABLE `nameplate_usage`
|
||||||
|
(
|
||||||
|
`app_id` VARCHAR,
|
||||||
|
`started` INTEGER, -- seconds since epoch, rounded to "blur time"
|
||||||
|
`waiting_time` INTEGER, -- seconds from start to 2nd side appearing, or None
|
||||||
|
`total_time` INTEGER, -- seconds from open to last close/prune
|
||||||
|
`result` VARCHAR -- happy, lonely, pruney, crowded
|
||||||
|
-- nameplate moods:
|
||||||
|
-- "happy": two sides open and close
|
||||||
|
-- "lonely": one side opens and closes (no response from 2nd side)
|
||||||
|
-- "pruney": channels which get pruned for inactivity
|
||||||
|
-- "crowded": three or more sides were involved
|
||||||
|
);
|
||||||
|
CREATE INDEX `nameplate_usage_idx` ON `nameplate_usage` (`app_id`, `started`);
|
||||||
|
|
||||||
|
CREATE TABLE `mailbox_usage`
|
||||||
|
(
|
||||||
|
`app_id` VARCHAR,
|
||||||
|
`started` INTEGER, -- seconds since epoch, rounded to "blur time"
|
||||||
|
`total_time` INTEGER, -- seconds from open to last close
|
||||||
|
`waiting_time` INTEGER, -- seconds from start to 2nd side appearing, or None
|
||||||
|
`result` VARCHAR -- happy, scary, lonely, errory, pruney
|
||||||
|
-- rendezvous moods:
|
||||||
|
-- "happy": both sides close with mood=happy
|
||||||
|
-- "scary": any side closes with mood=scary (bad MAC, probably wrong pw)
|
||||||
|
-- "lonely": any side closes with mood=lonely (no response from 2nd side)
|
||||||
|
-- "errory": any side closes with mood=errory (other errors)
|
||||||
|
-- "pruney": channels which get pruned for inactivity
|
||||||
|
-- "crowded": three or more sides were involved
|
||||||
|
);
|
||||||
|
CREATE INDEX `mailbox_usage_idx` ON `mailbox_usage` (`app_id`, `started`);
|
||||||
|
|
||||||
|
CREATE TABLE `transit_usage`
|
||||||
|
(
|
||||||
|
`started` INTEGER, -- seconds since epoch, rounded to "blur time"
|
||||||
|
`total_time` INTEGER, -- seconds from open to last close
|
||||||
|
`waiting_time` INTEGER, -- seconds from start to 2nd side appearing, or None
|
||||||
|
`total_bytes` INTEGER, -- total bytes relayed (both directions)
|
||||||
|
`result` VARCHAR -- happy, scary, lonely, errory, pruney
|
||||||
|
-- transit moods:
|
||||||
|
-- "errory": one side gave the wrong handshake
|
||||||
|
-- "lonely": good handshake, but the other side never showed up
|
||||||
|
-- "happy": both sides gave correct handshake
|
||||||
|
);
|
||||||
|
CREATE INDEX `transit_usage_idx` ON `transit_usage` (`started`);
|
|
@ -191,9 +191,9 @@ class AppNamespace:
|
||||||
def get_nameplate_ids(self):
|
def get_nameplate_ids(self):
|
||||||
db = self._db
|
db = self._db
|
||||||
# TODO: filter this to numeric ids?
|
# TODO: filter this to numeric ids?
|
||||||
c = db.execute("SELECT DISTINCT `id` FROM `nameplates`"
|
c = db.execute("SELECT DISTINCT `name` FROM `nameplates`"
|
||||||
" WHERE `app_id`=?", (self._app_id,))
|
" WHERE `app_id`=?", (self._app_id,))
|
||||||
return set([row["id"] for row in c.fetchall()])
|
return set([row["name"] for row in c.fetchall()])
|
||||||
|
|
||||||
def _find_available_nameplate_id(self):
|
def _find_available_nameplate_id(self):
|
||||||
claimed = self.get_nameplate_ids()
|
claimed = self.get_nameplate_ids()
|
||||||
|
@ -230,7 +230,7 @@ class AppNamespace:
|
||||||
assert isinstance(side, type("")), type(side)
|
assert isinstance(side, type("")), type(side)
|
||||||
db = self._db
|
db = self._db
|
||||||
row = db.execute("SELECT * FROM `nameplates`"
|
row = db.execute("SELECT * FROM `nameplates`"
|
||||||
" WHERE `app_id`=? AND `id`=?",
|
" WHERE `app_id`=? AND `name`=?",
|
||||||
(self._app_id, nameplate_id)).fetchone()
|
(self._app_id, nameplate_id)).fetchone()
|
||||||
if row:
|
if row:
|
||||||
mailbox_id = row["mailbox_id"]
|
mailbox_id = row["mailbox_id"]
|
||||||
|
@ -238,14 +238,14 @@ class AppNamespace:
|
||||||
sr = add_side(row, side)
|
sr = add_side(row, side)
|
||||||
except CrowdedError:
|
except CrowdedError:
|
||||||
db.execute("UPDATE `nameplates` SET `crowded`=?"
|
db.execute("UPDATE `nameplates` SET `crowded`=?"
|
||||||
" WHERE `app_id`=? AND `id`=?",
|
" WHERE `app_id`=? AND `name`=?",
|
||||||
(True, self._app_id, nameplate_id))
|
(True, self._app_id, nameplate_id))
|
||||||
db.commit()
|
db.commit()
|
||||||
raise
|
raise
|
||||||
if sr.changed:
|
if sr.changed:
|
||||||
db.execute("UPDATE `nameplates` SET"
|
db.execute("UPDATE `nameplates` SET"
|
||||||
" `side1`=?, `side2`=?, `updated`=?, `second`=?"
|
" `side1`=?, `side2`=?, `updated`=?, `second`=?"
|
||||||
" WHERE `app_id`=? AND `id`=?",
|
" WHERE `app_id`=? AND `name`=?",
|
||||||
(sr.side1, sr.side2, when, when,
|
(sr.side1, sr.side2, when, when,
|
||||||
self._app_id, nameplate_id))
|
self._app_id, nameplate_id))
|
||||||
else:
|
else:
|
||||||
|
@ -257,7 +257,7 @@ class AppNamespace:
|
||||||
else:
|
else:
|
||||||
mailbox_id = generate_mailbox_id()
|
mailbox_id = generate_mailbox_id()
|
||||||
db.execute("INSERT INTO `nameplates`"
|
db.execute("INSERT INTO `nameplates`"
|
||||||
" (`app_id`, `id`, `mailbox_id`, `side1`, `crowded`,"
|
" (`app_id`, `name`, `mailbox_id`, `side1`, `crowded`,"
|
||||||
" `updated`, `started`)"
|
" `updated`, `started`)"
|
||||||
" VALUES(?,?,?,?,?, ?,?)",
|
" VALUES(?,?,?,?,?, ?,?)",
|
||||||
(self._app_id, nameplate_id, mailbox_id, side, False,
|
(self._app_id, nameplate_id, mailbox_id, side, False,
|
||||||
|
@ -275,21 +275,21 @@ class AppNamespace:
|
||||||
assert isinstance(side, type("")), type(side)
|
assert isinstance(side, type("")), type(side)
|
||||||
db = self._db
|
db = self._db
|
||||||
row = db.execute("SELECT * FROM `nameplates`"
|
row = db.execute("SELECT * FROM `nameplates`"
|
||||||
" WHERE `app_id`=? AND `id`=?",
|
" WHERE `app_id`=? AND `name`=?",
|
||||||
(self._app_id, nameplate_id)).fetchone()
|
(self._app_id, nameplate_id)).fetchone()
|
||||||
if not row:
|
if not row:
|
||||||
return
|
return
|
||||||
sr = remove_side(row, side)
|
sr = remove_side(row, side)
|
||||||
if sr.empty:
|
if sr.empty:
|
||||||
db.execute("DELETE FROM `nameplates`"
|
db.execute("DELETE FROM `nameplates`"
|
||||||
" WHERE `app_id`=? AND `id`=?",
|
" WHERE `app_id`=? AND `name`=?",
|
||||||
(self._app_id, nameplate_id))
|
(self._app_id, nameplate_id))
|
||||||
self._summarize_nameplate_and_store(row, when, pruned=False)
|
self._summarize_nameplate_and_store(row, when, pruned=False)
|
||||||
db.commit()
|
db.commit()
|
||||||
elif sr.changed:
|
elif sr.changed:
|
||||||
db.execute("UPDATE `nameplates`"
|
db.execute("UPDATE `nameplates`"
|
||||||
" SET `side1`=?, `side2`=?, `updated`=?"
|
" SET `side1`=?, `side2`=?, `updated`=?"
|
||||||
" WHERE `app_id`=? AND `id`=?",
|
" WHERE `app_id`=? AND `name`=?",
|
||||||
(sr.side1, sr.side2, when,
|
(sr.side1, sr.side2, when,
|
||||||
self._app_id, nameplate_id))
|
self._app_id, nameplate_id))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
@ -475,7 +475,7 @@ class AppNamespace:
|
||||||
for row in db.execute("SELECT * FROM `nameplates`"
|
for row in db.execute("SELECT * FROM `nameplates`"
|
||||||
" WHERE `app_id`=?",
|
" WHERE `app_id`=?",
|
||||||
(self._app_id,)).fetchall():
|
(self._app_id,)).fetchall():
|
||||||
nameplate_id = row["id"]
|
nameplate_id = row["name"]
|
||||||
all_nameplate_rows[nameplate_id] = row
|
all_nameplate_rows[nameplate_id] = row
|
||||||
if row["updated"] > old:
|
if row["updated"] > old:
|
||||||
which = NEW
|
which = NEW
|
||||||
|
@ -500,7 +500,7 @@ class AppNamespace:
|
||||||
row = all_nameplate_rows[nameplate_id]
|
row = all_nameplate_rows[nameplate_id]
|
||||||
self._summarize_nameplate_and_store(row, now, pruned=True)
|
self._summarize_nameplate_and_store(row, now, pruned=True)
|
||||||
db.execute("DELETE FROM `nameplates`"
|
db.execute("DELETE FROM `nameplates`"
|
||||||
" WHERE `app_id`=? AND `id`=?",
|
" WHERE `app_id`=? AND `name`=?",
|
||||||
(self._app_id, nameplate_id))
|
(self._app_id, nameplate_id))
|
||||||
modified = True
|
modified = True
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Server(ServerBase, unittest.TestCase):
|
||||||
|
|
||||||
def _nameplate(self, app, nameplate_id):
|
def _nameplate(self, app, nameplate_id):
|
||||||
return app._db.execute("SELECT * FROM `nameplates`"
|
return app._db.execute("SELECT * FROM `nameplates`"
|
||||||
" WHERE `app_id`='appid' AND `id`=?",
|
" WHERE `app_id`='appid' AND `name`=?",
|
||||||
(nameplate_id,)).fetchone()
|
(nameplate_id,)).fetchone()
|
||||||
|
|
||||||
def test_nameplate(self):
|
def test_nameplate(self):
|
||||||
|
@ -355,7 +355,7 @@ class Prune(unittest.TestCase):
|
||||||
|
|
||||||
rv.prune(now=123, old=50)
|
rv.prune(now=123, old=50)
|
||||||
|
|
||||||
nameplates = set([row["id"] for row in
|
nameplates = set([row["name"] for row in
|
||||||
db.execute("SELECT * FROM `nameplates`").fetchall()])
|
db.execute("SELECT * FROM `nameplates`").fetchall()])
|
||||||
self.assertEqual(new_nameplates, nameplates)
|
self.assertEqual(new_nameplates, nameplates)
|
||||||
mailboxes = set([row["id"] for row in
|
mailboxes = set([row["id"] for row in
|
||||||
|
@ -439,7 +439,7 @@ class Prune(unittest.TestCase):
|
||||||
|
|
||||||
rv.prune(now=123, old=50)
|
rv.prune(now=123, old=50)
|
||||||
|
|
||||||
nameplates = set([row["id"] for row in
|
nameplates = set([row["name"] for row in
|
||||||
db.execute("SELECT * FROM `nameplates`").fetchall()])
|
db.execute("SELECT * FROM `nameplates`").fetchall()])
|
||||||
self.assertEqual(nameplate_survives, bool(nameplates),
|
self.assertEqual(nameplate_survives, bool(nameplates),
|
||||||
("nameplate", nameplate_survives, nameplates, desc))
|
("nameplate", nameplate_survives, nameplates, desc))
|
||||||
|
@ -725,7 +725,7 @@ class WebSocketAPI(ServerBase, unittest.TestCase):
|
||||||
c1.send("claim", nameplate=nameplate_id) # allocate+claim is ok
|
c1.send("claim", nameplate=nameplate_id) # allocate+claim is ok
|
||||||
yield c1.sync()
|
yield c1.sync()
|
||||||
row = app._db.execute("SELECT * FROM `nameplates`"
|
row = app._db.execute("SELECT * FROM `nameplates`"
|
||||||
" WHERE `app_id`='appid' AND `id`=?",
|
" WHERE `app_id`='appid' AND `name`=?",
|
||||||
(nameplate_id,)).fetchone()
|
(nameplate_id,)).fetchone()
|
||||||
self.assertEqual(row["side1"], "side")
|
self.assertEqual(row["side1"], "side")
|
||||||
self.assertEqual(row["side2"], None)
|
self.assertEqual(row["side2"], None)
|
||||||
|
@ -797,7 +797,7 @@ class WebSocketAPI(ServerBase, unittest.TestCase):
|
||||||
self.assertEqual(m["type"], "released")
|
self.assertEqual(m["type"], "released")
|
||||||
|
|
||||||
row = app._db.execute("SELECT * FROM `nameplates`"
|
row = app._db.execute("SELECT * FROM `nameplates`"
|
||||||
" WHERE `app_id`='appid' AND `id`='np1'").fetchone()
|
" WHERE `app_id`='appid' AND `name`='np1'").fetchone()
|
||||||
self.assertEqual(row["side1"], "side2")
|
self.assertEqual(row["side1"], "side2")
|
||||||
self.assertEqual(row["side2"], None)
|
self.assertEqual(row["side2"], None)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user