vaadin / collaboration-engine

The simplest way to build real-time collaboration into web apps
https://vaadin.com/collaboration
Other
3 stars 1 forks source link

Add API to be notified about exceeding usage limits #12

Closed pekam closed 3 years ago

pekam commented 3 years ago

Is your feature request related to a use case? Please describe.

Because of the licensing model that is based on a monthly end user quota, it is possible that Collaboration Engine features are disabled for a user when the quota is exceeded. When the quota is exceeded for the first time, there will be a 30 days grace period, during which the customer has 10x the regular quota in order to react to peaking users.

As the application owner, I want to be notified when entering the grace period, so that I know that I should buy a bigger user quota for the next month. I also want to know when the license is about to expire, so that I can renew it in time.

Just in case, I'd also like to also know if the grace period ends or the license expires. These cases would mean that I have failed to update my license in time.

As a developer, I want to connect these notifications to the existing monitoring system in our infrastructure.

Describe the solution you'd like

Usage example:

    @Component
    class CollaborationEngineConfiguration {
        public CollaborationEngineConfiguration(){
            System.setProperty("vaadin.ce.dataDir", "foo");
            CollaborationEngine.getInstance().setLicenseEventHandler(event -> {
                    switch (event.getType()) {
                    case GRACE_PERIOD_STARTED:
                    case LICENSE_EXPIRES_SOON:
                    case LICENSE_EXPIRED:
                        applicationMonitoring
                                .warning(notification.getMessage());
                        break;
                    case GRACE_PERIOD_ENDED:
                        applicationMonitoring.info(notification.getMessage());
                            break;
                    }
            });
        }
    }

These new types would be added:

interface LicenseEvent {
    LicenseEventType getType();
    String getMessage();
}
@FunctionalInterface
interface LicenseEventHandler {
    void licenseEventReceived(LicenseEvent event);
}
enum LicenseEventType {
    GRACE_PERIOD_STARTED, GRACE_PERIOD_ENDED, LICENSE_EXPIRES_SOON, LICENSE_EXPIRED
}

This method would be added to CollaborationEngine:

public void setLicenseEventHandler(LicenseEventHandler handler)

The notifications would be fired by the first openTopicConnection call, when a condition has been fulfilled:

Providing a handler should be required, to make sure that the developer is aware of these events and takes care of handling them. If the handler is not provided when using CollaborationEngine (calling openTopicConnection or requestAccess), an exception should be thrown with a clear description of this reasoning.

Overriding the handler after one has been set already should throw.

NOTE: Notifications related to the license end date can be split to another ticket, if the end date restriction has not been implemented yet.

Describe alternatives you've considered

If/when there are more things to configure once, we might want to wrap all of those in some config object, to keep the public API of CollaborationEngine cleaner.

Optimally, this kind of one-time config would also be defined in a declarative way, instead of imperative. With the proposed API, the developer needs to make sure that the code runs before using CE. It would be better to implement some configuration class and add some annotation on it, and then let CE take care of finding it. This is however not straightforward because of the differences in class-path scanning in spring-boot apps vs. other apps, but we can look into that as a later enhancement.

Peppe commented 3 years ago

Discussion during daily:

    @Component
    class CollaborationEngineConfiguration {
        public CollaborationEngineConfiguration(){
            System.setProperty("vaadin.ce.dataDir", "foo");
            CollaborationEngine.getInstance().setLicenseEventHandler(event -> {
                // foo = status, notification, message, license, event
                switch(event.getType()){
                    ...
                }
            });
        }
    }
heruan commented 3 years ago

To keep track of fired events, a new field should be added to the statistics file; e.g.

{
  "statistics": {},
  "licenseEvents": {
    "GRACE_PERIOD_STARTED": "2020-11-20",
    "LICENSE_EXPIRES_SOON": "2020-12-01"
  }
}
pekam commented 3 years ago

Event messages split into #19