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

Subscriber Billed Topics #609

Closed
wants to merge 12 commits into from

Conversation

karmanyaahm
Copy link
Contributor

@karmanyaahm karmanyaahm commented Feb 14, 2023

I am going with bill-to-last-visitor-for-12-hrs even though it doesn't allow users to unsubscribe because it is the simplest to explain. It's much easier to document and explain if you subscribe to a up_ topic, you are responsible for whatever is sent there for the next 12 hrs, so keep it secret, than anything else I could come up with.

The only other simple-for-the-user options would be:

  1. You can only subscribe to 30 UP topics in a day. Each UP topic can receive 100 messages / day. However, that requires keeping track of all those states and adds significant complexity to the code.
  2. Bill in sub := func(v *visitor, msg *message) error {, so only messages you actually receive count against you. However, that allows spamming the cache with messages that no one is billed for, on the sending side.

I'll add tests and rebase it and stuff if you're good with this general implementation.

server/server.go Show resolved Hide resolved
server/server.go Outdated Show resolved Hide resolved
server/errors.go Outdated Show resolved Hide resolved
log.Tag(tagSubscribe).Field("topic", t.ID).Debug("Canceling subscriber %s", s.userID)
if s.visitor.MaybeUserID() != exceptUserID {
// TODO: Shouldn't this log the IP for anonymous visitors? It was s.userID before my change.
log.Tag(tagSubscribe).Field("topic", t.ID).Debug("Canceling subscriber %s", s.visitor.MaybeUserID())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should that log be visitorID instead of userID, to also log anonymous visitors properly?

@karmanyaahm karmanyaahm marked this pull request as ready for review February 15, 2023 09:55
@binwiederhier
Copy link
Owner

I looked, I promise. I just cannot get my brain into the right headspace, which I need for this. I promise I will :-)

server/errors.go Outdated Show resolved Hide resolved
server/server.go Show resolved Hide resolved
}
return t.lastVisitor

}
Copy link
Owner

@binwiederhier binwiederhier Feb 18, 2023

Choose a reason for hiding this comment

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

  1. Style: Don't use snake_case, use camelCase. And: don't use getters (no getX), use X instead, here: func billee()
  2. This function should use the mutex!
  3. This is a strange way of retrieving the billee, IMHO. It took me very very very long to understand, which is probably not a good sign. So maybe we can do something where we assign it in Subscribe and pick a new one in Unsubscribe (if we're removing the the topicSubscriber with the same visitor as in topic.lastVisitor

Something like this:

type topic struct {
  vrate *visitor
  vrateExpires time.Time

(like you have, but rename it)

And then just assign it when you first subscribe:

  if t.vrate = nil {
    t.vrate = v
    t.vrateExpires = ...
  }
  t.subscribers[subscriberID] = &topicSubscriber{
    visitor: v,
    ..   
  }

Copy link
Owner

Choose a reason for hiding this comment

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

Updated my comment from this afternoon.

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 and 2 are done, and I think the latest rewrite achieves 3?

Copy link
Owner

@binwiederhier binwiederhier left a comment

Choose a reason for hiding this comment

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

  1. I think this is a good start, but needs quite some work. I am happy to help and work closely with you. I do want to do this very quickly, because there are very few things I have to do before I can start the payments.

  2. This needs UNIT TESTS! A lot of them :-)

server/server.go Show resolved Hide resolved
server/server.go Outdated Show resolved Hide resolved
if v == nil {
return nil, errHTTPWontStoreMessage
}
}
Copy link
Owner

Choose a reason for hiding this comment

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

I know I said to just replace v in an older comment, but the more I think about it, the more I think that this is literally just about rate limiting, right? So maybe maybe our Billee is just a vrate (= visitor used for rate limiting), and for all the rate limiting functions, we'd use vrate, but for everything else, we'd use v?

I have also noticed that you haven't tackled the limitRequests middleware at all. The rate limiting for number of messages (visitor-message-daily-limit) and number of emails (visitor-email-limit-*) happens in handlePublish*, but the rate limiting for requests (visitor-request-limit-*) happens in limitRequests, so this logic would have to happen there, not here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did this using context (as suggested below), but isn't that supposed to be an anti-pattern? In any case, I guess it's just one thing so it shouldn't matter much. I feel like the ideal solution to this would be making visitor an interface and having a compositeVisitor in addition to visitor...but, that's probably overengineering.

server/server.go Outdated Show resolved Hide resolved
}
return t.lastVisitor

}
Copy link
Owner

Choose a reason for hiding this comment

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

Updated my comment from this afternoon.

@binwiederhier
Copy link
Owner

Cool. I'll start reviewing again, but you gotta repoint to main and rebase/merge the latest main.

@karmanyaahm
Copy link
Contributor Author

karmanyaahm commented Feb 21, 2023 via email

@karmanyaahm karmanyaahm changed the base branch from user-account to main February 21, 2023 13:46
server/util.go Show resolved Hide resolved
server/server.go Show resolved Hide resolved
server/server.go Outdated Show resolved Hide resolved
@binwiederhier
Copy link
Owner

Superseded by #633

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants