mssf_core/runtime/package_change/
config.rs

1// ------------------------------------------------------------
2// Copyright (c) Microsoft Corporation.  All rights reserved.
3// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
4// ------------------------------------------------------------
5//! Handle callbacks for configuration package changes
6//! TODO: We probably should also provide a helpful callback to use in conjunction with the config-rs support (so that it processes configuration changes)
7use mssf_com::FabricRuntime::{
8    IFabricConfigurationPackageChangeHandler, IFabricConfigurationPackageChangeHandler_Impl,
9};
10
11use crate::runtime::{CodePackageActivationContext, config::ConfigurationPackage};
12
13use super::ConfigurationPackageChangeEvent;
14
15/// Rust trait to turn rust code into IFabricConfigurationPackageChangeHandler.
16/// Not exposed to user
17pub trait ConfigurationPackageChangeEventHandler: 'static {
18    fn on_change(&self, change: &ConfigurationPackageChangeEvent);
19}
20
21// Bridge implementation for the change handler to turn rust code into SF com object.
22#[windows_core::implement(IFabricConfigurationPackageChangeHandler)]
23#[allow(non_camel_case_types)] // Suppress lint for _Impl struct
24pub struct ConfigurationPackageChangeEventHandlerBridge<T>
25where
26    T: ConfigurationPackageChangeEventHandler,
27{
28    inner: T,
29}
30
31impl<T> ConfigurationPackageChangeEventHandlerBridge<T>
32where
33    T: ConfigurationPackageChangeEventHandler,
34{
35    pub fn new(inner: T) -> Self {
36        Self { inner }
37    }
38}
39
40impl<T> IFabricConfigurationPackageChangeHandler_Impl
41    for ConfigurationPackageChangeEventHandlerBridge_Impl<T>
42where
43    T: ConfigurationPackageChangeEventHandler,
44{
45    fn OnPackageAdded(
46        &self,
47        _source: windows_core::Ref<mssf_com::FabricRuntime::IFabricCodePackageActivationContext>,
48        configpackage: windows_core::Ref<mssf_com::FabricRuntime::IFabricConfigurationPackage>,
49    ) {
50        let new_package = ConfigurationPackage::from(configpackage.unwrap().clone());
51        let event = ConfigurationPackageChangeEvent::Addition { new_package };
52        self.inner.on_change(&event)
53    }
54
55    fn OnPackageRemoved(
56        &self,
57        _source: windows_core::Ref<mssf_com::FabricRuntime::IFabricCodePackageActivationContext>,
58        configpackage: windows_core::Ref<mssf_com::FabricRuntime::IFabricConfigurationPackage>,
59    ) {
60        let previous_package = ConfigurationPackage::from(configpackage.unwrap().clone());
61        let event = ConfigurationPackageChangeEvent::Removal { previous_package };
62        self.inner.on_change(&event)
63    }
64
65    fn OnPackageModified(
66        &self,
67        _source: windows_core::Ref<mssf_com::FabricRuntime::IFabricCodePackageActivationContext>,
68        previousconfigpackage: windows_core::Ref<
69            mssf_com::FabricRuntime::IFabricConfigurationPackage,
70        >,
71        configpackage: windows_core::Ref<mssf_com::FabricRuntime::IFabricConfigurationPackage>,
72    ) {
73        let new_package = ConfigurationPackage::from(configpackage.unwrap().clone());
74        let previous_package = ConfigurationPackage::from(previousconfigpackage.unwrap().clone());
75        let event = ConfigurationPackageChangeEvent::Modification {
76            previous_package,
77            new_package,
78        };
79        self.inner.on_change(&event)
80    }
81}
82
83/// Lambda implementation of ConfigurationPackageChangeEventHandler trait.
84/// This is used in FabricClientBuilder to build function into handler.
85/// Not exposed to user.
86/// Strictly speaking we don't need this layer. But it would allow us to open the door to trait implementations someday
87pub(crate) struct LambdaConfigurationPackageEventHandler<T>
88where
89    T: Fn(&ConfigurationPackageChangeEvent),
90{
91    f: T,
92}
93
94impl<T> LambdaConfigurationPackageEventHandler<T>
95where
96    T: Fn(&ConfigurationPackageChangeEvent) + 'static,
97{
98    pub fn new(f: T) -> Self {
99        Self { f }
100    }
101}
102
103impl<T> ConfigurationPackageChangeEventHandler for LambdaConfigurationPackageEventHandler<T>
104where
105    T: Fn(&ConfigurationPackageChangeEvent) + 'static,
106{
107    fn on_change(&self, change: &ConfigurationPackageChangeEvent) {
108        (self.f)(change)
109    }
110}
111
112/// An opaque id representing a registered Configuration Package Change callback
113#[derive(Debug)]
114pub struct ConfigurationPackageChangeCallbackHandle(pub(crate) i64);
115
116impl ConfigurationPackageChangeCallbackHandle {
117    /// # Safety
118    /// Caller ensures this is a registered callback id
119    pub const unsafe fn from(com: i64) -> Self {
120        Self(com)
121    }
122}
123
124/// This struct manages deregistering the Service Fabric Config Package Change callback
125/// when it leaves scope.
126#[derive(Debug)]
127pub struct AutoConfigurationPackageChangeCallbackHandle {
128    /// Service Fabric Activation Context
129    activation_ctx: CodePackageActivationContext,
130    /// Handle to deregister on drop
131    handle: Option<ConfigurationPackageChangeCallbackHandle>,
132}
133
134impl AutoConfigurationPackageChangeCallbackHandle {
135    /// Register a new handle for the provided lambda.
136    /// Clones (e.g. adjusts reference count) on activation_ctx
137    pub fn new<T>(activation_ctx: &CodePackageActivationContext, handler: T) -> crate::Result<Self>
138    where
139        T: Fn(&ConfigurationPackageChangeEvent) + 'static,
140    {
141        let handle = activation_ctx.register_configuration_package_change_handler(handler)?;
142        Ok(Self {
143            activation_ctx: activation_ctx.clone(),
144            handle: Some(handle),
145        })
146    }
147}
148
149impl Drop for AutoConfigurationPackageChangeCallbackHandle {
150    fn drop(&mut self) {
151        if let Some(my_handle) = self.handle.take() {
152            self.activation_ctx
153                .unregister_configuration_package_change_handler(my_handle)
154                .expect("Unregistering handle should succeed.");
155        }
156    }
157}