Chúng ta đã nói về ngoại tuyến trước tiên với Hasura và RxDB (về cơ bản là Postgres và PouchDB bên dưới).
Bài đăng này tiếp tục đi sâu hơn vào chủ đề. Đây là một cuộc thảo luận và hướng dẫn thực hiện giải quyết xung đột theo phong cách CouchDB với Postgres (cơ sở dữ liệu phụ trợ trung tâm) và PouchDB (ứng dụng mở trước người dùng cơ sở dữ liệu).
Đây là những gì chúng ta sẽ nói về:
- Giải quyết xung đột là gì?
- Ứng dụng của tôi có cần giải quyết xung đột không?
- Giải quyết xung đột với PouchDB đã giải thích
- Mang lại khả năng nhân rộng và quản lý xung đột dễ dàng cho pouchdb (giao diện người dùng) và Postgres (phụ trợ) với RxDB và Hasura
- Thiết lập Hasura
- Thiết lập phía khách hàng
- Thực hiện giải quyết xung đột
- Sử dụng các lượt xem
- Sử dụng trình kích hoạt postgres
- Các chiến lược Giải quyết Xung đột Tùy chỉnh với Hasura
- Giải quyết xung đột tùy chỉnh trên máy chủ
- Giải quyết xung đột tùy chỉnh trên máy khách
- Kết luận
Giải quyết xung đột là gì?
Hãy để chúng tôi lấy bảng Trello làm ví dụ. Giả sử bạn đã thay đổi người được giao trên thẻ Trello khi ngoại tuyến. Trong khi đó, đồng nghiệp của bạn chỉnh sửa mô tả của cùng một thẻ. Khi bạn trực tuyến trở lại, bạn sẽ muốn xem cả hai thay đổi. Bây giờ, giả sử cả hai bạn thay đổi mô tả cùng một lúc, điều gì sẽ xảy ra trong trường hợp này? Một tùy chọn là chỉ cần ghi lần cuối - đó là ghi đè thay đổi trước đó bằng thay đổi mới. Một cách khác là thông báo cho người dùng và để họ cập nhật thẻ bằng một trường đã hợp nhất (như git!).
Khía cạnh của việc thực hiện nhiều thay đổi đồng thời (có thể xung đột) và hợp nhất chúng thành một thay đổi được gọi là giải quyết xung đột.
Bạn có thể tạo loại ứng dụng nào khi bạn có khả năng nhân bản và giải quyết xung đột tốt?
Cơ sở hạ tầng nhân bản và giải quyết xung đột rất khó để xây dựng vào giao diện người dùng và phụ trợ của một ứng dụng. Nhưng một khi nó được thiết lập, một số trường hợp sử dụng quan trọng sẽ trở nên khả thi! Trên thực tế, đối với một số loại ứng dụng nhất định, việc nhân bản (và do đó giải quyết xung đột) là rất quan trọng đối với chức năng của ứng dụng!
- Thời gian thực:Các thay đổi do người dùng thực hiện trên các thiết bị khác nhau được đồng bộ hóa với nhau
- Cộng tác:Những người dùng khác nhau làm việc đồng thời trên cùng một dữ liệu
- Ưu tiên ngoại tuyến:Cùng một người dùng có thể làm việc với dữ liệu của họ ngay cả khi ứng dụng không được kết nối với cơ sở dữ liệu trung tâm
Ví dụ:Trello, Các ứng dụng email như Gmail, Superhuman, Google docs, Facebook, Twitter, v.v.
Hasura giúp bạn dễ dàng thêm các khả năng hiệu suất cao, bảo mật, thời gian thực vào ứng dụng dựa trên Postgres hiện có của bạn. Không cần phải triển khai thêm cơ sở hạ tầng phụ trợ để hỗ trợ các trường hợp sử dụng này! Trong một vài phần tiếp theo, chúng ta sẽ tìm hiểu cách bạn có thể sử dụng PouchDB / RxDB trên giao diện người dùng và ghép nối nó với Hasura để xây dựng các ứng dụng mạnh mẽ với trải nghiệm người dùng tuyệt vời.
Giải quyết xung đột với PouchDB được giải thích
Quản lý phiên bản với PouchDB
PouchDB - mà RxDB sử dụng bên dưới - đi kèm với cơ chế quản lý xung đột và lập phiên bản mạnh mẽ. Mọi tài liệu trong PouchDB đều có trường phiên bản được liên kết với nó. Các trường phiên bản có dạng <depth>-<object-hash>
ví dụ 2-c1592ce7b31cc26e91d2f2029c57e621
. Ở đây độ sâu cho biết độ sâu trong cây sửa đổi. Băm đối tượng là một chuỗi được tạo ngẫu nhiên.
Xem trước các bản sửa đổi của PouchDB
PouchDB để lộ các API để tìm nạp lịch sử sửa đổi của tài liệu. Chúng tôi có thể truy vấn lịch sử sửa đổi theo cách này:
todos.pouch.get(todo.id, {
revs: true
})
Thao tác này sẽ trả về một tài liệu có chứa _revisions
đồng ruộng:
{
"id": "559da26d-ad0f-42bc-a172-1821641bf2bb",
"_rev": "4-95162faab173d1e748952179e0db1a53",
"_revisions": {
"ids": [
"95162faab173d1e748952179e0db1a53",
"94162faab173d1e748952179e0db1a53",
"9055e63d99db056a95b61936f0185c8c",
"de71900ec14567088bed5914b2439896"
],
"start": 4
}
}
Đây ids
chứa hệ thống phân cấp các phiên bản của các phiên bản (bao gồm cả phiên bản hiện tại) và start
chứa "số tiền tố" cho bản sửa đổi hiện tại. Mỗi khi một bản sửa đổi mới được thêm vào start
được tăng dần và một hàm băm mới được thêm vào phần đầu của ids
mảng.
Khi tài liệu được đồng bộ hóa với máy chủ từ xa, _revisions
và _rev
các trường cần được đưa vào. Bằng cách này, tất cả các máy khách cuối cùng đều có lịch sử phiên bản hoàn chỉnh. Điều này xảy ra tự động khi PouchDB được thiết lập để đồng bộ với CouchDB. Yêu cầu kéo ở trên cũng cho phép điều này khi đồng bộ hóa qua GraphQL.
Lưu ý rằng tất cả các ứng dụng khách không nhất thiết phải có tất cả các bản sửa đổi, nhưng tất cả chúng cuối cùng sẽ có các phiên bản mới nhất và lịch sử của id sửa đổi cho các phiên bản này.
Giải quyết xung đột
Xung đột sẽ được phát hiện nếu hai bản sửa đổi có cùng nguồn gốc hoặc đơn giản hơn nếu hai bản sửa đổi bất kỳ có cùng độ sâu. Khi xung đột được phát hiện, CouchDB &PouchDB sẽ sử dụng cùng một thuật toán để tự động chọn người chiến thắng:
- Chọn các bản sửa đổi có trường độ sâu cao nhất không bị đánh dấu là đã xóa
- Nếu chỉ có 1 trường như vậy, hãy coi trường đó là trường chiến thắng
- Nếu có nhiều hơn 1, hãy sắp xếp các trường sửa đổi theo thứ tự giảm dần và chọn trường đầu tiên.
Lưu ý về việc xóa: PouchDB &CouchDB không bao giờ xóa các bản sửa đổi hoặc tài liệu thay vào đó một bản sửa đổi mới được tạo với cờ _deleted được đặt thành true. Vì vậy, trong bước 1 của thuật toán trên, bất kỳ chuỗi nào kết thúc bằng bản sửa đổi được đánh dấu là đã xóa đều bị bỏ qua.
Một tính năng thú vị của thuật toán này là không cần sự phối hợp giữa các máy khách hoặc máy khách và máy chủ để giải quyết xung đột. Không có điểm đánh dấu bổ sung nào được yêu cầu để đánh dấu một phiên bản là chiến thắng. Mỗi khách hàng và máy chủ chọn người chiến thắng một cách độc lập. Nhưng người chiến thắng sẽ là bản sửa đổi giống nhau vì họ sử dụng cùng một thuật toán xác định. Ngay cả khi một trong các ứng dụng khách bị thiếu một số bản sửa đổi, cuối cùng khi các bản sửa đổi đó được đồng bộ hóa, cùng một bản sửa đổi sẽ được chọn là người chiến thắng.
Triển khai các chiến lược giải quyết xung đột tùy chỉnh
Nhưng nếu chúng ta muốn một chiến lược giải quyết xung đột thay thế thì sao? Ví dụ "hợp nhất theo trường" - Nếu hai bản sửa đổi xung đột đã sửa đổi các khóa khác nhau của đối tượng, chúng tôi muốn tự động hợp nhất bằng cách tạo một bản sửa đổi với cả hai khóa. Cách được khuyến nghị để thực hiện việc này trong PouchDB là:
- Tạo bản sửa đổi mới này trên bất kỳ chuỗi nào
- Thêm bản sửa đổi với _deleted được đặt thành true cho từng chuỗi khác
Bản sửa đổi hợp nhất bây giờ sẽ tự động là bản sửa đổi chiến thắng theo thuật toán trên. Chúng tôi có thể thực hiện độ phân giải tùy chỉnh trên máy chủ hoặc máy khách. Khi các bản sửa đổi được đồng bộ hóa, tất cả các máy khách và máy chủ sẽ xem bản sửa đổi được hợp nhất là bản sửa đổi chiến thắng.
Giải quyết xung đột bằng Hasura và RxDB
Để triển khai chiến lược giải quyết xung đột ở trên, chúng tôi sẽ cần Hasura lưu trữ lịch sử sửa đổi và để RxDB đồng bộ hóa các phiên bản trong khi tái tạo bằng GraphQL.
Thiết lập Hasura
Tiếp tục với ví dụ về ứng dụng Todo từ bài trước. Chúng tôi sẽ phải cập nhật giản đồ cho bảng Todos như sau:
todo (
id: text primary key,
userId: text,
text: text, <br/>
createdAt: timestamp,
isCompleted: boolean,
deleted: boolean,
updatedAt: boolean,
_revisions: jsonb,
_rev: text primary key,
_parent_rev: text,
_depth: integer,
)
Lưu ý các trường bổ sung:
-
_rev
đại diện cho việc sửa đổi bản ghi. -
_parent_rev
đại diện cho bản sửa đổi chính của bản ghi -
_depth
là độ sâu của bản ghi trong cây sửa đổi -
_revisions
chứa toàn bộ lịch sử sửa đổi của hồ sơ.
Khóa chính của bảng là (ids
, _rev
).
Nói một cách chính xác, chúng tôi chỉ cần _revisions
vì thông tin khác có thể được lấy từ nó. Nhưng việc có sẵn các trường khác sẽ giúp phát hiện và giải quyết xung đột dễ dàng hơn.
Thiết lập phía máy khách
Chúng ta cần đặt syncRevisions
thành true trong khi thiết lập nhân rộng
async setupGraphQLReplication(auth) {
const replicationState = this.db.todos.syncGraphQL({
url: syncURL,
headers: {
'Authorization': `Bearer ${auth.idToken}`
},
push: {
batchSize,
queryBuilder: pushQueryBuilder
},
pull: {
queryBuilder: pullQueryBuilder(auth.userId)
},
live: true,
liveInterval: 1000 * 60 * 10,
deletedFlag: 'deleted',
syncRevisions: true,
});
...
}
Chúng tôi cũng cần thêm trường văn bản last_pulled_rev
sang lược đồ RxDB. Trường này được plugin sử dụng nội bộ để tránh đẩy các bản sửa đổi được tải về từ máy chủ trở lại máy chủ.
const todoSchema = {
...
'properties': {
...
'last_pulled_rev': {
'type': 'string'
}
},
...
};
Cuối cùng, chúng tôi cần thay đổi trình tạo truy vấn kéo &đẩy để đồng bộ hóa thông tin liên quan đến bản sửa đổi
Trình tạo truy vấn kéo
const pullQueryBuilder = (userId) => {
return (doc) => {
if (!doc) {
doc = {
id: '',
updatedAt: new Date(0).toUTCString()
};
}
const query = `{
todos(
where: {
_or: [
{updatedAt: {_gt: "${doc.updatedAt}"}},
{
updatedAt: {_eq: "${doc.updatedAt}"},
id: {_gt: "${doc.id}"}
}
],
userId: {_eq: "${userId}"}
},
limit: ${batchSize},
order_by: [{updatedAt: asc}, {id: asc}]
) {
id
text
isCompleted
deleted
createdAt
updatedAt
userId
_rev
_revisions
}
}`;
return {
query,
variables: {}
};
};
};
Bây giờ chúng ta tìm nạp các trường _rev &_revisions. Plugin được nâng cấp sẽ sử dụng các trường này để tạo các bản sửa đổi PouchDB cục bộ.
Trình tạo truy vấn đẩy
const pushQueryBuilder = doc => {
const query = `
mutation InsertTodo($todo: [todos_insert_input!]!) {
insert_todos(objects: $todo){
returning {
id
}
}
}
`;
const depth = doc._revisions.start;
const parent_rev = depth == 1 ? null : `${depth - 1}-${doc._revisions.ids[1]}`
const todo = Object.assign({}, doc, {
_depth: depth,
_parent_rev: parent_rev
})
delete todo['updatedAt']
const variables = {
todo: todo
};
return {
query,
variables
};
};
Với plugin được nâng cấp, tham số đầu vào doc
hiện chứa _rev
và _revisions
lĩnh vực. Chúng tôi chuyển cho Hasura trong truy vấn GraphQL. Chúng tôi thêm các trường _depth
, _parent_rev
sang doc
trước khi làm như vậy.
Trước đó, chúng tôi đã sử dụng một chương trình nâng cấp để chèn hoặc cập nhật todo
ghi lại trên Hasura. Bây giờ vì mỗi phiên bản kết thúc là một bản ghi mới, chúng tôi sử dụng đột biến chèn cũ đơn giản để thay thế.
Thực hiện giải quyết xung đột
Nếu bây giờ hai ứng dụng khách khác nhau thực hiện các thay đổi xung đột thì cả hai bản sửa đổi sẽ được đồng bộ hóa và hiện diện trong Hasura. Cả hai máy khách cuối cùng cũng sẽ nhận được bản sửa đổi khác. Bởi vì chiến lược giải quyết xung đột của PouchDB là xác định cả hai khách hàng sau đó sẽ chọn cùng một phiên bản làm "bản sửa đổi chiến thắng".
Làm thế nào chúng tôi có thể tìm thấy bản sửa đổi chiến thắng này trên máy chủ? Chúng tôi sẽ phải triển khai cùng một thuật toán trong SQL.
Triển khai thuật toán giải quyết xung đột của CouchDB trên Postgres
Bước 1:Tìm các nút lá không được đánh dấu là đã xóa
Để thực hiện việc này, chúng tôi cần bỏ qua bất kỳ phiên bản nào có bản sửa đổi con và bất kỳ phiên bản nào được đánh dấu là đã xóa:
SELECT
id,
_rev,
_depth
FROM
todos
WHERE
NOT EXISTS (
SELECT
id
FROM
todos AS t
WHERE
todos.id = t.id
AND t._parent_rev = todos._rev)
AND deleted = FALSE
Bước 2:Tìm chuỗi có độ sâu tối đa
Giả sử chúng ta có kết quả từ truy vấn trên trong một bảng (hoặc dạng xem hoặc một mệnh đề có) được gọi là các lá, chúng ta có thể tìm thấy chuỗi có độ sâu tối đa là thẳng về phía trước:
SELECT
id,
MAX(_depth) AS max_depth
FROM
leaves
GROUP BY
id
Bước 3:Tìm các bản sửa đổi chiến thắng trong số các bản sửa đổi có độ sâu tối đa bằng nhau
Một lần nữa, giả sử các kết quả từ truy vấn trên nằm trong một bảng (hoặc một chế độ xem hoặc một mệnh đề có) được gọi là max_depths, chúng ta có thể tìm thấy bản sửa đổi chiến thắng như sau:
SELECT
leaves.id,
MAX(leaves._rev) AS _rev
FROM
leaves
JOIN max_depths ON leaves.id = max_depths.id
AND leaves._depth = max_depths.max_depth
GROUP BY
leaves.id
Tạo chế độ xem với các bản sửa đổi thành công
Kết hợp ba truy vấn trên lại với nhau, chúng ta có thể tạo một chế độ xem hiển thị cho chúng ta các bản sửa đổi chiến thắng như sau:
CREATE OR REPLACE VIEW todos_current_revisions AS
WITH leaves AS (
SELECT
id,
_rev,
_depth
FROM
todos
WHERE
NOT EXISTS (
SELECT
id
FROM
todos AS t
WHERE
todos.id = t.id
AND t._parent_rev = todos._rev)
AND deleted = FALSE
),
max_depths AS (
SELECT
id,
MAX(_depth) AS max_depth
FROM
leaves
GROUP BY
id
),
winning_revisions AS (
SELECT
leaves.id,
MAX(leaves._rev) AS _rev
FROM
leaves
JOIN max_depths ON leaves.id = max_depths.id
AND leaves._depth = max_depths.max_depth
GROUP BY
(leaves.id))
SELECT
todos.*
FROM
todos
JOIN winning_revisions ON todos._rev = winning_revisions._rev;
Vì Hasura có thể theo dõi các lượt xem và cho phép truy vấn chúng qua GraphQL, các bản sửa đổi chiến thắng hiện có thể được hiển thị cho các khách hàng và dịch vụ khác.
Bất cứ khi nào bạn truy vấn chế độ xem, Postgres sẽ chỉ cần thay thế chế độ xem bằng truy vấn trong định nghĩa chế độ xem và chạy truy vấn kết quả. Nếu bạn truy vấn chế độ xem thường xuyên, điều này có thể dẫn đến nhiều chu kỳ CPU bị lãng phí. Chúng tôi có thể tối ưu hóa điều này bằng cách sử dụng trình kích hoạt Postgres và lưu trữ các bản sửa đổi chiến thắng trong một bảng khác.
Sử dụng trình kích hoạt Postgres để tính toán các bản sửa đổi chiến thắng
Bước 1:Tạo bảng mới todos_current_revisions
Lược đồ sẽ giống như của todos
bàn. Tuy nhiên, khóa chính sẽ là ids
thay vì (id, _rev)
Bước 2:Tạo trình kích hoạt Postgres
Chúng ta có thể viết truy vấn cho trình kích hoạt bằng cách bắt đầu với truy vấn chế độ xem. Vì hàm kích hoạt sẽ chạy cho một hàng tại một thời điểm, chúng tôi có thể đơn giản hóa truy vấn:
CREATE OR REPLACE FUNCTION calculate_winning_revision ()
RETURNS TRIGGER
AS $BODY$
BEGIN
INSERT INTO todos_current_revisions WITH leaves AS (
SELECT
id,
_rev,
_depth
FROM
todos
WHERE
NOT EXISTS (
SELECT
id
FROM
todos AS t
WHERE
t.id = NEW.id
AND t._parent_rev = todos._rev)
AND deleted = FALSE
AND id = NEW.id
),
max_depths AS (
SELECT
MAX(_depth) AS max_depth
FROM
leaves
),
winning_revisions AS (
SELECT
MAX(leaves._rev) AS _rev
FROM
leaves
JOIN max_depths ON leaves._depth = max_depths.max_depth
)
SELECT
todos.*
FROM
todos
JOIN winning_revisions ON todos._rev = winning_revisions._rev
ON CONFLICT ON CONSTRAINT todos_winning_revisions_pkey
DO UPDATE SET
_rev = EXCLUDED._rev,
_revisions = EXCLUDED._revisions,
_parent_rev = EXCLUDED._parent_rev,
_depth = EXCLUDED._depth,
text = EXCLUDED.text,
"updatedAt" = EXCLUDED."updatedAt",
deleted = EXCLUDED.deleted,
"userId" = EXCLUDED."userId",
"createdAt" = EXCLUDED."createdAt",
"isCompleted" = EXCLUDED."isCompleted";
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER trigger_insert_todos
AFTER INSERT ON todos
FOR EACH ROW
EXECUTE PROCEDURE calculate_winning_revision ()
Đó là nó! Giờ đây, chúng tôi có thể truy vấn các phiên bản chiến thắng cả trên máy chủ và máy khách.
Giải quyết xung đột tùy chỉnh
Bây giờ chúng ta hãy xem xét việc triển khai giải quyết xung đột tùy chỉnh với Hasura &RxDB.
Giải quyết xung đột tùy chỉnh ở phía máy chủ
Giả sử chúng tôi muốn hợp nhất các việc cần làm theo các trường. Làm thế nào để chúng ta làm điều này? Ý chính dưới đây cho chúng ta thấy điều này:
SQL đó trông có vẻ rất nhiều nhưng phần duy nhất liên quan đến chiến lược hợp nhất thực tế là:
CREATE OR REPLACE FUNCTION merge_revisions (item1 jsonb, item2 jsonb)
RETURNS jsonb
AS $$
BEGIN
IF NOT item1 ? 'id' THEN
RETURN item2;
ELSE
RETURN item1 || (item2 -> 'diff');
END IF;
END;
$$
LANGUAGE plpgsql;
CREATE OR REPLACE AGGREGATE agg_merge_revisions (jsonb) (
INITCOND = '{}',
STYPE = jsonb,
SFUNC = merge_revisions
);
Ở đây chúng tôi khai báo một hàm tổng hợp Postgres tùy chỉnh agg_merge_revisions
để hợp nhất các phần tử. Cách thức hoạt động của hàm này tương tự như hàm 'giảm':Postgres sẽ khởi tạo giá trị tổng hợp thành '{}'
, sau đó chạy merge_revisions
chức năng với phần tử tổng hợp hiện tại và phần tử tiếp theo được hợp nhất. Vì vậy, nếu chúng tôi có 3 phiên bản xung đột được hợp nhất, kết quả sẽ là:
merge_revisions(merge_revisions(merge_revisions('{}', v1), v2), v3)
Nếu chúng tôi muốn thực hiện một chiến lược khác, chúng tôi sẽ cần thay đổi merge_revisions
hàm số. Ví dụ:nếu chúng ta muốn thực hiện chiến lược 'ghi cuối cùng thắng':
CREATE OR REPLACE FUNCTION merge_revisions (item1 jsonb, item2 jsonb)
RETURNS jsonb
AS $$
BEGIN
IF NOT (item1 ? 'id') THEN
RETURN item2;
ELSE
IF (item2 -> 'updatedAt') > (item1 -> 'updatedAt') THEN
RETURN item2
ELSE
RETURN item1
END IF;
END IF;
END;
$$
LANGUAGE plpgsql;
Truy vấn chèn trong ý chính ở trên có thể được chạy trong trình kích hoạt chèn bài đăng để tự động hợp nhất các xung đột bất cứ khi nào chúng xảy ra.
Lưu ý: Ở trên chúng tôi đã sử dụng SQL để thực hiện giải quyết xung đột tùy chỉnh. Một cách tiếp cận thay thế là sử dụng một hành động viết:
- Tạo đột biến tùy chỉnh để xử lý chèn thay vì đột biến chèn mặc định được tạo tự động.
- Trong trình xử lý hành động, hãy tạo bản sửa đổi mới của bản ghi. Chúng ta có thể sử dụng đột biến chèn Hasura cho việc này.
- Tìm nạp tất cả các bản sửa đổi cho đối tượng bằng truy vấn danh sách
- Phát hiện bất kỳ xung đột nào bằng cách duyệt qua cây sửa đổi.
- Viết lại phiên bản đã hợp nhất.
Cách tiếp cận này sẽ hấp dẫn bạn nếu bạn muốn viết logic này bằng một ngôn ngữ khác ngoài SQL. Một cách tiếp cận khác là tạo dạng xem SQL để hiển thị các bản sửa đổi xung đột và triển khai logic còn lại trong trình xử lý hành động. Điều này sẽ đơn giản hóa bước 4. ở trên vì bây giờ chúng ta có thể chỉ cần truy vấn chế độ xem để phát hiện xung đột.
Giải quyết xung đột tùy chỉnh ở phía máy khách
Có những trường hợp bạn cần sự can thiệp của người dùng để có thể giải quyết xung đột. Ví dụ:nếu chúng tôi đang xây dựng một cái gì đó giống như ứng dụng Trello và hai người dùng đã sửa đổi mô tả của cùng một tác vụ, bạn có thể muốn hiển thị cho người dùng cả hai phiên bản và để họ tạo một phiên bản hợp nhất. Trong những tình huống này, chúng tôi sẽ cần giải quyết xung đột ở phía máy khách.
Giải quyết xung đột phía máy khách dễ thực hiện hơn vì PouchDB đã để lộ API để truy vấn các bản sửa đổi xung đột. Nếu chúng ta nhìn vào todos
Bộ sưu tập RxDB từ bài trước, đây là cách chúng tôi có thể tìm nạp các phiên bản xung đột:
todos.pouch.get(todo.id, {
conflicts: true
})
Truy vấn trên sẽ điền các bản sửa đổi xung đột trong _conflicts
trường trong kết quả. Sau đó, chúng tôi có thể trình bày những điều này cho người dùng để giải quyết.
Kết luận
PouchDB đi kèm với một cấu trúc linh hoạt và mạnh mẽ cho giải pháp quản lý xung đột và lập phiên bản. Bài đăng này đã chỉ cho chúng tôi cách sử dụng các cấu trúc này với Hasura / Postgres. Trong bài đăng này, chúng tôi đã tập trung vào việc sử dụng plpgsql. Chúng tôi sẽ thực hiện một bài đăng tiếp theo hướng dẫn cách thực hiện việc này với Actions để bạn có thể sử dụng ngôn ngữ bạn chọn trên chương trình phụ trợ!
Rất thích bài viết này? Tham gia với chúng tôi trên Discord để thảo luận thêm về Hasura &GraphQL!
Đăng ký nhận bản tin của chúng tôi để biết khi nào chúng tôi xuất bản các bài viết mới.