Repository: apache/streampipes
Pull request #2515 (2024-03-06 17:51:25)

2312 Extend Notification sinks by silent period
Purpose

For the following sinks: OneSignalSink, SlackSink, TelegramSink

Refactored to extend StreamPipesNotificationSink interface
Implemented migrations with the use of a common interface INotificationDataSinkMigrator

Added a unit test for INotificationDataSinkMigrator

Remarks
PR introduces (a) breaking change(s): no

PR introduces (a) deprecation(s): no


Patch:
diff --git a/NOTICE b/NOTICE
index f7f288bd5f..d06150f1c5 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache StreamPipes
-Copyright 2019-2023 The Apache Software Foundation.
+Copyright 2019-2024 The Apache Software Foundation.
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/streampipes-client-python/poetry.lock b/streampipes-client-python/poetry.lock
index 8987be2aca..07426ea18f 100644
--- a/streampipes-client-python/poetry.lock
+++ b/streampipes-client-python/poetry.lock
@@ -1502,38 +1502,38 @@ files = [
 
 [[package]]
 name = "mypy"
-version = "1.8.0"
+version = "1.9.0"
 description = "Optional static typing for Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"},
-    {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"},
-    {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"},
-    {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"},
-    {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"},
-    {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"},
-    {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"},
-    {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"},
-    {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"},
-    {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"},
-    {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"},
-    {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"},
-    {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"},
-    {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"},
-    {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"},
-    {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"},
-    {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"},
-    {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"},
-    {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"},
-    {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"},
-    {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"},
-    {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"},
-    {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"},
-    {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"},
-    {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"},
-    {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"},
-    {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"},
+    {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"},
+    {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"},
+    {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"},
+    {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"},
+    {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"},
+    {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"},
+    {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"},
+    {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"},
+    {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"},
+    {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"},
+    {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"},
+    {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"},
+    {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"},
+    {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"},
+    {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"},
+    {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"},
+    {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"},
+    {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"},
+    {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"},
+    {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"},
+    {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"},
+    {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"},
+    {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"},
+    {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"},
+    {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"},
+    {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"},
+    {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"},
 ]
 
 [package.dependencies]
@@ -2261,13 +2261,13 @@ extra = ["pygments (>=2.12)"]
 
 [[package]]
 name = "pytest"
-version = "8.0.0"
+version = "8.1.1"
 description = "pytest: simple powerful testing with Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"},
-    {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"},
+    {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
+    {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
 ]
 
 [package.dependencies]
@@ -2275,11 +2275,11 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""}
 exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
 iniconfig = "*"
 packaging = "*"
-pluggy = ">=1.3.0,<2.0"
-tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+pluggy = ">=1.4,<2.0"
+tomli = {version = ">=1", markers = "python_version < \"3.11\""}
 
 [package.extras]
-testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
 
 [[package]]
 name = "pytest-cov"
@@ -2415,6 +2415,7 @@ files = [
     {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
     {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
     {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+    {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
     {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
     {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
     {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
@@ -3211,13 +3212,13 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
 
 [[package]]
 name = "twine"
-version = "4.0.2"
+version = "5.0.0"
 description = "Collection of utilities for publishing packages on PyPI"
 optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 files = [
-    {file = "twine-4.0.2-py3-none-any.whl", hash = "sha256:929bc3c280033347a00f847236564d1c52a3e61b1ac2516c97c48f3ceab756d8"},
-    {file = "twine-4.0.2.tar.gz", hash = "sha256:9e102ef5fdd5a20661eb88fad46338806c3bd32cf1db729603fe3697b1bc83c8"},
+    {file = "twine-5.0.0-py3-none-any.whl", hash = "sha256:a262933de0b484c53408f9edae2e7821c1c45a3314ff2df9bdd343aa7ab8edc0"},
+    {file = "twine-5.0.0.tar.gz", hash = "sha256:89b0cc7d370a4b66421cc6102f269aa910fe0f1861c124f573cf2ddedbc10cf4"},
 ]
 
 [package.dependencies]
@@ -3294,13 +3295,13 @@ files = [
 
 [[package]]
 name = "typing-extensions"
-version = "4.9.0"
+version = "4.10.0"
 description = "Backported and Experimental Type Hints for Python 3.8+"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"},
-    {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
+    {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
+    {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
 ]
 
 [[package]]
@@ -3474,4 +3475,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
 [metadata]
 lock-version = "2.0"
 python-versions = ">3.8.1,<3.12"
-content-hash = "7d5ca5846fa512d861b67d65e5190ddd2b169a0ee6f3580a014642123585fb31"
+content-hash = "82a864e7d8bbf366a6b6ce35809ae9b80f4277a921451938eeffd67f2103b07f"
diff --git a/streampipes-client-python/pyproject.toml b/streampipes-client-python/pyproject.toml
index 37881be61b..7b5ecb2821 100644
--- a/streampipes-client-python/pyproject.toml
+++ b/streampipes-client-python/pyproject.toml
@@ -71,10 +71,10 @@ blacken-docs = "1.16.0"
 flake8 = "6.1.0"
 interrogate = { version = "1.5.0", extras = ["png"] }
 isort = "5.13.0"
-mypy = "1.8.0"
+mypy = "1.9.0"
 ruff = "0.3.0"
 pre-commit = "3.5.0"
-pytest = "8.0.0"
+pytest = "8.1.1"
 pytest-cov = "4.1.0"
 pyupgrade = "3.15.0"
 
@@ -105,7 +105,7 @@ types-requests = "2.31.0.0"
 optional = true
 
 [tool.poetry.group.deployment.dependencies]
-twine = "4.0.2"
+twine = "5.0.0"
 
 [[tool.poetry.source]]
 name = "PyPI"
diff --git a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/health/AdapterHealthCheck.java b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/health/AdapterHealthCheck.java
index 1d8843a62c..210f6e6674 100644
--- a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/health/AdapterHealthCheck.java
+++ b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/health/AdapterHealthCheck.java
@@ -222,7 +222,8 @@ public class AdapterHealthCheck implements Runnable {
                                                    adapterDescription.getElementId()));
                                      } catch (AdapterException e) {
                                        LOG.info(
-                                           "Could not recover adapter at endpoint {} due to {}",
+                                           "Could not recover adapter at endpoint {}  - "
+                                               + "marking it as requested to recover (reason: {})",
                                            adapterEndpointUrl,
                                            e.getMessage()
                                        );
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/NotificationsExtensionModuleExport.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/NotificationsExtensionModuleExport.java
index 3c3d29360e..87cac004f7 100644
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/NotificationsExtensionModuleExport.java
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/NotificationsExtensionModuleExport.java
@@ -23,6 +23,9 @@ import org.apache.streampipes.extensions.api.declarer.IExtensionModuleExport;
 import org.apache.streampipes.extensions.api.migration.IModelMigrator;
 import org.apache.streampipes.extensions.api.pe.IStreamPipesPipelineElement;
 import org.apache.streampipes.sinks.notifications.jvm.email.EmailSink;
+import org.apache.streampipes.sinks.notifications.jvm.migrations.OneSignalSinkMigrationV1;
+import org.apache.streampipes.sinks.notifications.jvm.migrations.SlackNotificationSinkMigrationV1;
+import org.apache.streampipes.sinks.notifications.jvm.migrations.TelegramSinkMigrationV1;
 import org.apache.streampipes.sinks.notifications.jvm.msteams.MSTeamsSink;
 import org.apache.streampipes.sinks.notifications.jvm.onesignal.OneSignalSink;
 import org.apache.streampipes.sinks.notifications.jvm.slack.SlackNotificationSink;
@@ -50,6 +53,10 @@ public class NotificationsExtensionModuleExport implements IExtensionModuleExpor
 
   @Override
   public List<IModelMigrator<?, ?>> migrators() {
-    return Collections.emptyList();
+    return List.of(
+            new OneSignalSinkMigrationV1(),
+            new SlackNotificationSinkMigrationV1(),
+            new TelegramSinkMigrationV1()
+    );
   }
 }
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/INotificationDataSinkMigrator.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/INotificationDataSinkMigrator.java
new file mode 100644
index 0000000000..f795c28460
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/INotificationDataSinkMigrator.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.notifications.jvm.migrations;
+
+import org.apache.streampipes.extensions.api.extractor.IDataSinkParameterExtractor;
+import org.apache.streampipes.extensions.api.migration.IDataSinkMigrator;
+import org.apache.streampipes.model.graph.DataSinkInvocation;
+import org.apache.streampipes.model.migration.MigrationResult;
+import org.apache.streampipes.model.staticproperty.FreeTextStaticProperty;
+import org.apache.streampipes.vocabulary.XSD;
+
+import static org.apache.streampipes.wrapper.standalone.StreamPipesNotificationSink.DEFAULT_WAITING_TIME_MINUTES;
+import static org.apache.streampipes.wrapper.standalone.StreamPipesNotificationSink.KEY_SILENT_PERIOD;
+
+public interface INotificationDataSinkMigrator extends IDataSinkMigrator  {
+  @Override
+  default MigrationResult<DataSinkInvocation> migrate(DataSinkInvocation element,
+                                                      IDataSinkParameterExtractor extractor) throws RuntimeException {
+    var fsp = new FreeTextStaticProperty(KEY_SILENT_PERIOD,
+        "Silent Period [min]",
+        "The minimum number of minutes between two consecutive notifications that are sent",
+        XSD.INTEGER);
+    fsp.setValue(String.valueOf(DEFAULT_WAITING_TIME_MINUTES));
+    element.getStaticProperties().add(fsp);
+
+    return MigrationResult.success(element);
+  }
+}
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/OneSignalSinkMigrationV1.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/OneSignalSinkMigrationV1.java
new file mode 100644
index 0000000000..cdba693f76
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/OneSignalSinkMigrationV1.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.notifications.jvm.migrations;
+
+import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceTagPrefix;
+import org.apache.streampipes.model.migration.ModelMigratorConfig;
+
+import static org.apache.streampipes.sinks.notifications.jvm.onesignal.OneSignalSink.ONE_SIGNAL_NOTIFICATION_SINK_ID;
+
+public class OneSignalSinkMigrationV1 implements INotificationDataSinkMigrator {
+  @Override
+  public ModelMigratorConfig config() {
+    return new ModelMigratorConfig(
+      ONE_SIGNAL_NOTIFICATION_SINK_ID,
+      SpServiceTagPrefix.DATA_SINK,
+      0,
+      1
+    );
+  }
+}
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/SlackNotificationSinkMigrationV1.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/SlackNotificationSinkMigrationV1.java
new file mode 100644
index 0000000000..ff8a048c8d
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/SlackNotificationSinkMigrationV1.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.notifications.jvm.migrations;
+
+import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceTagPrefix;
+import org.apache.streampipes.model.migration.ModelMigratorConfig;
+
+import static org.apache.streampipes.sinks.notifications.jvm.slack.SlackNotificationSink.SLACK_NOTIFICATION_SINK_ID;
+
+public class SlackNotificationSinkMigrationV1 implements INotificationDataSinkMigrator {
+  @Override
+  public ModelMigratorConfig config() {
+    return new ModelMigratorConfig(
+      SLACK_NOTIFICATION_SINK_ID,
+      SpServiceTagPrefix.DATA_SINK,
+      0,
+      1
+    );
+  }
+}
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPipelineMonitoringDataStorage.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/TelegramSinkMigrationV1.java
similarity index 57%
rename from streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPipelineMonitoringDataStorage.java
rename to streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/TelegramSinkMigrationV1.java
index eade25eabc..a040219b3a 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPipelineMonitoringDataStorage.java
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/migrations/TelegramSinkMigrationV1.java
@@ -16,21 +16,21 @@
  *
  */
 
-package org.apache.streampipes.storage.api;
-
-import org.apache.streampipes.model.client.monitoring.JobReport;
-
-import java.util.List;
-
-public interface IPipelineMonitoringDataStorage {
-
-  List<JobReport> getAllMonitoringJobReports();
-
-  List<JobReport> getAllMonitoringJobReportsByElement(String elementUri);
-
-  JobReport getLatestJobReport(String elementUri);
-
-  boolean storeJobReport(JobReport jobReport);
-
-
+package org.apache.streampipes.sinks.notifications.jvm.migrations;
+
+import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceTagPrefix;
+import org.apache.streampipes.model.migration.ModelMigratorConfig;
+
+import static org.apache.streampipes.sinks.notifications.jvm.telegram.TelegramSink.TELEGRAM_NOTIFICATION_SINK_ID;
+
+public class TelegramSinkMigrationV1 implements INotificationDataSinkMigrator {
+  @Override
+  public ModelMigratorConfig config() {
+    return new ModelMigratorConfig(
+      TELEGRAM_NOTIFICATION_SINK_ID,
+      SpServiceTagPrefix.DATA_SINK,
+      0,
+      1
+    );
+  }
 }
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/onesignal/OneSignalSink.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/onesignal/OneSignalSink.java
index ff5a23c8a5..ad17bb1b3b 100644
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/onesignal/OneSignalSink.java
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/onesignal/OneSignalSink.java
@@ -21,7 +21,6 @@ package org.apache.streampipes.sinks.notifications.jvm.onesignal;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.extensions.api.pe.context.EventSinkRuntimeContext;
 import org.apache.streampipes.model.DataSinkType;
-import org.apache.streampipes.model.graph.DataSinkDescription;
 import org.apache.streampipes.model.runtime.Event;
 import org.apache.streampipes.sdk.builder.DataSinkBuilder;
 import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
@@ -30,7 +29,7 @@ import org.apache.streampipes.sdk.helpers.Labels;
 import org.apache.streampipes.sdk.helpers.Locales;
 import org.apache.streampipes.sdk.utils.Assets;
 import org.apache.streampipes.wrapper.params.compat.SinkParams;
-import org.apache.streampipes.wrapper.standalone.StreamPipesDataSink;
+import org.apache.streampipes.wrapper.standalone.StreamPipesNotificationSink;
 
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
@@ -39,10 +38,13 @@ import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.HttpClients;
 
+
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 
-public class OneSignalSink extends StreamPipesDataSink {
+public class OneSignalSink extends StreamPipesNotificationSink {
+  public static final String ONE_SIGNAL_NOTIFICATION_SINK_ID =
+      "org.apache.streampipes.sinks.notifications.jvm.onesignal";
 
   private static final String CONTENT_KEY = "content";
   private static final String APP_ID = "app_id";
@@ -53,9 +55,9 @@ public class OneSignalSink extends StreamPipesDataSink {
   private String apiKey;
 
   @Override
-  public DataSinkDescription declareModel() {
+  public DataSinkBuilder declareModelWithoutSilentPeriod() {
     return DataSinkBuilder
-        .create("org.apache.streampipes.sinks.notifications.jvm.onesignal", 0)
+        .create(ONE_SIGNAL_NOTIFICATION_SINK_ID, 1)
         .withLocales(Locales.EN)
         .withAssets(Assets.DOCUMENTATION, Assets.ICON)
         .category(DataSinkType.NOTIFICATION)
@@ -65,13 +67,13 @@ public class OneSignalSink extends StreamPipesDataSink {
                             .build())
         .requiredHtmlInputParameter(Labels.withId(CONTENT_KEY))
         .requiredTextParameter(Labels.withId(APP_ID))
-        .requiredTextParameter(Labels.withId(REST_API_KEY))
-        .build();
+        .requiredTextParameter(Labels.withId(REST_API_KEY));
   }
 
   @Override
   public void onInvocation(SinkParams parameters,
                            EventSinkRuntimeContext runtimeContext) throws SpRuntimeException {
+    super.onInvocation(parameters, runtimeContext);
     var extractor = parameters.extractor();
     content = extractor.singleValueParameter(CONTENT_KEY, String.class);
     appId = extractor.singleValueParameter(APP_ID, String.class);
@@ -79,7 +81,7 @@ public class OneSignalSink extends StreamPipesDataSink {
   }
 
   @Override
-  public void onEvent(Event event) throws SpRuntimeException {
+  public void onNotificationEvent(Event event) throws SpRuntimeException{
     String jsondata =
         "{\"app_id\": \"" + appId + "\",\"contents\": {\"en\": \"" + content + "\"}, \"included_segments\":[\"All\"]}";
 
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/slack/SlackNotificationSink.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/slack/SlackNotificationSink.java
index c9e2828976..6b58c05285 100644
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/slack/SlackNotificationSink.java
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/slack/SlackNotificationSink.java
@@ -21,7 +21,6 @@ package org.apache.streampipes.sinks.notifications.jvm.slack;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.extensions.api.pe.context.EventSinkRuntimeContext;
 import org.apache.streampipes.model.DataSinkType;
-import org.apache.streampipes.model.graph.DataSinkDescription;
 import org.apache.streampipes.model.runtime.Event;
 import org.apache.streampipes.sdk.builder.DataSinkBuilder;
 import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
@@ -31,7 +30,7 @@ import org.apache.streampipes.sdk.helpers.Locales;
 import org.apache.streampipes.sdk.helpers.Options;
 import org.apache.streampipes.sdk.utils.Assets;
 import org.apache.streampipes.wrapper.params.compat.SinkParams;
-import org.apache.streampipes.wrapper.standalone.StreamPipesDataSink;
+import org.apache.streampipes.wrapper.standalone.StreamPipesNotificationSink;
 
 import com.ullink.slack.simpleslackapi.SlackChannel;
 import com.ullink.slack.simpleslackapi.SlackSession;
@@ -40,7 +39,8 @@ import com.ullink.slack.simpleslackapi.impl.SlackSessionFactory;
 
 import java.io.IOException;
 
-public class SlackNotificationSink extends StreamPipesDataSink {
+public class SlackNotificationSink extends StreamPipesNotificationSink {
+  public static final String SLACK_NOTIFICATION_SINK_ID = "org.apache.streampipes.sinks.notifications.jvm.slack";
 
   private static final String CHANNEL_TYPE = "channel-type";
   private static final String RECEIVER = "receiver";
@@ -56,10 +56,9 @@ public class SlackNotificationSink extends StreamPipesDataSink {
   private String originalMessage;
 
   @Override
-  public DataSinkDescription declareModel() {
-
+  public DataSinkBuilder declareModelWithoutSilentPeriod() {
     return DataSinkBuilder
-        .create("org.apache.streampipes.sinks.notifications.jvm.slack", 0)
+        .create(SLACK_NOTIFICATION_SINK_ID, 1)
         .withLocales(Locales.EN)
         .withAssets(Assets.DOCUMENTATION, Assets.ICON)
         .category(DataSinkType.NOTIFICATION)
@@ -71,13 +70,13 @@ public class SlackNotificationSink extends StreamPipesDataSink {
         .requiredTextParameter(Labels.withId(CONTENT), false, true)
         .requiredSingleValueSelection(Labels.withId(CHANNEL_TYPE),
                                       Options.from("User", "Channel"))
-        .requiredSecret(Labels.withId(AUTH_TOKEN))
-        .build();
+        .requiredSecret(Labels.withId(AUTH_TOKEN));
   }
 
   @Override
   public void onInvocation(SinkParams parameters,
                            EventSinkRuntimeContext runtimeContext) throws SpRuntimeException {
+    super.onInvocation(parameters, runtimeContext);
     var extractor = parameters.extractor();
 
     userChannel = extractor.singleValueParameter(RECEIVER, String.class);
@@ -110,11 +109,10 @@ public class SlackNotificationSink extends StreamPipesDataSink {
                                          + "the bot has no rights to access it");
       }
     }
-
   }
 
   @Override
-  public void onEvent(Event event) throws SpRuntimeException {
+  public void onNotificationEvent(Event event) {
     String message = replacePlaceholders(event, originalMessage);
     if (this.sendToUser) {
       this.session.sendMessageToUser(userChannel,
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/telegram/TelegramSink.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/telegram/TelegramSink.java
index 977b5fb0f4..3c09e5191a 100644
--- a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/telegram/TelegramSink.java
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/main/java/org/apache/streampipes/sinks/notifications/jvm/telegram/TelegramSink.java
@@ -21,7 +21,6 @@ package org.apache.streampipes.sinks.notifications.jvm.telegram;
 import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.extensions.api.pe.context.EventSinkRuntimeContext;
 import org.apache.streampipes.model.DataSinkType;
-import org.apache.streampipes.model.graph.DataSinkDescription;
 import org.apache.streampipes.model.runtime.Event;
 import org.apache.streampipes.sdk.builder.DataSinkBuilder;
 import org.apache.streampipes.sdk.builder.StreamRequirementsBuilder;
@@ -30,7 +29,7 @@ import org.apache.streampipes.sdk.helpers.Labels;
 import org.apache.streampipes.sdk.helpers.Locales;
 import org.apache.streampipes.sdk.utils.Assets;
 import org.apache.streampipes.wrapper.params.compat.SinkParams;
-import org.apache.streampipes.wrapper.standalone.StreamPipesDataSink;
+import org.apache.streampipes.wrapper.standalone.StreamPipesNotificationSink;
 
 import okhttp3.OkHttpClient;
 import okhttp3.Request;
@@ -42,7 +41,8 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
-public class TelegramSink extends StreamPipesDataSink {
+public class TelegramSink extends StreamPipesNotificationSink {
+  public static final String TELEGRAM_NOTIFICATION_SINK_ID = "org.apache.streampipes.sinks.notifications.jvm.telegram";
   private static final String CHANNEL_NAME_OR_CHAT_ID = "channel-chat-name";
   private static final String MESSAGE_TEXT = "message-text";
   private static final String BOT_API_KEY = "api-key";
@@ -57,9 +57,9 @@ public class TelegramSink extends StreamPipesDataSink {
   private String message;
 
   @Override
-  public DataSinkDescription declareModel() {
+  public DataSinkBuilder declareModelWithoutSilentPeriod() {
     return DataSinkBuilder
-        .create("org.apache.streampipes.sinks.notifications.jvm.telegram", 0)
+        .create(TELEGRAM_NOTIFICATION_SINK_ID, 1)
         .withLocales(Locales.EN)
         .withAssets(Assets.DOCUMENTATION, Assets.ICON)
         .category(DataSinkType.NOTIFICATION)
@@ -69,14 +69,13 @@ public class TelegramSink extends StreamPipesDataSink {
                             .build())
         .requiredSecret(Labels.withId(BOT_API_KEY))
         .requiredTextParameter(Labels.withId(CHANNEL_NAME_OR_CHAT_ID))
-        .requiredTextParameter(Labels.withId(MESSAGE_TEXT), true, true, true)
-        .build();
+        .requiredTextParameter(Labels.withId(MESSAGE_TEXT), true, true, true);
   }
 
-
   @Override
   public void onInvocation(SinkParams parameters,
                            EventSinkRuntimeContext runtimeContext) throws SpRuntimeException {
+    super.onInvocation(parameters, runtimeContext);
     var extractor = parameters.extractor();
     apiKey = extractor.secretValue(BOT_API_KEY);
     channelOrChatId = extractor.singleValueParameter(CHANNEL_NAME_OR_CHAT_ID, String.class);
@@ -84,7 +83,7 @@ public class TelegramSink extends StreamPipesDataSink {
   }
 
   @Override
-  public void onEvent(Event event) throws SpRuntimeException {
+  public void onNotificationEvent(Event event) {
     try {
       String content = replacePlaceholders(event, this.message);
       content = trimHTML(content);
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/migration/AdapterDescriptionMigration093.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/migration/AdapterDescriptionMigration093.java
deleted file mode 100644
index d10d279993..0000000000
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/migration/AdapterDescriptionMigration093.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.manager.migration;
-
-import org.apache.streampipes.commons.exceptions.SepaParseException;
-import org.apache.streampipes.manager.endpoint.HttpJsonParser;
-import org.apache.streampipes.manager.operations.Operations;
-import org.apache.streampipes.manager.util.AuthTokenUtils;
-import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceRegistration;
-import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceTagPrefix;
-import org.apache.streampipes.storage.api.IAdapterStorage;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.net.URI;
-
-import static org.apache.streampipes.manager.migration.MigrationUtils.getRequestUrl;
-
-public class AdapterDescriptionMigration093 extends AbstractMigrationManager {
-
-  private static final Logger LOG = LoggerFactory.getLogger(AdapterDescriptionMigration093.class);
-
-  private final IAdapterStorage adapterDescriptionStorage;
-
-  public AdapterDescriptionMigration093(IAdapterStorage adapterDescriptionStorage) {
-    this.adapterDescriptionStorage = adapterDescriptionStorage;
-  }
-
-  public void reinstallAdapters(SpServiceRegistration extensionsServiceConfig) {
-    var migrationProvider = AdapterDescriptionMigration093Provider.INSTANCE;
-    if (migrationProvider.hasAppIdsToReinstall()) {
-      var appIdsToReinstall = migrationProvider.getAppIdsToReinstall();
-      var serviceUrl = extensionsServiceConfig.getServiceUrl();
-      extensionsServiceConfig.getTags()
-          .stream()
-          .filter(tag -> tag.getPrefix() == SpServiceTagPrefix.ADAPTER)
-          .filter(tag -> appIdsToReinstall.contains(tag.getValue()))
-          .forEach(tag -> {
-            var appId = tag.getValue();
-            try {
-              if (adapterDescriptionStorage.getAdaptersByAppId(appId).isEmpty()) {
-                var requestUrl = getRequestUrl(SpServiceTagPrefix.ADAPTER, appId, serviceUrl);
-                var entityPayload = HttpJsonParser.getContentFromUrl(URI.create(requestUrl));
-                Operations.verifyAndAddElement(
-                    entityPayload,
-                    AuthTokenUtils.getAuthTokenForCurrentUser(),
-                    true);
-              }
-            } catch (IOException | SepaParseException e) {
-              LOG.warn("Could not reinstall adapter description {}", appId);
-            }
-          });
-    }
-  }
-}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/MigrationResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/MigrationResource.java
index abca2da422..aa3a509b80 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/MigrationResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/admin/MigrationResource.java
@@ -22,7 +22,6 @@ import org.apache.streampipes.connect.management.management.AdapterMigrationMana
 import org.apache.streampipes.manager.health.CoreInitialInstallationProgress;
 import org.apache.streampipes.manager.health.CoreServiceStatusManager;
 import org.apache.streampipes.manager.health.ServiceRegistrationManager;
-import org.apache.streampipes.manager.migration.AdapterDescriptionMigration093;
 import org.apache.streampipes.manager.migration.PipelineElementMigrationManager;
 import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceRegistration;
 import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceStatus;
@@ -64,8 +63,6 @@ public class MigrationResource extends AbstractAuthGuardedRestResource {
 
   private final CRUDStorage<String, SpServiceRegistration> extensionsServiceStorage =
       getNoSqlStorage().getExtensionsServiceStorage();
-
-  private final IAdapterStorage adapterDescriptionStorage = getNoSqlStorage().getAdapterDescriptionStorage();
   private final IAdapterStorage adapterStorage = getNoSqlStorage().getAdapterInstanceStorage();
 
   private final IDataProcessorStorage dataProcessorStorage = getNoSqlStorage().getDataProcessorStorage();
@@ -104,13 +101,12 @@ public class MigrationResource extends AbstractAuthGuardedRestResource {
     try {
       var extensionsServiceConfig = serviceManager.getService(serviceId);
       if (!CoreInitialInstallationProgress.INSTANCE.isInitiallyInstalling()) {
-        new AdapterDescriptionMigration093(adapterDescriptionStorage).reinstallAdapters(extensionsServiceConfig);
         if (!migrationConfigs.isEmpty()) {
           var anyServiceMigrating = serviceManager.isAnyServiceMigrating();
           var coreReady = isCoreReady();
           if (anyServiceMigrating || !coreReady) {
             LOG.info(
-                "Refusing migration request since precondition is not met (anyServiceMigratione={}, coreReady={}.",
+                "Refusing migration request since precondition is not met (anyServiceMigrating={}, coreReady={}.",
                 anyServiceMigrating,
                 coreReady
             );
diff --git a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/PostStartupTask.java b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/PostStartupTask.java
index 76ba815dcc..8e042c72f6 100644
--- a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/PostStartupTask.java
+++ b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/PostStartupTask.java
@@ -20,6 +20,7 @@ package org.apache.streampipes.service.core;
 
 import org.apache.streampipes.commons.prometheus.adapter.AdapterMetricsManager;
 import org.apache.streampipes.connect.management.management.WorkerAdministrationManagement;
+import org.apache.streampipes.manager.health.ServiceHealthCheck;
 import org.apache.streampipes.manager.operations.Operations;
 import org.apache.streampipes.model.extensions.svcdiscovery.SpServiceTagPrefix;
 import org.apache.streampipes.model.pipeline.Pipeline;
@@ -65,6 +66,7 @@ public class PostStartupTask implements Runnable {
 
   @Override
   public void run() {
+    new ServiceHealthCheck().run();
     performAdapterAssetUpdate();
     startAllPreviouslyStoppedPipelines();
     startAdapters();
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
index 473e8d1ca6..a87b0fabff 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
@@ -38,8 +38,6 @@ public interface INoSqlStorage {
 
   IUserStorage getUserStorageAPI();
 
-  IPipelineMonitoringDataStorage getMonitoringDataStorageApi();
-
   INotificationStorage getNotificationStorageApi();
 
   IPipelineCategoryStorage getPipelineCategoryStorageApi();
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
index 1ae99a5527..87886fc7c9 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
@@ -42,7 +42,6 @@ import org.apache.streampipes.storage.api.IPipelineCategoryStorage;
 import org.apache.streampipes.storage.api.IPipelineElementConnectionStorage;
 import org.apache.streampipes.storage.api.IPipelineElementDescriptionStorage;
 import org.apache.streampipes.storage.api.IPipelineElementTemplateStorage;
-import org.apache.streampipes.storage.api.IPipelineMonitoringDataStorage;
 import org.apache.streampipes.storage.api.IPipelineStorage;
 import org.apache.streampipes.storage.api.ISpCoreConfigurationStorage;
 import org.apache.streampipes.storage.api.IUserActivationTokenStorage;
@@ -68,7 +67,6 @@ import org.apache.streampipes.storage.couchdb.impl.ExtensionsServiceStorageImpl;
 import org.apache.streampipes.storage.couchdb.impl.FileMetadataStorageImpl;
 import org.apache.streampipes.storage.couchdb.impl.GenericStorageImpl;
 import org.apache.streampipes.storage.couchdb.impl.ImageStorageImpl;
-import org.apache.streampipes.storage.couchdb.impl.MonitoringDataStorageImpl;
 import org.apache.streampipes.storage.couchdb.impl.NotificationStorageImpl;
 import org.apache.streampipes.storage.couchdb.impl.PasswordRecoveryTokenImpl;
 import org.apache.streampipes.storage.couchdb.impl.PermissionStorageImpl;
@@ -126,11 +124,6 @@ public enum CouchDbStorageManager implements INoSqlStorage {
     return new UserStorage();
   }
 
-  @Override
-  public IPipelineMonitoringDataStorage getMonitoringDataStorageApi() {
-    return new MonitoringDataStorageImpl();
-  }
-
   @Override
   public INotificationStorage getNotificationStorageApi() {
     return new NotificationStorageImpl();
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/MonitoringDataStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/MonitoringDataStorageImpl.java
deleted file mode 100644
index 1b51d44f24..0000000000
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/MonitoringDataStorageImpl.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.streampipes.storage.couchdb.impl;
-
-import org.apache.streampipes.model.client.monitoring.JobReport;
-import org.apache.streampipes.storage.api.IPipelineMonitoringDataStorage;
-import org.apache.streampipes.storage.couchdb.dao.AbstractDao;
-import org.apache.streampipes.storage.couchdb.utils.Utils;
-
-import java.util.Comparator;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public class MonitoringDataStorageImpl extends AbstractDao<JobReport> implements IPipelineMonitoringDataStorage {
-
-  public MonitoringDataStorageImpl() {
-    super(Utils::getCouchDbMonitoringClient, JobReport.class);
-  }
-
-  @Override
-  public List<JobReport> getAllMonitoringJobReports() {
-    return findAll();
-  }
-
-  @Override
-  public List<JobReport> getAllMonitoringJobReportsByElement(String elementUri) {
-    List<JobReport> allReports = findAll();
-    return getJobReportStream(elementUri, allReports)
-        .collect(Collectors.toList());
-  }
-
-  private Stream<JobReport> getJobReportStream(String elementUri, List<JobReport> allReports) {
-    return allReports
-        .stream()
-        .filter(r -> r.getElementId().equals(elementUri));
-  }
-
-  @Override
-  public JobReport getLatestJobReport(String elementUri) {
-    List<JobReport> allReports = findAll();
-    return getJobReportStream(elementUri, allReports)
-        .sorted(Comparator.comparing(JobReport::getGenerationDate))
-        .findFirst()
-        .get();
-  }
-
-  @Override
-  public boolean storeJobReport(JobReport jobReport) {
-    return persist(jobReport).k;
-  }
-
-}
diff --git a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/StreamPipesNotificationSink.java b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/StreamPipesNotificationSink.java
index 6d3a6d891a..eaa0917287 100644
--- a/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/StreamPipesNotificationSink.java
+++ b/streampipes-wrapper-standalone/src/main/java/org/apache/streampipes/wrapper/standalone/StreamPipesNotificationSink.java
@@ -41,12 +41,12 @@ public abstract class StreamPipesNotificationSink extends StreamPipesDataSink {
   /**
    * Default waiting time in minutes between two consecutive notifications.
    */
-  private static final int DEFAULT_WAITING_TIME_MINUTES = 10;
+  public static final int DEFAULT_WAITING_TIME_MINUTES = 10;
 
   /**
    * Key for the silent period parameter.
    */
-  private static final String KEY_SILENT_PERIOD = "silentPeriod";
+  public static final String KEY_SILENT_PERIOD = "silentPeriod";
 
   /**
    * The epoch second of the last message sent.


Test patch:
diff --git a/streampipes-extensions/streampipes-sinks-notifications-jvm/src/test/java/org/apache/streampipes/sinks/notifications/jvm/migrations/INotificationDataSinkMigratorTest.java b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/test/java/org/apache/streampipes/sinks/notifications/jvm/migrations/INotificationDataSinkMigratorTest.java
new file mode 100644
index 0000000000..319f993b8b
--- /dev/null
+++ b/streampipes-extensions/streampipes-sinks-notifications-jvm/src/test/java/org/apache/streampipes/sinks/notifications/jvm/migrations/INotificationDataSinkMigratorTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.sinks.notifications.jvm.migrations;
+
+import org.apache.streampipes.extensions.api.extractor.IDataSinkParameterExtractor;
+import org.apache.streampipes.model.graph.DataSinkInvocation;
+import org.apache.streampipes.model.migration.MigrationResult;
+import org.apache.streampipes.model.staticproperty.FreeTextStaticProperty;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+import static org.apache.streampipes.wrapper.standalone.StreamPipesNotificationSink.DEFAULT_WAITING_TIME_MINUTES;
+import static org.apache.streampipes.wrapper.standalone.StreamPipesNotificationSink.KEY_SILENT_PERIOD;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+public class INotificationDataSinkMigratorTest {
+
+  @Test
+  public void testNotificationDataSinkMigration() {
+
+    INotificationDataSinkMigrator migrator = spy(INotificationDataSinkMigrator.class);
+    IDataSinkParameterExtractor extractor = mock(IDataSinkParameterExtractor.class);
+
+    DataSinkInvocation dataSinkInvocation = new DataSinkInvocation();
+    dataSinkInvocation.setStaticProperties(new ArrayList<>());
+
+    MigrationResult<DataSinkInvocation> result = migrator.migrate(dataSinkInvocation, extractor);
+
+    assertEquals(1, result.element().getStaticProperties().size());
+
+    var property = (FreeTextStaticProperty) result.element().getStaticProperties().get(0);
+    assertEquals(KEY_SILENT_PERIOD, property.getInternalName());
+    assertEquals(DEFAULT_WAITING_TIME_MINUTES, Integer.valueOf(property.getValue()).intValue());
+  }
+}
\ No newline at end of file