mirror of
https://github.com/danieldemus/openhab-core.git
synced 2026-07-29 12:34:22 +02:00
Persistence no default strategies and persistence configuration health check (#4682)
* no default strategy and persistence health * upgradetool Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
This commit is contained in:
+84
-17
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.core.io.rest.core.internal.persistence;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
@@ -44,11 +45,13 @@ import javax.ws.rs.core.UriInfo;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.rest.JSONResponse;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.openhab.core.io.rest.core.config.ConfigurationService;
|
||||
import org.openhab.core.items.Item;
|
||||
import org.openhab.core.items.ItemNotFoundException;
|
||||
import org.openhab.core.items.ItemRegistry;
|
||||
@@ -63,12 +66,13 @@ import org.openhab.core.persistence.PersistenceItemConfiguration;
|
||||
import org.openhab.core.persistence.PersistenceItemInfo;
|
||||
import org.openhab.core.persistence.PersistenceManager;
|
||||
import org.openhab.core.persistence.PersistenceService;
|
||||
import org.openhab.core.persistence.PersistenceServiceProblem;
|
||||
import org.openhab.core.persistence.PersistenceServiceRegistry;
|
||||
import org.openhab.core.persistence.QueryablePersistenceService;
|
||||
import org.openhab.core.persistence.config.PersistenceAllConfig;
|
||||
import org.openhab.core.persistence.dto.ItemHistoryDTO;
|
||||
import org.openhab.core.persistence.dto.PersistenceServiceConfigurationDTO;
|
||||
import org.openhab.core.persistence.dto.PersistenceServiceDTO;
|
||||
import org.openhab.core.persistence.dto.PersistenceStrategyDTO;
|
||||
import org.openhab.core.persistence.registry.ManagedPersistenceServiceConfigurationProvider;
|
||||
import org.openhab.core.persistence.registry.PersistenceServiceConfiguration;
|
||||
import org.openhab.core.persistence.registry.PersistenceServiceConfigurationDTOMapper;
|
||||
@@ -109,6 +113,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
|
||||
* @author Wouter Born - Migrated to OpenAPI annotations
|
||||
* @author Mark Herwege - Implement aliases
|
||||
* @author Mark Herwege - Make default strategy to be only a configuration suggestion
|
||||
*/
|
||||
@Component
|
||||
@JaxrsResource
|
||||
@@ -136,6 +141,7 @@ public class PersistenceResource implements RESTResource {
|
||||
private final PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry;
|
||||
private final ManagedPersistenceServiceConfigurationProvider managedPersistenceServiceConfigurationProvider;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
private final ConfigurationService configurationService;
|
||||
|
||||
@Activate
|
||||
public PersistenceResource( //
|
||||
@@ -145,7 +151,8 @@ public class PersistenceResource implements RESTResource {
|
||||
final @Reference PersistenceManager persistenceManager,
|
||||
final @Reference PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry,
|
||||
final @Reference ManagedPersistenceServiceConfigurationProvider managedPersistenceServiceConfigurationProvider,
|
||||
final @Reference TimeZoneProvider timeZoneProvider) {
|
||||
final @Reference TimeZoneProvider timeZoneProvider,
|
||||
final @Reference ConfigurationService configurationService) {
|
||||
this.itemRegistry = itemRegistry;
|
||||
this.localeService = localeService;
|
||||
this.persistenceServiceRegistry = persistenceServiceRegistry;
|
||||
@@ -153,6 +160,7 @@ public class PersistenceResource implements RESTResource {
|
||||
this.persistenceServiceConfigurationRegistry = persistenceServiceConfigurationRegistry;
|
||||
this.managedPersistenceServiceConfigurationProvider = managedPersistenceServiceConfigurationProvider;
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.configurationService = configurationService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -180,25 +188,11 @@ public class PersistenceResource implements RESTResource {
|
||||
public Response httpGetPersistenceServiceConfiguration(@Context HttpHeaders headers,
|
||||
@Parameter(description = "Id of the persistence service.") @PathParam("serviceId") String serviceId) {
|
||||
PersistenceServiceConfiguration configuration = persistenceServiceConfigurationRegistry.get(serviceId);
|
||||
boolean editable = managedPersistenceServiceConfigurationProvider.get(serviceId) != null;
|
||||
|
||||
if (configuration == null) {
|
||||
PersistenceService service = persistenceServiceRegistry.get(serviceId);
|
||||
if (service != null) {
|
||||
List<PersistenceStrategy> strategies = service.getDefaultStrategies();
|
||||
List<PersistenceItemConfiguration> configs = List
|
||||
.of(new PersistenceItemConfiguration(List.of(new PersistenceAllConfig()), strategies, null));
|
||||
Map<String, String> aliases = Map.of();
|
||||
configuration = new PersistenceServiceConfiguration(serviceId, configs, aliases, strategies, strategies,
|
||||
List.of());
|
||||
editable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (configuration != null) {
|
||||
PersistenceServiceConfigurationDTO configurationDTO = PersistenceServiceConfigurationDTOMapper
|
||||
.map(configuration);
|
||||
configurationDTO.editable = editable;
|
||||
configurationDTO.editable = managedPersistenceServiceConfigurationProvider.get(serviceId) != null;
|
||||
return JSONResponse.createResponse(Status.OK, configurationDTO, null);
|
||||
} else {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
@@ -345,6 +339,79 @@ public class PersistenceResource implements RESTResource {
|
||||
return putItemState(serviceId, itemName, value, time);
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Path("strategysuggestions")
|
||||
@Operation(operationId = "getPersistenceServiceStrategySuggestions", summary = "Gets a persistence service suggested strategies.", security = {
|
||||
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = PersistenceStrategyDTO.class), uniqueItems = true))),
|
||||
@ApiResponse(responseCode = "404", description = "Suggested strategies not found.") })
|
||||
public Response httpGetPersistenceServiceStrategySuggestions(@Context HttpHeaders headers,
|
||||
@Parameter(description = "Id of the persistence service.") @QueryParam("serviceId") String serviceId) {
|
||||
PersistenceService service = persistenceServiceRegistry.get(serviceId);
|
||||
if (service != null) {
|
||||
return JSONResponse.createResponse(Status.OK, service.getSuggestedStrategies(), null);
|
||||
}
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Path("persistencehealth")
|
||||
@Operation(operationId = "getPersistenceHealth", summary = "Gets configuration problems with persistence services.", security = {
|
||||
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = PersistenceServiceProblem.class), uniqueItems = true))) })
|
||||
public Response httpGetPersistenceHealth(@Context HttpHeaders headers) {
|
||||
List<PersistenceServiceProblem> persistenceProblems = new ArrayList<>();
|
||||
Set<PersistenceService> persistenceServices = persistenceServiceRegistry.getAll();
|
||||
|
||||
if (persistenceServices.size() > 1) {
|
||||
try {
|
||||
Configuration configuration = configurationService.get("org.openhab.persistence");
|
||||
if (configuration == null || configuration.get("default") == null) {
|
||||
persistenceProblems.add(new PersistenceServiceProblem(
|
||||
PersistenceServiceProblem.PERSISTENCE_NO_DEFAULT, null, null, true));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warn("Unable to retrieve configuration for 'org.openhab.persistence': {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
for (PersistenceService service : persistenceServices) {
|
||||
String serviceId = service.getId();
|
||||
PersistenceServiceConfiguration serviceConfig = persistenceServiceConfigurationRegistry.get(serviceId);
|
||||
if (serviceConfig == null) {
|
||||
persistenceProblems.add(new PersistenceServiceProblem(PersistenceServiceProblem.PERSISTENCE_NO_CONFIG,
|
||||
serviceId, null, true));
|
||||
} else {
|
||||
boolean editable = managedPersistenceServiceConfigurationProvider.get(serviceId) != null;
|
||||
List<PersistenceItemConfiguration> configs = serviceConfig.getConfigs();
|
||||
if (configs.isEmpty()) {
|
||||
persistenceProblems.add(new PersistenceServiceProblem(
|
||||
PersistenceServiceProblem.PERSISTENCE_NO_ITEMS, serviceId, null, editable));
|
||||
} else {
|
||||
for (PersistenceItemConfiguration config : configs) {
|
||||
List<PersistenceStrategy> strategies = config.strategies();
|
||||
List<String> items = config.items().stream()
|
||||
.map(PersistenceServiceConfigurationDTOMapper::persistenceConfigToString).toList();
|
||||
if (strategies.isEmpty()) {
|
||||
persistenceProblems.add(new PersistenceServiceProblem(
|
||||
PersistenceServiceProblem.PERSISTENCE_NO_STRATEGY, serviceId, items, editable));
|
||||
} else if (strategies.size() == 1
|
||||
&& PersistenceStrategy.Globals.RESTORE.equals(strategies.get(0))) {
|
||||
persistenceProblems.add(new PersistenceServiceProblem(
|
||||
PersistenceServiceProblem.PERSISTENCE_NO_STORE_STRATEGY, serviceId, items,
|
||||
editable));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return JSONResponse.createResponse(Status.OK, persistenceProblems, null);
|
||||
}
|
||||
|
||||
private ZonedDateTime convertTime(String sTime) {
|
||||
DateTimeType dateTime = new DateTimeType(sTime);
|
||||
return dateTime.getZonedDateTime(timeZoneProvider.getTimeZone());
|
||||
|
||||
+6
-3
@@ -12,11 +12,12 @@
|
||||
*/
|
||||
package org.openhab.core.io.rest.core.internal.persistence;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.time.ZoneId;
|
||||
@@ -36,6 +37,7 @@ import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.core.config.ConfigurationService;
|
||||
import org.openhab.core.items.Item;
|
||||
import org.openhab.core.items.ItemNotFoundException;
|
||||
import org.openhab.core.items.ItemRegistry;
|
||||
@@ -77,13 +79,14 @@ public class PersistenceResourceTest {
|
||||
private @Mock @NonNullByDefault({}) PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistryMock;
|
||||
private @Mock @NonNullByDefault({}) ManagedPersistenceServiceConfigurationProvider managedPersistenceServiceConfigurationProviderMock;
|
||||
private @Mock @NonNullByDefault({}) TimeZoneProvider timeZoneProviderMock;
|
||||
private @Mock @NonNullByDefault({}) ConfigurationService configurationServiceMock;
|
||||
private @Mock @NonNullByDefault({}) Item itemMock;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
pResource = new PersistenceResource(itemRegistryMock, localeServiceMock, persistenceServiceRegistryMock,
|
||||
persistenceManagerMock, persistenceServiceConfigurationRegistryMock,
|
||||
managedPersistenceServiceConfigurationProviderMock, timeZoneProviderMock);
|
||||
managedPersistenceServiceConfigurationProviderMock, timeZoneProviderMock, configurationServiceMock);
|
||||
|
||||
int startValue = 2016;
|
||||
int endValue = 2018;
|
||||
|
||||
+2
-5
@@ -6,9 +6,7 @@ generate persistence "https://openhab.org/model/Persistence"
|
||||
|
||||
PersistenceModel:
|
||||
{PersistenceModel}
|
||||
('Strategies' '{' strategies+=Strategy*
|
||||
('default' '=' defaults+=[Strategy|ID] (',' defaults+=[Strategy|ID])*)?
|
||||
'}')?
|
||||
('Strategies' '{' strategies+=Strategy* '}')?
|
||||
('Filters' '{' filters+=Filter* '}')?
|
||||
('Items' '{' configs+=PersistenceConfiguration* '}')?
|
||||
('Aliases' '{' aliases+=AliasConfiguration* '}')?
|
||||
@@ -59,9 +57,8 @@ NotIncludeFilter:
|
||||
PersistenceConfiguration:
|
||||
items+=(AllConfig | ItemConfig | GroupConfig | ItemExcludeConfig | GroupExcludeConfig)
|
||||
(',' items+=(AllConfig | ItemConfig | GroupConfig | ItemExcludeConfig | GroupExcludeConfig))*
|
||||
((':' ('strategy' '=' strategies+=[Strategy|ID] (',' strategies+=[Strategy|ID])*)?
|
||||
(':' ('strategy' '=' strategies+=[Strategy|ID] (',' strategies+=[Strategy|ID])*)
|
||||
('filter' '=' filters+=[Filter|ID] (',' filters+=[Filter|ID])*)?)
|
||||
| ';')
|
||||
;
|
||||
|
||||
AllConfig:
|
||||
|
||||
+1
-2
@@ -116,8 +116,7 @@ public class PersistenceModelManager extends AbstractProvider<PersistenceService
|
||||
if (model != null) {
|
||||
PersistenceServiceConfiguration newConfiguration = new PersistenceServiceConfiguration(serviceName,
|
||||
mapConfigs(model.getConfigs()), mapAliases(model.getAliases()),
|
||||
mapStrategies(model.getDefaults()), mapStrategies(model.getStrategies()),
|
||||
mapFilters(model.getFilters()));
|
||||
mapStrategies(model.getStrategies()), mapFilters(model.getFilters()));
|
||||
PersistenceServiceConfiguration oldConfiguration = configurations.put(serviceName,
|
||||
newConfiguration);
|
||||
if (oldConfiguration == null) {
|
||||
|
||||
+2
-3
@@ -14,12 +14,11 @@ package org.openhab.core.persistence;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.items.Item;
|
||||
import org.openhab.core.persistence.internal.PersistenceManagerImpl;
|
||||
|
||||
/**
|
||||
* The {@link PersistenceManager} interface is used to communicate between external components (e.g. REST interface)
|
||||
* that modify persisted data bypassing the {@link PersistenceManagerImpl}. This is required because forecast jobs might
|
||||
* need an update when the persisted data changes.
|
||||
* that modify persisted data bypassing the {@link org.openhab.core.persistence.internal.PersistenceManagerImpl}. This
|
||||
* is required because forecast jobs might need an update when the persisted data changes.
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
|
||||
+18
-2
@@ -27,6 +27,7 @@ import org.openhab.core.persistence.strategy.PersistenceStrategy;
|
||||
* for sending data to an IoT (Internet of Things) service.
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Mark Herwege - Make default strategy to be only a configuration suggestion
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface PersistenceService {
|
||||
@@ -76,7 +77,22 @@ public interface PersistenceService {
|
||||
/**
|
||||
* Provides default persistence strategies that are used for all items if no user defined configuration is found.
|
||||
*
|
||||
* @return The default persistence strategies
|
||||
* This method has been deprecated and {@link #getSuggestedStrategies()} should be used instead. These
|
||||
* persistence strategies are no longer applied automatically.
|
||||
*
|
||||
* @return The suggested persistence strategies
|
||||
*/
|
||||
List<PersistenceStrategy> getDefaultStrategies();
|
||||
@Deprecated
|
||||
default List<PersistenceStrategy> getDefaultStrategies() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides suggested persistence strategies that can be used in the UI as a suggestion for configuration.
|
||||
*
|
||||
* @return The suggested persistence strategies
|
||||
*/
|
||||
default List<PersistenceStrategy> getSuggestedStrategies() {
|
||||
return getDefaultStrategies();
|
||||
}
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.core.persistence;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This is a representation of a persistence service configuration problem.
|
||||
*
|
||||
* @param reason description for the persistence configuration problem, free text, but one of the public constants can
|
||||
* be used to allow the consumer (e.g. UI) to tailor the message.
|
||||
* @param serviceId persistence service
|
||||
* @param items list of persistence item definitions
|
||||
* @param editable true if this is a managed service
|
||||
*
|
||||
* @author Mark Herwege - Persistence health API endpoint
|
||||
*/
|
||||
public record PersistenceServiceProblem(String reason, @Nullable String serviceId, @Nullable List<String> items,
|
||||
boolean editable) {
|
||||
|
||||
// Reasons for persistence configuration problems.
|
||||
// If one of these constants is used as reason, the UI can use these values to give a more descriptive message.
|
||||
public static final String PERSISTENCE_NO_DEFAULT = "PERSISTENCE_NO_DEFAULT";
|
||||
public static final String PERSISTENCE_NO_CONFIG = "PERSISTENCE_SERVICE_NO_CONFIG";
|
||||
public static final String PERSISTENCE_NO_ITEMS = "PERSISTENCE_SERVICE_NO_ITEMS";
|
||||
public static final String PERSISTENCE_NO_STRATEGY = "PERSISTENCE_SERVICE_ITEMS_NO_STRATEGY";
|
||||
public static final String PERSISTENCE_NO_STORE_STRATEGY = "PERSISTENCE_SERVICE_ITEMS_NO_STORE_STRATEGY";
|
||||
}
|
||||
+9
-1
@@ -17,18 +17,26 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link PersistenceServiceConfigurationDTO} is used for transferring persistence service configurations
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
* @author Mark Herwege - Make default strategy to be only a configuration suggestion
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PersistenceServiceConfigurationDTO {
|
||||
public String serviceId = "";
|
||||
public Collection<PersistenceItemConfigurationDTO> configs = List.of();
|
||||
public Map<String, String> aliases = Map.of();
|
||||
public Collection<String> defaults = List.of();
|
||||
/**
|
||||
* @deprecated This field is kept to enable migration from previous version storage.
|
||||
* It should not be removed as this would make automatic upgrading persistence configurations from an
|
||||
* older version impossible.
|
||||
*/
|
||||
@Deprecated
|
||||
public @Nullable Collection<String> defaults;
|
||||
public Collection<PersistenceCronStrategyDTO> cronStrategies = List.of();
|
||||
public Collection<PersistenceFilterDTO> thresholdFilters = List.of();
|
||||
public Collection<PersistenceFilterDTO> timeFilters = List.of();
|
||||
|
||||
+10
-16
@@ -92,6 +92,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Jan N. Klug - Refactored to use service configuration registry
|
||||
* @author Jan N. Klug - Added time series support
|
||||
* @author Mark Herwege - Added restoring lastState, lastStateChange and lastStateUpdate
|
||||
* @author Mark Herwege - Make default strategy to be only a configuration suggestion
|
||||
*/
|
||||
@Component(immediate = true, service = PersistenceManager.class)
|
||||
@NonNullByDefault
|
||||
@@ -461,7 +462,7 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, State
|
||||
public PersistenceServiceContainer(PersistenceService persistenceService,
|
||||
@Nullable PersistenceServiceConfiguration configuration) {
|
||||
this.persistenceService = persistenceService;
|
||||
this.configuration = Objects.requireNonNullElseGet(configuration, this::getDefaultConfig);
|
||||
this.configuration = Objects.requireNonNullElseGet(configuration, this::getEmptyConfig);
|
||||
}
|
||||
|
||||
public PersistenceService getPersistenceService() {
|
||||
@@ -471,13 +472,13 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, State
|
||||
/**
|
||||
* Set a new configuration for this persistence service (also cancels all cron jobs)
|
||||
*
|
||||
* @param configuration the new {@link PersistenceServiceConfiguration}, if {@code null} the default
|
||||
* configuration of the service is used
|
||||
* @param configuration the new {@link PersistenceServiceConfiguration}, if {@code null} all configuration will
|
||||
* be removed
|
||||
*/
|
||||
public void setConfiguration(@Nullable PersistenceServiceConfiguration configuration) {
|
||||
cancelPersistJobs();
|
||||
cancelForecastJobs();
|
||||
this.configuration = Objects.requireNonNullElseGet(configuration, this::getDefaultConfig);
|
||||
this.configuration = Objects.requireNonNullElseGet(configuration, this::getEmptyConfig);
|
||||
strategyCache.clear();
|
||||
}
|
||||
|
||||
@@ -489,25 +490,18 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, State
|
||||
*/
|
||||
public Stream<PersistenceItemConfiguration> getMatchingConfigurations(PersistenceStrategy strategy) {
|
||||
return Objects.requireNonNull(strategyCache.computeIfAbsent(strategy, s -> {
|
||||
boolean matchesDefaultStrategies = configuration.getDefaults().contains(strategy);
|
||||
return configuration.getConfigs().stream()
|
||||
.filter(itemConfig -> itemConfig.strategies().contains(strategy)
|
||||
|| (itemConfig.strategies().isEmpty() && matchesDefaultStrategies))
|
||||
.toList();
|
||||
}).stream());
|
||||
.filter(itemConfig -> itemConfig.strategies().contains(strategy)).toList();
|
||||
})).stream();
|
||||
}
|
||||
|
||||
public @Nullable String getAlias(Item item) {
|
||||
return configuration.getAliases().get(item.getName());
|
||||
}
|
||||
|
||||
private PersistenceServiceConfiguration getDefaultConfig() {
|
||||
List<PersistenceStrategy> strategies = persistenceService.getDefaultStrategies();
|
||||
List<PersistenceItemConfiguration> configs = List
|
||||
.of(new PersistenceItemConfiguration(List.of(new PersistenceAllConfig()), strategies, null));
|
||||
Map<String, String> aliases = Map.of();
|
||||
return new PersistenceServiceConfiguration(persistenceService.getId(), configs, aliases, strategies,
|
||||
strategies, List.of());
|
||||
private PersistenceServiceConfiguration getEmptyConfig() {
|
||||
return new PersistenceServiceConfiguration(persistenceService.getId(), List.of(), Map.of(), List.of(),
|
||||
List.of());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-13
@@ -27,23 +27,22 @@ import org.openhab.core.persistence.strategy.PersistenceStrategy;
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
* @author Mark Herwege - Implement aliases
|
||||
* @author Mark Herwege - Make default strategy to be only a configuration suggestion
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PersistenceServiceConfiguration implements Identifiable<String> {
|
||||
private final String serviceId;
|
||||
private final List<PersistenceItemConfiguration> configs;
|
||||
private final Map<String, String> aliases;
|
||||
private final List<PersistenceStrategy> defaults;
|
||||
private final List<PersistenceStrategy> strategies;
|
||||
private final List<PersistenceFilter> filters;
|
||||
|
||||
public PersistenceServiceConfiguration(String serviceId, Collection<PersistenceItemConfiguration> configs,
|
||||
Map<String, String> aliases, Collection<PersistenceStrategy> defaults,
|
||||
Collection<PersistenceStrategy> strategies, Collection<PersistenceFilter> filters) {
|
||||
Map<String, String> aliases, Collection<PersistenceStrategy> strategies,
|
||||
Collection<PersistenceFilter> filters) {
|
||||
this.serviceId = serviceId;
|
||||
this.configs = List.copyOf(configs);
|
||||
this.aliases = Map.copyOf(aliases);
|
||||
this.defaults = List.copyOf(defaults);
|
||||
this.strategies = List.copyOf(strategies);
|
||||
this.filters = List.copyOf(filters);
|
||||
}
|
||||
@@ -71,15 +70,6 @@ public class PersistenceServiceConfiguration implements Identifiable<String> {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default strategies.
|
||||
*
|
||||
* @return an unmodifiable list of the default strategies
|
||||
*/
|
||||
public List<PersistenceStrategy> getDefaults() {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all defined strategies.
|
||||
*
|
||||
|
||||
+3
-7
@@ -47,6 +47,7 @@ import org.openhab.core.persistence.strategy.PersistenceStrategy;
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
* @author Mark Herwege - Implement aliases
|
||||
* @author Mark Herwege - Make default strategy to be only a configuration suggestion
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PersistenceServiceConfigurationDTOMapper {
|
||||
@@ -62,8 +63,6 @@ public class PersistenceServiceConfigurationDTOMapper {
|
||||
dto.configs = persistenceServiceConfiguration.getConfigs().stream()
|
||||
.map(PersistenceServiceConfigurationDTOMapper::mapPersistenceItemConfig).toList();
|
||||
dto.aliases = Map.copyOf(persistenceServiceConfiguration.getAliases());
|
||||
dto.defaults = persistenceServiceConfiguration.getDefaults().stream().map(PersistenceStrategy::getName)
|
||||
.toList();
|
||||
dto.cronStrategies = filterList(persistenceServiceConfiguration.getStrategies(), PersistenceCronStrategy.class,
|
||||
PersistenceServiceConfigurationDTOMapper::mapPersistenceCronStrategy);
|
||||
dto.thresholdFilters = filterList(persistenceServiceConfiguration.getFilters(),
|
||||
@@ -92,9 +91,6 @@ public class PersistenceServiceConfigurationDTOMapper {
|
||||
.map(f -> new PersistenceIncludeFilter(f.name, f.lower, f.upper, f.unit, f.inverted)))
|
||||
.flatMap(Function.identity()).collect(Collectors.toMap(PersistenceFilter::getName, e -> e));
|
||||
|
||||
List<PersistenceStrategy> defaults = dto.defaults.stream()
|
||||
.map(str -> stringToPersistenceStrategy(str, strategyMap, dto.serviceId)).toList();
|
||||
|
||||
List<PersistenceItemConfiguration> configs = dto.configs.stream().map(config -> {
|
||||
List<PersistenceConfig> items = config.items.stream()
|
||||
.map(PersistenceServiceConfigurationDTOMapper::stringToPersistenceConfig).toList();
|
||||
@@ -107,7 +103,7 @@ public class PersistenceServiceConfigurationDTOMapper {
|
||||
|
||||
Map<String, String> aliases = Map.copyOf(dto.aliases);
|
||||
|
||||
return new PersistenceServiceConfiguration(dto.serviceId, configs, aliases, defaults, strategyMap.values(),
|
||||
return new PersistenceServiceConfiguration(dto.serviceId, configs, aliases, strategyMap.values(),
|
||||
filterMap.values());
|
||||
}
|
||||
|
||||
@@ -154,7 +150,7 @@ public class PersistenceServiceConfigurationDTOMapper {
|
||||
throw new IllegalArgumentException("Filter '" + string + "' unknown for service '" + serviceId + "'");
|
||||
}
|
||||
|
||||
private static String persistenceConfigToString(PersistenceConfig config) {
|
||||
public static String persistenceConfigToString(PersistenceConfig config) {
|
||||
if (config instanceof PersistenceAllConfig) {
|
||||
return "*";
|
||||
} else if (config instanceof PersistenceGroupConfig persistenceGroupConfig) {
|
||||
|
||||
+1
-2
@@ -14,12 +14,11 @@ package org.openhab.core.persistence.registry;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.common.registry.Registry;
|
||||
import org.openhab.core.persistence.internal.PersistenceManagerImpl;
|
||||
|
||||
/**
|
||||
* The {@link PersistenceServiceConfigurationRegistry} is the central place to store persistence service configurations.
|
||||
* Configurations are registered through {@link PersistenceServiceConfigurationProvider}.
|
||||
* Because the {@link PersistenceManagerImpl} implementation needs to listen to
|
||||
* Because the {@link org.openhab.core.persistence.internal.PersistenceManagerImpl} implementation needs to listen to
|
||||
* different registries, the {@link PersistenceServiceConfigurationRegistryChangeListener} can be used to add listeners
|
||||
* to this registry.
|
||||
*
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public class TestCachedValuesPersistenceService implements ModifiablePersistence
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PersistenceStrategy> getDefaultStrategies() {
|
||||
public List<PersistenceStrategy> getSuggestedStrategies() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -231,7 +231,7 @@ public class TestPersistenceService implements QueryablePersistenceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PersistenceStrategy> getDefaultStrategies() {
|
||||
public List<PersistenceStrategy> getSuggestedStrategies() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -13,8 +13,7 @@
|
||||
package org.openhab.core.persistence.filter;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -47,9 +46,8 @@ import org.openhab.core.types.State;
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@NonNullByDefault
|
||||
public class PersistenceEqualsFilterTest {
|
||||
private static final String ITEM_NAME = "itemName";
|
||||
|
||||
private @NonNullByDefault({}) @Mock GenericItem item;
|
||||
private @Mock @NonNullByDefault({}) GenericItem item;
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("argumentProvider")
|
||||
|
||||
+2
-3
@@ -13,7 +13,7 @@
|
||||
package org.openhab.core.persistence.filter;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -42,9 +42,8 @@ import org.openhab.core.types.State;
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@NonNullByDefault
|
||||
public class PersistenceIncludeFilterTest {
|
||||
private static final String ITEM_NAME = "itemName";
|
||||
|
||||
private @NonNullByDefault({}) @Mock GenericItem item;
|
||||
private @Mock @NonNullByDefault({}) GenericItem item;
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("argumentProvider")
|
||||
|
||||
+2
-2
@@ -574,7 +574,7 @@ public class PersistenceManagerTest {
|
||||
: List.of(strategy);
|
||||
|
||||
PersistenceServiceConfiguration serviceConfiguration = new PersistenceServiceConfiguration(serviceId,
|
||||
List.of(itemConfiguration), Map.of(), List.of(), strategies, filters);
|
||||
List.of(itemConfiguration), Map.of(), strategies, filters);
|
||||
manager.added(serviceConfiguration);
|
||||
|
||||
return serviceConfiguration;
|
||||
@@ -625,7 +625,7 @@ public class PersistenceManagerTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PersistenceStrategy> getDefaultStrategies() {
|
||||
public List<PersistenceStrategy> getSuggestedStrategies() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
<artifactId>org.openhab.core.thing</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.core.bundles</groupId>
|
||||
<artifactId>org.openhab.core.persistence</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.core.bundles</groupId>
|
||||
<artifactId>org.openhab.core.storage.json</artifactId>
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
* @author Jimmy Tanagra - Refactor upgraders into individual classes
|
||||
* @author Mark Herwege - Added persistence strategy upgrader
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UpgradeTool {
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2025 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.core.tools.internal;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.persistence.dto.PersistenceItemConfigurationDTO;
|
||||
import org.openhab.core.persistence.dto.PersistenceServiceConfigurationDTO;
|
||||
import org.openhab.core.storage.json.internal.JsonStorage;
|
||||
import org.openhab.core.tools.Upgrader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PersistenceUpgrader} removes the default persistence strategy.
|
||||
*
|
||||
* It upgrades the PersistenceServiceConfiguration database, removing default strategies and setting strategies on each
|
||||
* configuration that has no strategy defined.
|
||||
* See <a href="https://github.com/openhab/openhab-core/pull/4682">openhab/openhab-core#4682</a>.
|
||||
*
|
||||
* @author Mark Herwege - Initial Contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PersistenceUpgrader implements Upgrader {
|
||||
private final Logger logger = LoggerFactory.getLogger(PersistenceUpgrader.class);
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "persistenceCopyDefaultStrategy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Move persistence default strategy configuration to all persistence configuration without strategy defined";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@Nullable Path userdataPath, @Nullable Path confPath) {
|
||||
if (userdataPath == null) {
|
||||
logger.error("{} skipped: no userdata directory found.", getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
Path persistenceJsonDatabasePath = userdataPath
|
||||
.resolve(Path.of("jsondb", "org.openhab.core.persistence.PersistenceServiceConfiguration.json"));
|
||||
logger.info("Setting default strategy on persistence configurations without strategy '{}'",
|
||||
persistenceJsonDatabasePath);
|
||||
|
||||
if (!Files.isWritable(persistenceJsonDatabasePath)) {
|
||||
logger.error("Cannot access persistence configuration database '{}', check path and access rights.",
|
||||
persistenceJsonDatabasePath);
|
||||
return false;
|
||||
}
|
||||
JsonStorage<PersistenceServiceConfigurationDTO> persistenceStorage = new JsonStorage<>(
|
||||
persistenceJsonDatabasePath.toFile(), null, 5, 0, 0, List.of());
|
||||
|
||||
List.copyOf(persistenceStorage.getKeys()).forEach(serviceId -> {
|
||||
PersistenceServiceConfigurationDTO serviceConfigDTO = Objects
|
||||
.requireNonNull(persistenceStorage.get(serviceId));
|
||||
Collection<String> defaults = serviceConfigDTO.defaults;
|
||||
if (defaults != null) {
|
||||
Collection<PersistenceItemConfigurationDTO> configs = serviceConfigDTO.configs;
|
||||
configs.forEach(config -> {
|
||||
Collection<String> strategies = config.strategies;
|
||||
if (strategies.isEmpty()) {
|
||||
config.strategies = defaults;
|
||||
}
|
||||
});
|
||||
serviceConfigDTO.defaults = null;
|
||||
|
||||
persistenceStorage.put(serviceId, serviceConfigDTO);
|
||||
logger.info("{}: updated strategy configurations and removed default strategies", serviceId);
|
||||
}
|
||||
});
|
||||
|
||||
persistenceStorage.flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user