Skip to content

Limit the number of duplicate requests in flight #445

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 22, 2025

Conversation

phbnf
Copy link
Collaborator

@phbnf phbnf commented Jul 17, 2025

Towards #322, #448

@phbnf phbnf added this to the alpha milestone Jul 17, 2025
@phbnf phbnf requested review from roger2hk and AlCutter July 17, 2025 10:03
@phbnf phbnf added the enhancement New feature or request label Jul 17, 2025
@phbnf phbnf marked this pull request as ready for review July 17, 2025 10:31
Copy link
Collaborator

@AlCutter AlCutter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one, just a couple of little suggestions in-line.

@@ -168,7 +169,7 @@ func newStorage(ctx context.Context, signer note.Signer) (*storage.CTStorage, er
return nil, fmt.Errorf("failed to initialize GCP issuer storage: %v", err)
}

return storage.NewCTStorage(ctx, appender, issuerStorage, reader, *enablePublicationAwaiter)
return storage.NewCTStorage(ctx, appender, issuerStorage, reader, *enablePublicationAwaiter, *pushbackMaxDupesInFlight)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like this is getting close to warranting a CTStorageOptions struct

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 (it's getting longer and longer)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. We now have to pass a struct to a function that itself create a new struct... We should be able to restructure the code a bit later, but let's leave it like this for now to see what we'll need to add / remove.

}

t := time.NewTicker(1 * time.Second)
go func() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worthwhile adding a small comment which just explains how this limiting works. It's straightfoward and easy to understand, but there's related action at a distance so worth a bread-crumb trail?

A vehicle for this could be to pull the inline func out into a ...Job func like we do in the Tessera storage impls and use the opportunity to pop on a Godoc func comment?

@@ -138,6 +155,10 @@ func (cts *CTStorage) Add(ctx context.Context, entry *ctonly.Entry) (uint64, uin
}
}
if idx.IsDup {
if cts.dupesInFlight.Load() > int64(cts.maxDupesInFlight) {
return 0, 0, fmt.Errorf("antispam in-flight %w", tessera.ErrPushback)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return 0, 0, fmt.Errorf("antispam in-flight %w", tessera.ErrPushback)
return 0, 0, fmt.Errorf("too many duplicate submissions %w", tessera.ErrPushback)

@@ -59,6 +59,7 @@ var (
origin = flag.String("origin", "", "Origin of the log, for checkpoints and the monitoring prefix.")
storageDir = flag.String("storage_dir", "", "Path to root of log storage.")
pushbackMaxOutstanding = flag.Uint("pushback_max_outstanding", tessera.DefaultPushbackMaxOutstanding, "Maximum number of number of in-flight add requests - i.e. the number of entries with sequence numbers assigned, but which are not yet integrated into the log.")
pushbackMaxDupesInFlight = flag.Uint("pushback_max_dupes_in_flight", 100, "Maximum number of number of in-flight duplicate add requests. When 0, duplicate entries are always pushed back.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove _in_flight from the flag name. The pushback_max_outstanding flag is also for in-flight requests and we don't have "in flight" in the flag name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought a lot about this before sending this PR, and after reading your comment. pushbackMaxOutstanding has an element of time with "outstanding", implying that eventually there will be less outstanding requests at some point.
Given that this new pushback mechanism looks at the number of request happening at a given point in time, I think using the "inFlight" qualifier better conveys that this. I've changed the name, and improved the flag description.

Comment on lines 66 to 67
dupesInFlight atomic.Int64
maxDupesInFlight uint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dupesInFlight atomic.Int64
maxDupesInFlight uint
maxDupesInFlight uint
dupesInFlight atomic.Int64

Separating the struct variables into two different groups helps the readability.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that we could probably re-arrange this struct. I can't really tell what grouping you were thinking of and why dupesInFlight should be alone though. I'll merge this as is, and we can talk about it when you're back :)

Copy link
Contributor

@roger2hk roger2hk Jul 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only dedupeFutureInFlight is not passed from NewCTStorage func. That's why I think it's better to put it in another group (or at least put it at the end of the list).

type CTStorage struct {
	storeData               func(context.Context, *ctonly.Entry) tessera.IndexFuture
	storeIssuers            func(context.Context, []KV) error
	reader                  tessera.LogReader
	awaiter                 *tessera.PublicationAwaiter
	enableAwaiter           bool
	dedupeFutureInFlight    atomic.Int64
	maxDedupeFutureInFlight uint
}
	ctStorage := &CTStorage{
		storeData:               tessera.NewCertificateTransparencyAppender(opts.Appender),
		storeIssuers:            cachedStoreIssuers(opts.IssuerStorage),
		reader:                  opts.Reader,
		awaiter:                 awaiter,
		enableAwaiter:           opts.EnableAwaiter,
		maxDedupeFutureInFlight: opts.MaxDedupeInFlight,
	}

@phbnf phbnf force-pushed the deduplock branch 5 times, most recently from e053f35 to a49b784 Compare July 22, 2025 12:45
@phbnf
Copy link
Collaborator Author

phbnf commented Jul 22, 2025

I've changed this PR quite a lot:

  • added ops
  • added a new struct
  • I moved around the throttling
  • I changed names

phbnf added 2 commits July 22, 2025 14:40
# Conflicts:
#	cmd/tesseract/gcp/main.go
# Conflicts:
#	cmd/tesseract/gcp/main.go
@phbnf phbnf merged commit b57aa18 into transparency-dev:main Jul 22, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants