Skip to content
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

Queues: Move Notification to use a Queue #9902

Closed
wants to merge 13 commits into from

Conversation

zeripath
Copy link
Contributor

@zeripath zeripath commented Jan 20, 2020

Move the notifier system to use a Queue.

  • First step is to move the ui service to use a Queue
  • Next in preparation to use a Queue we ensure that we can json marshal things passed in the notification
  • Autogeneration is used to create a notifier that wraps all the notification calls to a queue push and expand them back out
  • A special notification helper is provided for tests allowing these to specifically check notification events

Closes #8874

@zeripath zeripath added the type/enhancement An improvement of existing functionality label Jan 20, 2020
@zeripath
Copy link
Contributor Author

This one is potentially quite controversial ... Basically every request can cause a notification so this one might require a large amount of workers if we don't want it to get overloaded.

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Jan 20, 2020
@guillep2k
Copy link
Member

This one is potentially quite controversial ... Basically every request can cause a notification so this one might require a large amount of workers if we don't want it to get overloaded.

He he... 😁

Well, I'm in favor of longer queues rather than many workers. If we've got to send 1,000 mails or insert as many UI notifications, I'd rather do it in one or two workers than in 1,000. Heck! Our default db pool size is unlimited, which is not very friendly.

And since all workers would be potentially competing for the same resources, I think less workers would eventually be much faster if the number of items is sufficiently large. Maybe with this PR it will be easier to test, if I generate a large number of users. 🤔

@zeripath
Copy link
Contributor Author

So there's still a race in the pull merge test. I'll have to do a bit more work on that.

I guess it's just enforce that what we're seeing is actually a merge or not for this test.

@zeripath
Copy link
Contributor Author

@guillep2k I agree, we should grow worker pools where we know that they can cope with the concurrency and restrict the others with a large enough channel (for channel based queues.)

@lunny lunny added this to the 1.12.0 milestone Jan 21, 2020
Copy link
Member

@guillep2k guillep2k left a comment

Choose a reason for hiding this comment

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

Oh, man, you've been having fun! 😁

modules/notification/base/main.go Outdated Show resolved Hide resolved
integrations/notification_helper_test.go Outdated Show resolved Hide resolved
modules/notification/base/main.go Outdated Show resolved Hide resolved
modules/notification/base/main.go Show resolved Hide resolved
@@ -9,6 +9,8 @@ import (
"code.gitea.io/gitea/modules/repository"
)

//go:generate go run -mod=vendor main.go
Copy link
Member

Choose a reason for hiding this comment

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

So if any functions are added to the interface we need to run go generate and commit what's been created? Maybe the generated files should be added to .gitignore, but then changes in main.go become very difficult to review.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah or just make build as we run go generate in build now.

notifier.go needs a comment to this effect though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a few comments

Copy link
Member

Choose a reason for hiding this comment

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

Why we need to generate that two files? Any advantage the new method than before?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. If you change notifier.go they will be both be kept up to date.
  2. It would be beyond tiresome to write the notifier queue by hand and incredibly difficult to keep up to date.

