Use j.fact twice to create a new predecessor, and a new successor. For example:
var predecessor = predecessor: {
value: 'Never seen before',
root: {
value: 'This one already existed'
}
};
j.fact(predecessor);
j.fact({
predecessor: predecessor,
value: 'Brand new, too'
}
Outcome
Because the first j.fact is not awaited, this creates a race condition between saving the predecessor and the successor. Both save methods go to the server simultaneously, and are handled in parallel. When the server succeeds in saving the predecessor, the successor does not always see that the predecessor exists. Sometimes, it tries to save the predecessor again itself.
The database provider throws duplicate key value violates unique constraint "ux_edge" because the edge between the predecessor and the root was created when the predecessor was saved. The successor save does not accept this exception as a success.
This aborts the save of the fact, and so the successor fact is never saved.
Expected behavior
The exception from the database should be ignored. The record that we are trying to insert already exists.
Reproduction steps:
Use
j.fact
twice to create a new predecessor, and a new successor. For example:Outcome
Because the first
j.fact
is not awaited, this creates a race condition between saving the predecessor and the successor. Both save methods go to the server simultaneously, and are handled in parallel. When the server succeeds in saving the predecessor, the successor does not always see that the predecessor exists. Sometimes, it tries to save the predecessor again itself.The database provider throws duplicate key value violates unique constraint "ux_edge" because the edge between the predecessor and the root was created when the predecessor was saved. The successor save does not accept this exception as a success.
This aborts the save of the fact, and so the successor fact is never saved.
Expected behavior
The exception from the database should be ignored. The record that we are trying to insert already exists.