git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 5/6] refs: implement partial reference transaction support

From
Karthik Nayak <karthik.188@gmail.com>
Date
Feb 21, 2025, 10:33 UTC
Message-ID
<CAOLa=ZQG7UOiYf94jXJwm5SC69hwXCpv2HRCXxMCOUONnzKaUA@mail.gmail.com>
In-Reply-To
<Z6YxA4BlhNwbeYk-@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
Show 27 quoted lines
> On Fri, Feb 07, 2025 at 08:34:40AM +0100, Karthik Nayak wrote:
>> Git's reference transactions are all-or-nothing: either all updates
>> succeed, or none do. While this atomic behavior is generally desirable,
>> it can be suboptimal when using the reftable backend, where batching
>> multiple reference updates into a single transaction is more efficient
>> than performing them sequentially.
>
> In fact it's even inefficient for the "files" backend. The whole
> machinery around creating a new transaction, preparing it, committing it
> and then cleaning up its state does bring a bunch of overhead with it.
> But true, for the "reftable" backend it's way more impactful.
>
>> diff --git a/refs.c b/refs.c
>> index b420a120102b3793168598b885bba68e4f5f5f03..75dbd84acbc41658d4b8b6b5e7763c04e78d0061 100644
>> --- a/refs.c
>> +++ b/refs.c
>> @@ -1211,6 +1212,14 @@ void ref_transaction_free(struct ref_transaction *transaction)
>>  	free(transaction);
>>  }
>>
>> +void ref_transaction_add_rejection(struct ref_transaction *transaction,
>> +				   size_t update_idx, struct strbuf *err)
>
> "add" to me sounds like you're adding a new thingy to the transaction,
> but you rather update something. How about `ref_update_set_rejected()`
> or `ref_transacton_set_rejected()`?
>
Fair enough, I've changed it to `ref_transacton_set_rejected()`.
Show 5 quoted lines
>> +{
>> +	struct ref_update *update = transaction->updates[update_idx];
>
> Do we want to `BUG()` in case `update_idx >= transaction->nr`?
>
Good point, let me add that in.
Show 16 quoted lines
>> +	update->rejected = 1;
>> +	strbuf_addbuf(&update->rejection_err, err);
>> +}
>
> Do we really need a string as rejection error? I'd expect that the set
> of failures that lead to rejection should be rather limited, which means
> that we could use an enum instead. This would unify the errors across
> backends and also allows us to figure out the root cause of rejection in
> other subsystems.
>
> If we introduced an enum, we could eventually even iterate a bit on the
> mechanism and rather trivially tell the backends which kind of failures
> are acceptable. As an example, a conflicting ref update may for example
> be ignored and not cause failure, a conflicting path name might cause
> failure.
>

That's a good point, This also allows us to eventually extend the flag to do something like you mentioned where `--allow-partial=all` would skip all errors. But one could optimize to also say `--allow-partial=name_conflict,old_value` to only skip errors due to refname conflicts and invalid/incorrect old_value.

I'll add another commit to introduce and add 'enum transaction_error' and build around it.