@@ -47,7 +47,7 @@ type Issue struct {
IsClosed bool `xorm:"INDEX"`
IsRead bool `xorm:"-"`
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
PullRequest *PullRequest `xorm:"-"`
PullRequest *PullRequest `xorm:"-" json:"-"`
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering whether attachments, comments, reactions, assignees, etc. should be skipped too. Because there are reference fields in those structs as well (isn't there an Issue property in Comment?). Sounds like recursions can cause some headaches. On the other hand, the serialized data is a snapshot of the object state that protects the notifier from other processes changing the data, so it makes some sense to keep it as is. Decisions, decisions... 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yup. I decided to bridge the problem as and when we see it. The trouble is under the default testing case you might not see the issue as we don't necessarily try to jsonify these things. (Hmm maybe I should add a jsontestqueue that will always json.Marshal stuff.)

As we pass into notifier pull requests and issues which definitely have a cyclic reference and therefore MarshalJSON doesn't work - we need to break the cycle. Every PR has an issue. Not all issues have PRs - so breaking the cycle at issue seemed best.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not particularly worried about cyclic references; those should stand out soon enough. But I think the overhead of serializing the whole bunch might be excessive. What I'm thinking is to use the opposite strategy: pass on only what is not derived, unless there's a reason to.

On the other hand, passing data which is tightly-coupled with the running Gitea version poses a problem for upgrading if any queues contain data during the process (e.g. file-system backed queues retained across shutdowns). One possible solution to this problem is to prevent upgrading if any queues contain data, but that may require a migration step being aware of the queue configuration and it would be very difficult to implement. May be we could drop a record on the database when shutting down if all queues are empty and the shutdown was orderly? A migration step could refuse to continue if that record is missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The trouble with not passing "derived" data is that the notification you may get may be different from what was done.

You have to pass and parse all the data that makes the notification because you can't be certain what's going to change in future.

If you migrate and you can't deserialize mostly the notification will be dropped or default values added.

As you say we need a flush mechanism. That may mean opening a non listening Gitea to run through its queues.

integrations/notification_helper_test.go Outdated Show resolved Hide resolved
integrations/pull_merge_test.go Outdated Show resolved Hide resolved
integrations/pull_merge_test.go Outdated Show resolved Hide resolved
integrations/pull_merge_test.go Outdated Show resolved Hide resolved
@lunny
Copy link
Member

lunny commented Jan 22, 2020

For test with notification, I think we just need a mockNotification and register only this notification. That will make the code simpler.

@GiteaBot GiteaBot added lgtm/need 1 This PR needs approval from one additional maintainer to be merged. and removed lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. labels Jan 22, 2020
@zeripath
Copy link
Contributor Author

zeripath commented Jan 26, 2020

I've forcibly rebased on #10001 as this should fix a number of issues with the tests. Except it doesn't because there is a race between the TestPullRequests and Merging.

@zeripath zeripath force-pushed the queues-notification branch 3 times, most recently from aefbb99 to 13ba0da Compare February 10, 2020 17:07
@codecov-io
Copy link

codecov-io commented Feb 10, 2020

Codecov Report

Merging #9902 into master will decrease coverage by 0.15%.
The diff coverage is 43.9%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #9902      +/-   ##
==========================================
- Coverage   43.74%   43.58%   -0.16%     
==========================================
  Files         585      586       +1     
  Lines       81023    82598    +1575     
==========================================
+ Hits        35440    36002     +562     
- Misses      41202    42092     +890     
- Partials     4381     4504     +123
Impacted Files Coverage Δ
models/user.go 49.54% <ø> (ø) ⬆️
models/issue.go 53.95% <ø> (ø) ⬆️
modules/convert/pull.go 72.58% <0%> (+1.5%) ⬆️
modules/notification/indexer/indexer.go 56.96% <100%> (+2.29%) ⬆️
routers/api/v1/repo/issue_comment.go 57.39% <100%> (+0.18%) ⬆️
modules/notification/notification.go 79.85% <100%> (+0.59%) ⬆️
modules/notification/mail/mail.go 29.62% <33.33%> (+0.64%) ⬆️
modules/notification/base/queue.go 42.61% <42.61%> (ø)
models/repo_unit.go 72.64% <56.09%> (-10.44%) ⬇️
modules/notification/ui/ui.go 77.77% <60%> (+7.4%) ⬆️
... and 28 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 17445bb...a7ad2ab. Read the comment docs.

@6543
Copy link
Member

6543 commented Mar 31, 2020

can you pleace resolve confilcts :D

@lafriks
Copy link
Member

lafriks commented Apr 27, 2020

@zeripath ping

@lunny
Copy link
Member

lunny commented May 2, 2020

We have to be careful most notifier function params are pointers that maybe changed both in the notifiers' go routines or the original go routine.

@GiteaBot GiteaBot added lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels May 16, 2020
@zeripath
Copy link
Contributor Author

This should not go in to 1.12 at this stage.

@zeripath zeripath added the status/blocked This PR cannot be merged yet, i.e. because it depends on another unmerged PR label May 16, 2020
@zeripath zeripath modified the milestones: 1.12.0, 1.13.0 May 16, 2020
@codecov-commenter
Copy link

Codecov Report

Merging #9902 into master will decrease coverage by 0.25%.
The diff coverage is 43.80%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #9902      +/-   ##
==========================================
- Coverage   43.88%   43.62%   -0.26%     
==========================================
  Files         614      608       -6     
  Lines       87607    88522     +915     
==========================================
+ Hits        38449    38622     +173     
- Misses      44421    45070     +649     
- Partials     4737     4830      +93     
Impacted Files Coverage Δ
models/issue.go 51.94% <ø> (+0.37%) ⬆️
models/user.go 49.66% <ø> (-1.38%) ⬇️
modules/convert/pull.go 70.33% <0.00%> (+1.64%) ⬆️
modules/notification/mail/mail.go 30.23% <33.33%> (+0.50%) ⬆️
modules/notification/base/queue.go 42.39% <42.39%> (ø)
models/repo_unit.go 72.64% <56.09%> (-10.44%) ⬇️
modules/notification/base/null.go 69.69% <68.75%> (ø)
modules/notification/indexer/indexer.go 56.96% <100.00%> (+6.96%) ⬆️
modules/notification/notification.go 80.41% <100.00%> (+0.56%) ⬆️
modules/notification/ui/ui.go 80.76% <100.00%> (+5.12%) ⬆️
... and 90 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update aaaaeb7...d43d378. Read the comment docs.

@6543
Copy link
Member

6543 commented Sep 2, 2020

pleace resolve conflict

@lunny lunny modified the milestones: 1.13.0, 1.14.0 Sep 10, 2020
@lunny lunny modified the milestones: 1.14.0, 1.x.x Jan 27, 2021
@zeripath zeripath closed this Oct 15, 2022
@lunny lunny removed this from the 1.x.x milestone Oct 17, 2022
@go-gitea go-gitea locked and limited conversation to collaborators May 3, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. status/blocked This PR cannot be merged yet, i.e. because it depends on another unmerged PR type/enhancement An improvement of existing functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants