{"payload":{"feedbackUrl":"https://github.com/orgs/community/discussions/53140","repo":{"id":347983856,"defaultBranch":"main","name":"khepri","ownerLogin":"rabbitmq","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2021-03-15T13:38:36.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/96669?v=4","public":true,"private":false,"isOrgOwned":true},"refInfo":{"name":"","listCacheKey":"v0:1715848234.0","currentOid":""},"activityList":{"items":[{"before":"601499e3d1ff83cf5c60832110c4328b056060db","after":"46218055e3c6f0b6954a3d4efe5bc38abc806993","ref":"refs/heads/main","pushedAt":"2024-05-16T08:26:19.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Bump Khepri to version 0.14.0","shortMessageHtmlLink":"Bump Khepri to version 0.14.0"}},{"before":"e50b5fe1bd3cba199690a997352450f8d8765175","after":"601499e3d1ff83cf5c60832110c4328b056060db","ref":"refs/heads/main","pushedAt":"2024-05-16T08:15:59.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"GitHub Actions: Bump actions components\n\n[Why]\nWe need to fix the \"Node.js 16 actions are deprecated\" warnings.","shortMessageHtmlLink":"GitHub Actions: Bump actions components"}},{"before":"58c9557927ba60dbebbd50c8b86584076c2ce7e6","after":"d909bf089d2f925c43835668ca0ab273b12b6e7d","ref":"refs/heads/gh-pages","pushedAt":"2024-05-16T08:07:13.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"github-actions[bot]","name":null,"path":"/apps/github-actions","primaryAvatarUrl":"https://avatars.githubusercontent.com/in/15368?s=80&v=4"},"commit":{"message":"deploy: e50b5fe1bd3cba199690a997352450f8d8765175","shortMessageHtmlLink":"deploy: e50b5fe"}},{"before":"5f6f3e6846ab88bd236ea74f1a30603de0bd1031","after":"e50b5fe1bd3cba199690a997352450f8d8765175","ref":"refs/heads/main","pushedAt":"2024-05-16T08:06:46.000Z","pushType":"push","commitsCount":2,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"GitHub Actions: Bump actions components\n\n[Why]\nWe need to fix the \"Node.js 16 actions are deprecated\" warnings.","shortMessageHtmlLink":"GitHub Actions: Bump actions components"}},{"before":"305f4c71e6c94224a1c9f634fedaa279a44c22aa","after":"58c9557927ba60dbebbd50c8b86584076c2ce7e6","ref":"refs/heads/gh-pages","pushedAt":"2024-05-15T20:23:05.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"github-actions[bot]","name":null,"path":"/apps/github-actions","primaryAvatarUrl":"https://avatars.githubusercontent.com/in/15368?s=80&v=4"},"commit":{"message":"deploy: 5f6f3e6846ab88bd236ea74f1a30603de0bd1031","shortMessageHtmlLink":"deploy: 5f6f3e6"}},{"before":"c6465c2fad6d584f00424681b8a259a1f74238c5","after":null,"ref":"refs/heads/test-duplicated-commands","pushedAt":"2024-05-15T20:22:41.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"}},{"before":"a478a9e5edb87a3d7a61dfad84145e55d2d74d4f","after":"5f6f3e6846ab88bd236ea74f1a30603de0bd1031","ref":"refs/heads/main","pushedAt":"2024-05-15T20:22:40.000Z","pushType":"pr_merge","commitsCount":3,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Merge pull request #250 from rabbitmq/test-duplicated-commands\n\nkhepri_machine: Add command deduplication mechanism","shortMessageHtmlLink":"Merge pull request #250 from rabbitmq/test-duplicated-commands"}},{"before":"04b27676140559d4a9731ea211c5f12ae32e4188","after":"c6465c2fad6d584f00424681b8a259a1f74238c5","ref":"refs/heads/test-duplicated-commands","pushedAt":"2024-05-15T19:58:34.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_machine: Add command deduplication mechanism\n\n[Why]\nThe \"client\" side of `khepri_machine` implemented in\n`process_sync_command/3` have a retry mechanism if\n`ra:process_command/3` returns an error such as `noproc`, `nodedown` or\n`shutdown`.\n\nHowever, this retry mechanism can't tell if the state machine already\nreceived the command and just couldn't reply, for instance because there\nis a node stopping or a change of leadership.\n\nTherefore, it's possible that the same command is submitted twice and\nthus processed twice.\n\nThat's ok for idempotent commands, but it may not be alright for all\ntransactions for example. That's why we need a deduplication mechanism\nthat ensures the same command is not applied multiple times.\n\n[How]\nTwo new commands are introduced to implement the deduplication system:\n* #dedup{} which is used to wrap the command to protect and assign a\n unique reference to it\n* #dedup_ack{} which is used at the end of the retry loop to let the\n state machine know that the \"client\" side received the reply\n\nWhen the state machine receives a command wrapped into a #dedup{}\ncommand, it will remember the reply for the initial processing of that\ncommand. For any subsequent copies of the same #dedup{} (based on the\nunique reference), the state machine will not apply the wrapped command\nand will simply returned the reply it remembered from the first\napplication.\n\nLater when the state machine receives a #dedup_ack{}, it will drop the\ncached reply for that reference.\n\nJust in case the client never sends a #dedup_ack{}, the state machine\nwill drop any expired cached entries. The expiration time is based on\nthe command timeout. If it's infinity, it defaults to 15 minutes.\n\nThis whole deduplication mechanism can be enabled or disabled through\nthe new `protect_against_dups` command option which takes a boolean.\nThis option is off by default, except for R/W transactions.\n\nThus if the caller knows the transation is idempotent, it can decide to\nturn the dedup mechanism off.\n\nBecause the state machine's state grows with a new field and handles two\nnew commandes, we bump the machine version from 0 to 1.\n\nV2: We now use the `effective_machine_version` counter provided by\n `ra_counters:counters/2` if it is available as it is faster than\n querying the Ra server. If the counter is unavailable, we fall back\n to the query. The new counter is added by rabbitmq/ra#426 and will\n be used once a Ra release contains this change.","shortMessageHtmlLink":"khepri_machine: Add command deduplication mechanism"}},{"before":"661ea99482681b7e8e2b0312123fd1c6b0731766","after":"305f4c71e6c94224a1c9f634fedaa279a44c22aa","ref":"refs/heads/gh-pages","pushedAt":"2024-05-15T19:58:01.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"github-actions[bot]","name":null,"path":"/apps/github-actions","primaryAvatarUrl":"https://avatars.githubusercontent.com/in/15368?s=80&v=4"},"commit":{"message":"deploy: a478a9e5edb87a3d7a61dfad84145e55d2d74d4f","shortMessageHtmlLink":"deploy: a478a9e"}},{"before":"a5e90e3ce656030a9e7b7ec883a3ebd2418b2395","after":null,"ref":"refs/heads/bump-ra","pushedAt":"2024-05-15T19:57:33.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"}},{"before":"8dde132fe7f2263e223959fcc68d9dc153264a3a","after":"a478a9e5edb87a3d7a61dfad84145e55d2d74d4f","ref":"refs/heads/main","pushedAt":"2024-05-15T19:57:33.000Z","pushType":"pr_merge","commitsCount":2,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Merge pull request #258 from rabbitmq/bump-ra\n\nUpdate Ra from 2.9.1 to 2.10.1","shortMessageHtmlLink":"Merge pull request #258 from rabbitmq/bump-ra"}},{"before":null,"after":"a5e90e3ce656030a9e7b7ec883a3ebd2418b2395","ref":"refs/heads/bump-ra","pushedAt":"2024-05-15T15:41:02.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Update Ra from 2.9.1 to 2.10.1\n\nRelease notes:\n* Ra 2.10.0: https://github.com/rabbitmq/ra/releases/tag/v2.10.0\n* Ra 2.10.1: (unavailable)","shortMessageHtmlLink":"Update Ra from 2.9.1 to 2.10.1"}},{"before":"e76d5724d7a01aab60e09c0a5bb7772ad899ce27","after":"04b27676140559d4a9731ea211c5f12ae32e4188","ref":"refs/heads/test-duplicated-commands","pushedAt":"2024-05-15T15:37:59.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_machine: Add command deduplication mechanism\n\n[Why]\nThe \"client\" side of `khepri_machine` implemented in\n`process_sync_command/3` have a retry mechanism if\n`ra:process_command/3` returns an error such as `noproc`, `nodedown` or\n`shutdown`.\n\nHowever, this retry mechanism can't tell if the state machine already\nreceived the command and just couldn't reply, for instance because there\nis a node stopping or a change of leadership.\n\nTherefore, it's possible that the same command is submitted twice and\nthus processed twice.\n\nThat's ok for idempotent commands, but it may not be alright for all\ntransactions for example. That's why we need a deduplication mechanism\nthat ensures the same command is not applied multiple times.\n\n[How]\nTwo new commands are introduced to implement the deduplication system:\n* #dedup{} which is used to wrap the command to protect and assign a\n unique reference to it\n* #dedup_ack{} which is used at the end of the retry loop to let the\n state machine know that the \"client\" side received the reply\n\nWhen the state machine receives a command wrapped into a #dedup{}\ncommand, it will remember the reply for the initial processing of that\ncommand. For any subsequent copies of the same #dedup{} (based on the\nunique reference), the state machine will not apply the wrapped command\nand will simply returned the reply it remembered from the first\napplication.\n\nLater when the state machine receives a #dedup_ack{}, it will drop the\ncached reply for that reference.\n\nJust in case the client never sends a #dedup_ack{}, the state machine\nwill drop any expired cached entries. The expiration time is based on\nthe command timeout. If it's infinity, it defaults to 15 minutes.\n\nThis whole deduplication mechanism can be enabled or disabled through\nthe new `protect_against_dups` command option which takes a boolean.\nThis option is off by default, except for R/W transactions.\n\nThus if the caller knows the transation is idempotent, it can decide to\nturn the dedup mechanism off.\n\nBecause the state machine's state grows with a new field and handles two\nnew commandes, we bump the machine version from 0 to 1.\n\nV2: We now use the `effective_machine_version` counter provided by\n `ra_counters:counters/2` if it is available as it is faster than\n querying the Ra server. If the counter is unavailable, we fall back\n to the query. The new counter is added by rabbitmq/ra#426 and will\n be used once a Ra release contains this change.","shortMessageHtmlLink":"khepri_machine: Add command deduplication mechanism"}},{"before":"b963ca88e7ad25983326f433a4855a92df6c03a8","after":"8dde132fe7f2263e223959fcc68d9dc153264a3a","ref":"refs/heads/main","pushedAt":"2024-05-15T15:37:26.000Z","pushType":"pr_merge","commitsCount":2,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Merge pull request #257 from rabbitmq/fix-pattern-tree-conditions-matching-subtrees\n\nkhepri_pattern_tree: Fix conditions that were matching subtrees","shortMessageHtmlLink":"Merge pull request #257 from rabbitmq/fix-pattern-tree-conditions-mat…"}},{"before":"f523f287fdbaec5071d67864420bb7ba9dc2f210","after":null,"ref":"refs/heads/fix-pattern-tree-conditions-matching-subtrees","pushedAt":"2024-05-15T15:37:26.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"}},{"before":"93f4e414983484724669f224148c2061acaec787","after":"f523f287fdbaec5071d67864420bb7ba9dc2f210","ref":"refs/heads/fix-pattern-tree-conditions-matching-subtrees","pushedAt":"2024-05-15T15:17:46.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_pattern_tree: Fix conditions that were matching subtrees\n\n[Why]\nA pattern tree with `/parent/*` is supposed to match\n`/parent/child` but not `/parent/child/grandchild`.\n\nBefore this patch, this was the case because we didn't check if we\nreached the of the path before calling the folding function in\n`khepri_pattern_tree:fold1/6`.\n\n[How]\nNow, we check the context and only call the fold function if we reached\nthe end of the path.\n\nOtherwise, we recurse without calling that fold function, checking a few\nmore things depending on whether the condition could match grand\nchildren or not.\n\nThe testsuites are expanded with more testcases to cover these\nsituations.","shortMessageHtmlLink":"khepri_pattern_tree: Fix conditions that were matching subtrees"}},{"before":null,"after":"93f4e414983484724669f224148c2061acaec787","ref":"refs/heads/fix-pattern-tree-conditions-matching-subtrees","pushedAt":"2024-05-15T14:36:55.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_pattern_tree: Fix conditions that were matching subtrees\n\n[Why]\nA pattern tree with `/parent/*` is supposed to match\n`/parent/child` but not `/parent/child/grandchild`.\n\nBefore this patch, this was the case because we didn't check if we\nreached the of the path before calling the folding function in\n`khepri_pattern_tree:fold1/6`.\n\n[How]\nNow, we check the context and only call the fold function if we reached\nthe end of the path.\n\nOtherwise, we recurse without calling that fold function, checking a few\nmore things depending on whether the condition could match grand\nchildren or not.\n\nThe testsuites are expanded with more testcases to cover these\nsituations.","shortMessageHtmlLink":"khepri_pattern_tree: Fix conditions that were matching subtrees"}},{"before":"cf1cf7c521c3e9cf8ae85031df7e4b9d5c357cde","after":"661ea99482681b7e8e2b0312123fd1c6b0731766","ref":"refs/heads/gh-pages","pushedAt":"2024-05-15T14:31:48.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"github-actions[bot]","name":null,"path":"/apps/github-actions","primaryAvatarUrl":"https://avatars.githubusercontent.com/in/15368?s=80&v=4"},"commit":{"message":"deploy: b963ca88e7ad25983326f433a4855a92df6c03a8","shortMessageHtmlLink":"deploy: b963ca8"}},{"before":"e65e3b38d772b76ef3974feec5697fb9f995f0d7","after":"b963ca88e7ad25983326f433a4855a92df6c03a8","ref":"refs/heads/main","pushedAt":"2024-05-15T14:31:11.000Z","pushType":"push","commitsCount":2,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri: Fix doc of `khepri:delete/3`\n\n[Why]\nIt was copy-pasted from `khepri:update/4` and was not adapted\nafterwards...","shortMessageHtmlLink":"khepri: Fix doc of khepri:delete/3"}},{"before":"2b986e834f06cd542a8f70239451ce641b20d3e6","after":null,"ref":"refs/heads/md/error-timeout-return","pushedAt":"2024-04-11T13:26:49.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"}},{"before":"076926a618443af5d406c0047006654de5346c55","after":"e65e3b38d772b76ef3974feec5697fb9f995f0d7","ref":"refs/heads/main","pushedAt":"2024-04-11T13:26:48.000Z","pushType":"pr_merge","commitsCount":2,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Merge pull request #256 from rabbitmq/md/error-timeout-return\n\nSimplify `{error,timeout}` error type","shortMessageHtmlLink":"Merge pull request #256 from rabbitmq/md/error-timeout-return"}},{"before":null,"after":"2b986e834f06cd542a8f70239451ce641b20d3e6","ref":"refs/heads/md/error-timeout-return","pushedAt":"2024-04-03T15:45:15.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"the-mikedavis","name":"Michael Davis","path":"/the-mikedavis","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/21230295?s=80&v=4"},"commit":{"message":"Simplify '{error,timeout}' error type\n\nPreviously this return value was '{error,{timeout,RaLeaderId}}'. Leader\ninformation is generally not useful to Khepri API consumers though since\nKhepri covers leader redirection. So this change removes the leader ID\nfrom the error type and returns '{error,timeout}' instead.","shortMessageHtmlLink":"Simplify '{error,timeout}' error type"}},{"before":"5d1bb392b64a1ea04e6213201624d2df443151ed","after":"e76d5724d7a01aab60e09c0a5bb7772ad899ce27","ref":"refs/heads/test-duplicated-commands","pushedAt":"2024-03-28T14:37:04.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_machine: Add command deduplication mechanism\n\n[Why]\nThe \"client\" side of `khepri_machine` implemented in\n`process_sync_command/3` have a retry mechanism if\n`ra:process_command/3` returns an error such as `noproc`, `nodedown` or\n`shutdown`.\n\nHowever, this retry mechanism can't tell if the state machine already\nreceived the command and just couldn't reply, for instance because there\nis a node stopping or a change of leadership.\n\nTherefore, it's possible that the same command is submitted twice and\nthus processed twice.\n\nThat's ok for idempotent commands, but it may not be alright for all\ntransactions for example. That's why we need a deduplication mechanism\nthat ensures the same command is not applied multiple times.\n\n[How]\nTwo new commands are introduced to implement the deduplication system:\n* #dedup{} which is used to wrap the command to protect and assign a\n unique reference to it\n* #dedup_ack{} which is used at the end of the retry loop to let the\n state machine know that the \"client\" side received the reply\n\nWhen the state machine receives a command wrapped into a #dedup{}\ncommand, it will remember the reply for the initial processing of that\ncommand. For any subsequent copies of the same #dedup{} (based on the\nunique reference), the state machine will not apply the wrapped command\nand will simply returned the reply it remembered from the first\napplication.\n\nLater when the state machine receives a #dedup_ack{}, it will drop the\ncached reply for that reference.\n\nJust in case the client never sends a #dedup_ack{}, the state machine\nwill drop any expired cached entries. The expiration time is based on\nthe command timeout. If it's infinity, it defaults to 15 minutes.\n\nThis whole deduplication mechanism can be enabled or disabled through\nthe new `protect_against_dups` command option which takes a boolean.\nThis option is off by default, except for R/W transactions.\n\nThus if the caller knows the transation is idempotent, it can decide to\nturn the dedup mechanism off.\n\nBecause the state machine's state grows with a new field and handles two\nnew commandes, we bump the machine version from 0 to 1.\n\nV2: We now use the `effective_machine_version` counter provided by\n `ra_counters:counters/2` if it is available as it is faster than\n querying the Ra server. If the counter is unavailable, we fall back\n to the query. The new counter is added by rabbitmq/ra#426 and will\n be used once a Ra release contains this change.","shortMessageHtmlLink":"khepri_machine: Add command deduplication mechanism"}},{"before":"0296adbd583db73d5236715968bd4b7575c9eb71","after":"5d1bb392b64a1ea04e6213201624d2df443151ed","ref":"refs/heads/test-duplicated-commands","pushedAt":"2024-03-28T14:35:00.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_machine: Add command deduplication mechanism\n\n[Why]\nThe \"client\" side of `khepri_machine` implemented in\n`process_sync_command/3` have a retry mechanism if\n`ra:process_command/3` returns an error such as `noproc`, `nodedown` or\n`shutdown`.\n\nHowever, this retry mechanism can't tell if the state machine already\nreceived the command and just couldn't reply, for instance because there\nis a node stopping or a change of leadership.\n\nTherefore, it's possible that the same command is submitted twice and\nthus processed twice.\n\nThat's ok for idempotent commands, but it may not be alright for all\ntransactions for example. That's why we need a deduplication mechanism\nthat ensures the same command is not applied multiple times.\n\n[How]\nTwo new commands are introduced to implement the deduplication system:\n* #dedup{} which is used to wrap the command to protect and assign a\n unique reference to it\n* #dedup_ack{} which is used at the end of the retry loop to let the\n state machine know that the \"client\" side received the reply\n\nWhen the state machine receives a command wrapped into a #dedup{}\ncommand, it will remember the reply for the initial processing of that\ncommand. For any subsequent copies of the same #dedup{} (based on the\nunique reference), the state machine will not apply the wrapped command\nand will simply returned the reply it remembered from the first\napplication.\n\nLater when the state machine receives a #dedup_ack{}, it will drop the\ncached reply for that reference.\n\nJust in case the client never sends a #dedup_ack{}, the state machine\nwill drop any expired cached entries. The expiration time is based on\nthe command timeout. If it's infinity, it defaults to 15 minutes.\n\nThis whole deduplication mechanism can be enabled or disabled through\nthe new `protect_against_dups` command option which takes a boolean.\nThis option is off by default, except for R/W transactions.\n\nThus if the caller knows the transation is idempotent, it can decide to\nturn the dedup mechanism off.\n\nBecause the state machine's state grows with a new field and handles two\nnew commandes, we bump the machine version from 0 to 1.\n\nV2: We now use the `effective_machine_version` counter provided by\n `ra_counters:counters/2` if it is available as it is faster than\n querying the Ra server. If the counter is unavailable, we fall back\n to the query. The new counter is added by rabbitmq/ra#426 and will\n be used once a Ra release contains this change.","shortMessageHtmlLink":"khepri_machine: Add command deduplication mechanism"}},{"before":"013e7a0bce38ca8bbf27d796d180c2a2e576e238","after":"cf1cf7c521c3e9cf8ae85031df7e4b9d5c357cde","ref":"refs/heads/gh-pages","pushedAt":"2024-03-28T13:51:25.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"github-actions[bot]","name":null,"path":"/apps/github-actions","primaryAvatarUrl":"https://avatars.githubusercontent.com/in/15368?s=80&v=4"},"commit":{"message":"deploy: 076926a618443af5d406c0047006654de5346c55","shortMessageHtmlLink":"deploy: 076926a"}},{"before":"2ee52e698ae7f48ede883b5253b0b01cfcb0f741","after":"076926a618443af5d406c0047006654de5346c55","ref":"refs/heads/main","pushedAt":"2024-03-28T13:50:52.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_machine: Remove `@private` tag for `make_virgin_state/1`\n\n[Why]\nApparently EDoc doesn't like this directive for code behind a\n`-ifdef(TEST).` macro. It fails with the following error:\n\n .../src/khepri_machine.erl, in module footer: at line 1994: tag @private not allowed here.\n edoc: skipping source file '.../src/khepri_machine.erl': {'EXIT',error}.\n\n[How]\nJust delete the tag for now. The function is not exported anyway when\nthe doc is built.","shortMessageHtmlLink":"khepri_machine: Remove @private tag for make_virgin_state/1"}},{"before":"e3b7b7bc7df0545d829b371fbefc052114fc0e2e","after":"2ee52e698ae7f48ede883b5253b0b01cfcb0f741","ref":"refs/heads/main","pushedAt":"2024-03-28T13:44:58.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Bump Khepri to version 0.13.0","shortMessageHtmlLink":"Bump Khepri to version 0.13.0"}},{"before":"ac9dbbc93d821067d9af62c7045a55f193eb03f9","after":"0296adbd583db73d5236715968bd4b7575c9eb71","ref":"refs/heads/test-duplicated-commands","pushedAt":"2024-03-28T09:46:13.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"khepri_machine: Add command deduplication mechanism\n\n[Why]\nThe \"client\" side of `khepri_machine` implemented in\n`process_sync_command/3` have a retry mechanism if\n`ra:process_command/3` returns an error such as `noproc`, `nodedown` or\n`shutdown`.\n\nHowever, this retry mechanism can't tell if the state machine already\nreceived the command and just couldn't reply, for instance because there\nis a node stopping or a change of leadership.\n\nTherefore, it's possible that the same command is submitted twice and\nthus processed twice.\n\nThat's ok for idempotent commands, but it may not be alright for all\ntransactions for example. That's why we need a deduplication mechanism\nthat ensures the same command is not applied multiple times.\n\n[How]\nTwo new commands are introduced to implement the deduplication system:\n* #dedup{} which is used to wrap the command to protect and assign a\n unique reference to it\n* #dedup_ack{} which is used at the end of the retry loop to let the\n state machine know that the \"client\" side received the reply\n\nWhen the state machine receives a command wrapped into a #dedup{}\ncommand, it will remember the reply for the initial processing of that\ncommand. For any subsequent copies of the same #dedup{} (based on the\nunique reference), the state machine will not apply the wrapped command\nand will simply returned the reply it remembered from the first\napplication.\n\nLater when the state machine receives a #dedup_ack{}, it will drop the\ncached reply for that reference.\n\nJust in case the client never sends a #dedup_ack{}, the state machine\nwill drop any expired cached entries. The expiration time is based on\nthe command timeout. If it's infinity, it defaults to 15 minutes.\n\nThis whole deduplication mechanism can be enabled or disabled through\nthe new `protect_against_dups` command option which takes a boolean.\nThis option is off by default, except for R/W transactions.\n\nThus if the caller knows the transation is idempotent, it can decide to\nturn the dedup mechanism off.\n\nBecause the state machine's state grows with a new field and handles two\nnew commandes, we bump the machine version from 0 to 1.","shortMessageHtmlLink":"khepri_machine: Add command deduplication mechanism"}},{"before":"06712a1943de840c6ad651ee76ad175f214f08fb","after":null,"ref":"refs/heads/md-has-projection/2-and-effect-free-register","pushedAt":"2024-03-27T14:19:40.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"}},{"before":"2151d8a80369b50f770565977de3d62661e487ad","after":"e3b7b7bc7df0545d829b371fbefc052114fc0e2e","ref":"refs/heads/main","pushedAt":"2024-03-27T14:19:39.000Z","pushType":"pr_merge","commitsCount":4,"pusher":{"login":"dumbbell","name":"Jean-Sébastien Pédron","path":"/dumbbell","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/159804?s=80&v=4"},"commit":{"message":"Merge pull request #255 from rabbitmq/md-has-projection/2-and-effect-free-register\n\nUse effects to initialize new projections","shortMessageHtmlLink":"Merge pull request #255 from rabbitmq/md-has-projection/2-and-effect-…"}}],"hasNextPage":true,"hasPreviousPage":false,"activityType":"all","actor":null,"timePeriod":"all","sort":"DESC","perPage":30,"cursor":"djE6ks8AAAAES14gMgA","startCursor":null,"endCursor":null}},"title":"Activity · rabbitmq/khepri"}