Mono<Void> stop() {
        List<Mono<Void>> stopMonos = new ArrayList<>(extensions.size());
        for (TurmsExtension extension : extensions) {
            stopMonos.add(extension.stopExtension()
                    .onErrorMap(t -> new RuntimeException(
                            "Caught an error while stopping the extension: "
                                    + extension.getClass()
                                            .getName(),
                            t)));
        }
        return Mono.whenDelayError(stopMonos)
                .materialize()
                .flatMap(signal -> {
                    Throwable stopExtensionsException = signal.getThrowable();
                    Exception closeContextException = null;
                    try {
                        close();
                    } catch (Exception e) {
                        closeContextException = e;
                    }
                    if (stopExtensionsException != null || closeContextException != null) {
                        RuntimeException e = new RuntimeException(
                                "Caught errors while stopping the extensions of the plugin: "
                                        + descriptor.getId());
                        if (stopExtensionsException != null) {
                            e.addSuppressed(stopExtensionsException);
                        }
                        if (closeContextException != null) {
                            e.addSuppressed(closeContextException);
                        }
                        return Mono.error(e);
                    }
                    LOGGER.info("The extensions of the plugin ({}) have been stopped",
                            descriptor.getId());
                    return Mono.empty();
                });
    }
{@link TurmsPlugin} is the plugin class for plugin developers, while {@link Plugin} is the plugin
class for us and internal development.
<p>
From the perspective of Turms developers, it is more accurate to call {@link TurmsPlugin}
"CustomPlugin" or "JavaPlugin", but from the perspective of Java plugin developers, both
"JavaPlugin" and "CustomPlugin" are fluffy because it is obvious that they are developing a java
custom plugin while "TurmsPlugin" can ensure developers know that they are developing a plugin
for Turms to distinguish with other plugin classes in their classpath.

@author James Chen
turms-server-common/src/main/java/im/turms/server/common/infra/plugin/Plugin.java