Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import static org.openmrs.module.initializer.InitializerConstants.PROPS_LOGGING_ENABLED;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_LOGGING_LEVEL;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_LOGGING_LOCATION;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_PRIMARY_STARTUP;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_STARTUP_LOAD_DISABLED;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_STARTUP_LOAD_FAIL_ON_ERROR;
import static org.openmrs.module.initializer.api.utils.Utils.getPropertyValue;
Expand Down Expand Up @@ -76,20 +77,34 @@ public void started() {
InitializerMessageSource messageSource = getInitializerMessageSource();
Context.getMessageSourceService().setActiveMessageSource(messageSource);

boolean isPrimary = Boolean.parseBoolean(getPropertyValue(PROPS_PRIMARY_STARTUP, "false"));
if (!isPrimary) {
log.info("Initializer running in REPLICA mode → skipping config imports");
return;
}

String startupLoadingMode = getInitializerService().getInitializerConfig().getStartupLoadingMode();

if (PROPS_STARTUP_LOAD_DISABLED.equalsIgnoreCase(startupLoadingMode)) {
log.info("OpenMRS config loading process disabled at initializer startup");
} else {
boolean throwError = PROPS_STARTUP_LOAD_FAIL_ON_ERROR.equalsIgnoreCase(startupLoadingMode);
log.info("OpenMRS config loading process started...");
try {
getInitializerService().loadUnsafe(true, throwError);
log.info("OpenMRS config loading process completed.");
}
catch (Exception e) {
throw new ModuleException("An error occurred loading initializer configuration", e);
}
return;
}

if (!shouldRunInitializerSafely()) {
log.info("No version/config changes detected → skipping initializer execution.");
return;
}

boolean throwError = PROPS_STARTUP_LOAD_FAIL_ON_ERROR.equalsIgnoreCase(startupLoadingMode);
log.info("OpenMRS config loading process started...");

try {
getInitializerService().loadUnsafe(true, throwError);
updateRunState();
log.info("OpenMRS config loading process completed.");
}
catch (Exception e) {
throw new ModuleException("An error occurred loading initializer configuration", e);
}
}

Expand All @@ -105,6 +120,14 @@ protected InitializerMessageSource getInitializerMessageSource() {
return Context.getRegisteredComponents(InitializerMessageSource.class).get(0);
}

protected boolean shouldRunInitializerSafely() {
return getInitializerService().shouldRunInitializer();
}

protected void updateRunState() {
getInitializerService().updateInitializerRunState();
}

/**
* @see #shutdown()
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ public class InitializerConstants {

public static final String PROPS_STARTUP_LOAD_DISABLED = "disabled";

public static final String GP_INITIALIZER_SIGNATURE = "initializer.lastSignature";

public static final String PROPS_PRIMARY_STARTUP = "primary.startup";

/*
* Logging properties
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,15 @@ public interface InitializerService extends OpenmrsService {
* @return the found Concepts
*/
List<Concept> getUnretiredConceptsByFullySpecifiedName(String name);

/**
* Returns true if initializer should run based on: core version change, module version change,
* config directory checksum change.
*/
boolean shouldRunInitializer();

/**
* Updates stored signature after successful initializer execution.
*/
void updateInitializerRunState();
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,35 @@

import static org.openmrs.module.initializer.InitializerConstants.DIR_NAME_CHECKSUM;
import static org.openmrs.module.initializer.InitializerConstants.DIR_NAME_CONFIG;
import static org.openmrs.module.initializer.InitializerConstants.GP_INITIALIZER_SIGNATURE;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.openmrs.Concept;
import org.openmrs.PersonAttributeType;
import org.openmrs.api.context.Context;
import org.openmrs.api.impl.BaseOpenmrsService;
import org.openmrs.module.ModuleFactory;
import org.openmrs.module.initializer.InitializerConfig;
import org.openmrs.module.initializer.api.loaders.Loader;
import org.openmrs.module.initializer.api.utils.Utils;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -223,4 +229,39 @@ public InitializerConfig getInitializerConfig() {
public List<Concept> getUnretiredConceptsByFullySpecifiedName(String name) {
return initializerDAO.getUnretiredConceptsByFullySpecifiedName(name);
}

@Override
public boolean shouldRunInitializer() {
String oldSig = Context.getAdministrationService().getGlobalProperty(GP_INITIALIZER_SIGNATURE);
return oldSig == null || !oldSig.equals(computeSignature());
}

@Override
public void updateInitializerRunState() {
Context.getAdministrationService().setGlobalProperty(GP_INITIALIZER_SIGNATURE, computeSignature());
}

private String computeSignature() {
String coreVersion = OpenmrsConstants.OPENMRS_VERSION;

String moduleVersions = ModuleFactory.getLoadedModules().stream().map(m -> m.getModuleId() + ":" + m.getVersion())
.collect(Collectors.joining(","));

ConfigDirUtil configUtil = new ConfigDirUtil(getConfigDirPath(), getChecksumsDirPath(), "");

List<File> files = configUtil.getFiles("", Collections.emptyList());
String concatenated = files.stream().filter(File::isFile).sorted(Comparator.comparing(File::getAbsolutePath))
.map(file -> {
try {
byte[] bytes = Files.readAllBytes(file.toPath());
return DigestUtils.sha256Hex(bytes) + ":" + file.getAbsolutePath();
}
catch (Exception e) {
return "ERR:" + file.getAbsolutePath();
}
}).collect(Collectors.joining("|"));

String configChecksum = DigestUtils.sha256Hex(concatenated);
return DigestUtils.sha256Hex(coreVersion + "|" + moduleVersions + "|" + configChecksum);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static org.openmrs.module.initializer.Domain.CONCEPTS;
import static org.openmrs.module.initializer.Domain.DRUGS;
import static org.openmrs.module.initializer.Domain.ENCOUNTER_TYPES;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_PRIMARY_STARTUP;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_STARTUP_LOAD;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_STARTUP_LOAD_CONTINUE_ON_ERROR;
import static org.openmrs.module.initializer.InitializerConstants.PROPS_STARTUP_LOAD_DISABLED;
Expand Down Expand Up @@ -68,6 +69,15 @@ protected InitializerService getInitializerService() {
return iniz;
}

@Override
protected boolean shouldRunInitializerSafely() {
return true;
}

@Override
protected void updateRunState() {
}

@Override
protected List<InitializerLogConfigurator> getInitializerLogConfigurator() {
return null;
Expand All @@ -83,6 +93,7 @@ protected InitializerMessageSource getInitializerMessageSource() {
}

protected void startActivator(String startupLoadConfiguration) {
System.setProperty(PROPS_PRIMARY_STARTUP, "true");
startActivator(startupLoadConfiguration, false);
}

Expand Down