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

Shard notification hub #54

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open

Shard notification hub #54

wants to merge 37 commits into from

Conversation

lizard-boy
Copy link

@lizard-boy lizard-boy commented Oct 19, 2024

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-9452

📔 Objective

Reworks notification hub sharding to be based on the date of GUID comb creation and a binning algorithm.

This change is needed so that we can keep track of the installation location of each device, which is needed for updates related to changes to a device's

  1. Token
  2. User Organizations
  3. User authentication

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

Greptile Summary

This pull request implements a significant rework of the notification hub sharding mechanism, focusing on GUID comb creation dates and a binning algorithm for improved device management.

  • Introduced NotificationHubPool and NotificationHubConnection classes for managing multiple notification hub clients
  • Removed DeviceType parameter from various methods, simplifying push notification and registration interfaces
  • Added new interfaces INotificationHubProxy and INotificationHubPool for better abstraction of notification hub operations
  • Implemented CoreHelpers.DateFromComb and CoreHelpers.BinForComb methods to support the new sharding mechanism
  • Updated GlobalSettings to include NotificationHubPoolSettings with registration start and end dates for each hub

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

29 file(s) reviewed, 45 comment(s)
Edit PR Review Bot Settings | Greptile

@@ -46,15 +46,15 @@ await _pushRegistrationService.CreateOrUpdateRegistrationAsync(model.PushToken,
public async Task PostDelete([FromBody] PushDeviceRequestModel model)
{
CheckUsage();
await _pushRegistrationService.DeleteRegistrationAsync(Prefix(model.Id), model.Type);
await _pushRegistrationService.DeleteRegistrationAsync(Prefix(model.Id));
Copy link

Choose a reason for hiding this comment

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

logic: Removal of device type parameter may affect how different device types are handled during deletion

Comment on lines 56 to 58
await _pushRegistrationService.AddUserRegistrationOrganizationAsync(
model.Devices.Select(d => new KeyValuePair<string, Core.Enums.DeviceType>(Prefix(d.Id), d.Type)),
model.Devices.Select(d => Prefix(d.Id)),
Prefix(model.OrganizationId));
Copy link

Choose a reason for hiding this comment

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

logic: Device type information is no longer passed to AddUserRegistrationOrganizationAsync, which could impact device-specific organization management

Comment on lines 65 to 67
await _pushRegistrationService.DeleteUserRegistrationOrganizationAsync(
model.Devices.Select(d => new KeyValuePair<string, Core.Enums.DeviceType>(Prefix(d.Id), d.Type)),
model.Devices.Select(d => Prefix(d.Id)),
Prefix(model.OrganizationId));
Copy link

Choose a reason for hiding this comment

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

logic: Similar to the add-organization endpoint, device type information is removed from DeleteUserRegistrationOrganizationAsync

Comment on lines 1839 to 1841
.Where(d => !string.IsNullOrWhiteSpace(d.PushToken))
.Select(d => new KeyValuePair<string, DeviceType>(d.Id.ToString(), d.Type));
.Select(d => d.Id.ToString());
}
Copy link

Choose a reason for hiding this comment

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

logic: The Select statement now only returns the device ID as a string, omitting the DeviceType. Ensure this doesn't break any code that previously relied on the device type information.

@@ -37,4 +37,25 @@ public static bool IsInstallationDeviceId(string deviceId)
{
return deviceId != null && deviceId.Length == 73 && deviceId[36] == '_';
}
public static bool TryParse(string deviceId, out InstallationDeviceEntity installationDeviceEntity)
Copy link

Choose a reason for hiding this comment

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

style: consider adding XML documentation for this public method

Comment on lines +199 to +200
// Act
var result = connection.RegistrationEnabled(CoreHelpers.GenerateComb(Guid.NewGuid(), DateTime.UtcNow.AddHours(1)));
Copy link

Choose a reason for hiding this comment

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

style: Test might be sensitive to execution time. Consider using fixed timestamps

Comment on lines +85 to +86
RegistrationStartDate = null,
RegistrationEndDate = null,
Copy link

Choose a reason for hiding this comment

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

logic: Test might not accurately represent a scenario with no valid hubs. Consider setting dates to the past


[Theory]
[MemberData(nameof(ClientMethods))]
public async void CallsAllClients(Func<NotificationHubClientProxy, Task> proxyMethod, Func<INotificationHubClient, Task> clientMethod)
Copy link

Choose a reason for hiding this comment

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

style: Use Task instead of async void for better error handling

[MemberData(nameof(ClientMethods))]
public async void CallsAllClients(Func<NotificationHubClientProxy, Task> proxyMethod, Func<INotificationHubClient, Task> clientMethod)
{
var clients = _clients.ToArray();
Copy link

Choose a reason for hiding this comment

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

logic: Ensure _clients is not empty before converting to array

private readonly ILogger<MultiServicePushNotificationService> _logger;
private readonly ILogger<RelayPushNotificationService> _relayLogger;
private readonly ILogger<NotificationsApiPushNotificationService> _hubLogger;
private readonly IEnumerable<IPushNotificationService> _services;
Copy link

Choose a reason for hiding this comment

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

style: Consider using a more specific type like IList instead of IEnumerable for better control over the collection

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