Skip to content

Conversation

Muaz-Ibn-Kamal
Copy link

This pull request refactors manager.go to improve safety, efficiency, and maintainability.

Changes made:

  • Added context parameter to NewSession and EndSession instead of using context.Background
  • Improved session cleanup by deleting session mapping before calling endSession
  • Preallocated slice in AvailableBrokers for better performance
  • Standardized and clarified error messages across methods
  • Normalized username handling in BrokerForUser

These changes make session handling safer, error messages clearer, and overall code more robust.

@Muaz-Ibn-Kamal Muaz-Ibn-Kamal requested a review from a team as a code owner September 16, 2025 19:04
Copy link
Contributor

@adombeck adombeck left a comment

Choose a reason for hiding this comment

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

Thanks for contributing!

In general, please don't bundle multiple changes into a single commit, but make commits as small as possible and explain the change in the commit message.

}()

// Connect to the system bus
// Don't call dbus.SystemBus which caches globally system dbus (issues in tests)
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't remove this comment

Copy link
Author

Choose a reason for hiding this comment

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

okey thank You


// AvailableBrokers returns currently loaded and available brokers in preference order.
func (m *Manager) AvailableBrokers() (r []*Broker) {
r = make([]*Broker, 0, len(m.brokersOrder))
Copy link
Contributor

Choose a reason for hiding this comment

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

This change is fine, I see that it can avoid unnecessary allocations when appending the brokers. However, that's not explained in the commit message. Please create a separate commit with this change and explain in the commit message why it is useful.

Copy link
Author

Choose a reason for hiding this comment

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

yes

m.usersToBrokerMu.RLock()
defer m.usersToBrokerMu.RUnlock()
return m.usersToBroker[username]
return m.usersToBroker[strings.ToLower(username)]
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a bit undecided if we want this change or not. We do use lowercase usernames in authd, so this username must indeed be lowercase. However, we have so many layers of functions which take a username as an argument that it's a bit inefficient to convert it lowercase in each function.

Here we have these layers:

sequenceDiagram
    box PAM
        participant A as authd-pam
    end
    box authd
        participant B as pam.Service
        participant C as brokers.Manager
    end

    Note over A,B: Communication via gRPC

    A->>B: GetPreviousBroker
    B->>C: BrokerForUser
    C-->>B: Return broker
    B-->>A: Response
Loading

If the brokers.Manager doesn't find the broker, the users.Manager is called, which results in even more layers:

sequenceDiagram
    box PAM
        participant A as authd-pam
    end
    box authd
        participant B as pam.Service
        participant C as users.Manager
        participant D as db.Manager
    end

    Note over A,B: Communication via gRPC

    A->>B: GetPreviousBroker
    B->>C: BrokerForUser
    C->>D: UserByName
    D-->>C: UserRow.BrokerID
    C-->>B: Return BrokerID
    B-->>A: Response
Loading

We currently call strings.ToLower in all of these layers (or at least in some functions of each layer).

Looking at it like this, it's my impression that it would make most sense to just convert the usernames to lowercase once in the gRPC methods, and in the other layers (brokers.Manager, users.Manager, db.Manager) assume that the usernames are already in lowercase.

Note that the same applies to all other methods of pam.Service which takes a username as an argument, and also to the methods of user.Service.

What do you think, @3v1n0?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I was noticing the change too and I was wondering whether is needed... Ideally we should do it in any public APIs though at this point...

broker, exists := m.transactionsToBroker[id]
if !exists {
return nil, fmt.Errorf("no broker found for session %q", id)
return nil, fmt.Errorf("no broker found for session ID %q", id)
Copy link
Contributor

Choose a reason for hiding this comment

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

We use "session %q" all over the place in error and debug messages, so for consistency we should not change it here.


// NewSession create a new session for the broker and store the sesssionID on the manager.
func (m *Manager) NewSession(brokerID, username, lang, mode string) (sessionID string, encryptionKey string, err error) {
// NewSession create a new session for the broker and store the sessionID on the manager.
Copy link
Contributor

Choose a reason for hiding this comment

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

Please create a separate commit with this change. The commit message can simply be "Fix typo".

Copy link
Contributor

Choose a reason for hiding this comment

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

I see you pushed a commit with the commit message "Fix typo". However, it doesn't contain this change but adds a comment //Fix typo.

// NewSession create a new session for the broker and store the sesssionID on the manager.
func (m *Manager) NewSession(brokerID, username, lang, mode string) (sessionID string, encryptionKey string, err error) {
// NewSession create a new session for the broker and store the sessionID on the manager.
func (m *Manager) NewSession(ctx context.Context, brokerID, username, lang, mode string) (sessionID string, encryptionKey string, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's not add unused context parameters to functions. The log functions don't actually use their context arguments (for now), so that's not a good reason to add a context parameter here.

Comment on lines 188 to 196
// EndSession signals the end of the session to the broker associated with the sessionID and then removes the
// session -> broker mapping.
func (m *Manager) EndSession(sessionID string) error {
b, err := m.BrokerFromSessionID(sessionID)
if err != nil {
return err
func (m *Manager) EndSession(ctx context.Context, sessionID string) error {
m.transactionsToBrokerMu.Lock()
broker, exists := m.transactionsToBroker[sessionID]
if !exists {
m.transactionsToBrokerMu.Unlock()
return fmt.Errorf("no broker found for session ID %q", sessionID)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

why should we change the order of deleting session mapping and calling endSession? if we want to change this (which I'm not convinced of), we should also update the comment.

broker, exists := m.brokers[id]
if !exists {
return nil, fmt.Errorf("no broker found matching %q", id)
return nil, fmt.Errorf("no broker found matching ID %q", id)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fine with this change, please create a separate commit for it.


// AvailableBrokers returns currently loaded and available brokers in preference order.
func (m *Manager) AvailableBrokers() (r []*Broker) {
r = make([]*Broker, 0, len(m.brokersOrder))
Copy link
Author

Choose a reason for hiding this comment

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

Optimize AvailableBrokers to preallocate slice capacity

Preallocate the slice in AvailableBrokers with len(m.brokersOrder) capacity:

r = make([]*Broker, 0, len(m.brokersOrder))

This avoids repeated slice reallocations when appending brokers,
improves efficiency, and reduces memory churn, especially when
many brokers are loaded.

Copy link
Collaborator

Choose a reason for hiding this comment

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

True, we don't have that many though... But well still fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

Optimize AvailableBrokers to preallocate slice capacity

Preallocate the slice in AvailableBrokers with len(m.brokersOrder) capacity:

r = make([]*Broker, 0, len(m.brokersOrder))

This avoids repeated slice reallocations when appending brokers,
improves efficiency, and reduces memory churn, especially when
many brokers are loaded.

This would be a good commit message. Again, please create a separate commit with this change.

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.

3 participants