-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
[WIP] Notifications system #321
Conversation
new(UpdateTask), new(HookTask), | ||
new(Team), new(OrgUser), new(TeamUser), new(TeamRepo), | ||
new(Notice), new(EmailAddress)) | ||
new(User), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This has been messing with my OCD for a while 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about reorder them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lunny in alphabetical order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If order doesn't need to match the order in which fields are defined in the structure, then it makes sense to me to sort them alphabetically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few things
) | ||
|
||
const ( | ||
NotificationStatusUnread = "U" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use iota
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer string because it is more readable (while querying the database).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you're throwing away performance for readibility of the DB? 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One char string: 1 byte
Int: 4 bytes, unless we used smallint, it would be 2 bytes in the DB.
I don't think there will be a performance difference at all. But I'm open to change to int if most of you prefer. 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also prefer iota.
RepoID int64 `xorm:"INDEX NOT NULL"` | ||
|
||
Status string `xorm:"VARCHAR(1) INDEX NOT NULL"` | ||
Source string `xorm:"VARCHAR(1) INDEX NOT NULL"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be type NotificationStatus string
and type NotificationSource string
(if string, see above comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^
Status NotificationStatus
Source NotificationSource
now = time.Now() | ||
nowUnix = now.Unix() | ||
) | ||
n.Updated = now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gofmt
if err := sess.Begin(); err != nil { | ||
return err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no new-line IMO
for _, watch := range watches { | ||
exists, err := issueNotificationExists(sess, watch.UserID, watch.RepoID) | ||
if err != nil { | ||
return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not put the errors in a channel and check that one afterwards... what happens now is that if a User is improperly deleted, no-one will get any notifications 😕
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you're right. Ideally we should have foreign keys, so that wouldn't happen. 😄
But I think I'll call this in a goroutine, and just log on any error, instead of break.
} | ||
|
||
if err != nil { | ||
return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
Does this address gogs/gogs#2929 ? |
@strk It will. |
On Fri, Dec 02, 2016 at 01:23:24AM -0800, Andrey Nering wrote:
+ NotificationStatusUnread = "U"
One char string: 1 byte
Int: 4 bytes, unless we used smallint, it would be 2 bytes in the DB.
A char is 1 byte but a string of one char may be 2 bytes (if null
terminated) or 5 bytes (if having a 4 bytes size header, as it happens
for the "varchar" PostgreSQL datatype).
So, can you turn it into a char ?
Still, I do like readability in the DB
|
Just a thought... Can't this be "extracted" into a Service? Since (as far as I can read) this will block issue-creation response until all watchers have been notified Setting it up as a Service also have the added bonus of being able to move Mail-sending and such to the background (not sure how this works currently though) |
@bkcsoft Yes, that's a good idea |
@andreynering Preferably use channels 😉
|
192b3c7
to
72794ec
Compare
72794ec
to
7da3f89
Compare
@@ -453,6 +454,8 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) { | |||
return | |||
} | |||
|
|||
notification.Service.NotifyIssue(issue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be put in background too ?
is: go notification.Service.NotifyIssue(issues)
If I read the code correctly the NotifyIssue writes into a channel, is that operation immediate or blocks until someone reads from the channel ? (lame gopher here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a good point. Channels act like a queue, so I think it will block until it's consumed by the service.
We can use buffered channels [1], but I think we will have a panic if we exceed the buffer size. I will make some tests.
[1] https://gobyexample.com/channel-buffering
Edit: buffered channels will do the trick: https://tour.golang.org/concurrency/3
- Replace old IssueUser table with Notifications - Mark notification as read on opening - Changing creation of notifications from router to models
@bkcsoft Hmm... I tried to keep the commit history, but yeah, I agree that it's big. I'll split then, but I'll have to wait the 1.0.0 release, I think. |
Splitted. Step 1 at #429 |
WIP: still in an early stage