Show 17 quoted lines
>> diff --git a/refs/files-backend.c b/refs/files-backend.c
>> index 9fc5454678340dd7c72539bfa0f15ee7eb24b1ff..99ec29164fbd30635125cc2325aab3d300cf906c 100644
>> --- a/refs/files-backend.c
>> +++ b/refs/files-backend.c
>> @@ -2852,8 +2852,18 @@ static int files_transaction_prepare(struct ref_store *ref_store,
>>
>>  		ret = lock_ref_for_update(refs, update, transaction,
>>  					  head_ref, err);
>> -		if (ret)
>> +		if (ret) {
>
> I wonder whether we want to accept all failures. Some failures are
> certainly benign, like for example mismatching expected OIDs or a
> conflict due to a preexisting ref that blocks the path. But other kinds
> of failures which are unexpected might be a bit more on the dangerous
> side to accept, so I think we should be careful here.
>

Fair point. For the current implementation with the enum design discussed above. I think it would be best to skip over all user oriented errors. But any system errors would actually cease the transaction. We can further iterate on this later.

> The same comment also applies to the other backends.
>
> Patrick
Previous: Patrick SteinhardtNext: Karthik Nayak
Message 13 of 49 in “refs: introduce support for partial reference transactions”
  1. 0/6 refs: introduce support for partial reference transactionsKarthik Nayak, Feb 7, 2025
  2. 1/6 refs/files: remove duplicate check in `split_symref_update()`Karthik Nayak, Feb 7, 2025
  3. Patrick SteinhardtFeb 7, 2025
  4. Karthik NayakFeb 11, 2025
  5. 2/6 refs: move duplicate refname update check to generic layerKarthik Nayak, Feb 7, 2025
  6. Patrick SteinhardtFeb 7, 2025
  7. Karthik NayakFeb 11, 2025
  8. 3/6 refs/files: remove duplicate duplicates checkKarthik Nayak, Feb 7, 2025
  9. Patrick SteinhardtFeb 7, 2025
  10. 4/6 refs/reftable: extract code from the transaction preparationKarthik Nayak, Feb 7, 2025
  11. 5/6 refs: implement partial reference transaction supportKarthik Nayak, Feb 7, 2025
  12. Patrick SteinhardtFeb 7, 2025
  13. Karthik NayakFeb 21, 2025
  14. 6/6 update-ref: add --allow-partial flag for stdin modeKarthik Nayak, Feb 7, 2025
  15. Patrick SteinhardtFeb 7, 2025
  16. Karthik NayakFeb 21, 2025
  17. Phillip WoodFeb 11, 2025
  18. Phillip WoodFeb 11, 2025
  19. Karthik NayakFeb 12, 2025
  20. Karthik NayakFeb 12, 2025
  21. Phillip WoodFeb 19, 2025
  22. Patrick SteinhardtFeb 19, 2025
  23. Karthik NayakFeb 21, 2025
  24. 0/8 refs: introduce support for batched reference updatesKarthik Nayak, Mar 27, 2025
  25. 1/8 refs/files: remove redundant check in split_symref_update()Karthik Nayak, Mar 27, 2025
  26. 2/8 refs: move duplicate refname update check to generic layerKarthik Nayak, Mar 27, 2025
  27. 3/8 refs/files: remove duplicate duplicates checkKarthik Nayak, Mar 27, 2025
  28. 4/8 refs/reftable: extract code from the transaction preparationKarthik Nayak, Mar 27, 2025
  29. 5/8 refs: introduce enum-based transaction error typesKarthik Nayak, Mar 27, 2025
  30. 6/8 refs: implement batch reference update supportKarthik Nayak, Mar 27, 2025
  31. 7/8 refs: support rejection in batch updates during F/D checksKarthik Nayak, Mar 27, 2025
  32. 8/8 update-ref: add --batch-updates flag for stdin modeKarthik Nayak, Mar 27, 2025
  33. Jean-Noël AVILAMar 28, 2025
  34. Junio C HamanoMar 29, 2025
  35. Karthik NayakMar 29, 2025
  36. Patrick SteinhardtMar 28, 2025
  37. 0/8 refs: introduce support for batched reference updatesKarthik Nayak, Apr 8, 2025
  38. 1/8 refs/files: remove redundant check in split_symref_update()Karthik Nayak, Apr 8, 2025
  39. 2/8 refs: move duplicate refname update check to generic layerKarthik Nayak, Apr 8, 2025
  40. 3/8 refs/files: remove duplicate duplicates checkKarthik Nayak, Apr 8, 2025
  41. 4/8 refs/reftable: extract code from the transaction preparationKarthik Nayak, Apr 8, 2025
  42. 5/8 refs: introduce enum-based transaction error typesKarthik Nayak, Apr 8, 2025
  43. 6/8 refs: implement batch reference update supportKarthik Nayak, Apr 8, 2025
  44. 7/8 refs: support rejection in batch updates during F/D checksKarthik Nayak, Apr 8, 2025
  45. 8/8 update-ref: add --batch-updates flag for stdin modeKarthik Nayak, Apr 8, 2025
  46. Junio C HamanoApr 8, 2025
  47. Karthik NayakApr 8, 2025
  48. Junio C HamanoApr 8, 2025
  49. Karthik NayakApr 10, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.