I'm trying to build a wikipedia like thing, where multiple people can edit the content。People with privilege can also revert changes. I don't want reversions to be lossy (meaning really drop the edits people made. It should only hides it), so this seems to require a git branch like data structure store the edits with a pointer that points to the "current".
I tried this design:
CREATE TABLE article (
id serial PRIMARY KEY,
content text NOT NULL,
author integer NOT NULL REFERENCES "user",
path text NOT NULL,
relationship ltree NOT NULL
);
CREATE TABLE current_article (
article_id NOT NULL REFERENCES article
);
Where relationship
records if it's a new article or an edit of an existing article:
id | content | path | author | relationship
---+---------+------+--------+-------------
1 | foo | /a1 | 1 | 'root'
2 | bar | /a1 | 2 | 'root.1'
3 | baz | /a2 | 3 | 'root'
Here, it means, author 2 changed article /a1
from foo to bar, and article /a2
is a new one.
current_article
records which article is the "current" one, usually it just points to the newest one. After reversion, it can point to an older one:
article_id
----------
2
3
When an edit comes in, I insert it like this:
INSERT INTO article (content, path, author) VALUES ('qux', '/a2', 4);
And rely on a before insert trigger to find the current article for that path and fill in relationship, and an after insert trigger to update the current article pointer.
What do you think of this design? The problem I'm having with this design is the difficulty dealing with concurrency.
In the before insert trigger, by the time it finds the current article, it may already be changed, and in the after insert trigger, it might incorrectly overwrite current article with already points to a different one.
I have three questions in this regard:
- Will serializable Isolation solve the problem? (I'm pretty new to the concept of MVCC, still trying to wrap my head around it) If not, how should I solve it?
- Is there a better design that doesn't have to deal with concurrency?
- If I do need to deal with concurrency, how can I unit test my design in different race conditions (or are such unit tests even necessary)?
Thank you.