use of com.accenture.trac.common.exception.EStartup in project tracdap by finos.
the class CommonServiceBase method start.
/**
* Start the service
*
* This method can optionally register shutdown hooks, which are needed to
* run a standalone instance of the service.
*
* Note: Services started using svcMain() have their lifecycle managed automatically,
* there is no need to call start() or stop().
*
* @param registerShutdownHook Flag indicating a JVM shutdown hook should be registered to manage clean shutdowns
*/
public void start(boolean registerShutdownHook) {
try {
var serviceClass = getClass();
var componentName = VersionInfo.getComponentName(serviceClass);
var componentVersion = VersionInfo.getComponentVersion(serviceClass);
log.info("{} {}", componentName, componentVersion);
log.info("Service is coming up...");
timedSequence(t -> {
doStartup(t);
return null;
}, startupTimeout, "startup");
// This is needed when running a real server instance, but not when running embedded tests
if (registerShutdownHook) {
var shutdownThread = new Thread(this::jvmShutdownHook, "shutdown");
Runtime.getRuntime().addShutdownHook(shutdownThread);
}
// Keep the logging system active while shutdown hooks are running
disableLog4jShutdownHook();
log.info("Service is up and running");
} catch (ETrac e) {
// Do not log errors for quiet startup exceptions
if (e instanceof EStartup && ((EStartup) e).isQuiet())
throw e;
var errorMessage = "Service failed to start: " + e.getMessage();
log.error(errorMessage, e);
throw e;
} catch (InterruptedException e) {
log.error("Service failed to start: Startup sequence was interrupted");
Thread.currentThread().interrupt();
} catch (Exception e) {
log.error("Service failed to start: There was an unhandled error during startup (this is a bug)");
log.error(e.getMessage(), e);
throw new EStartup(e.getMessage(), e);
}
}
use of com.accenture.trac.common.exception.EStartup in project tracdap by finos.
the class StandardArgsProcessor method processTasks.
private static List<StandardArgs.Task> processTasks(CommandLine command, List<StandardArgs.Task> availableTasks) {
var taskMap = availableTasks.stream().collect(Collectors.toMap(StandardArgs.Task::getTaskName, task -> task));
var taskArgs = command.getOptionValues("task");
var tasks = new ArrayList<StandardArgs.Task>();
for (var argIndex = 0; argIndex < taskArgs.length; argIndex++) {
var taskName = taskArgs[argIndex];
if (!taskMap.containsKey(taskName))
throw new EStartup(String.format("Unknown task: [%s]", taskName));
var taskDefinition = taskMap.get(taskName);
if (taskDefinition.hasArg()) {
if (argIndex + 1 == taskArgs.length) {
var message = String.format("Task [%s] requires argument [%s]", taskName, taskDefinition.getTaskArg());
throw new EStartup(message);
}
var taskArg = taskArgs[argIndex + 1];
argIndex++;
var task = new StandardArgs.Task(taskName, taskArg);
tasks.add(task);
} else {
var task = new StandardArgs.Task(taskName);
tasks.add(task);
}
}
return List.copyOf(tasks);
}
use of com.accenture.trac.common.exception.EStartup in project tracdap by finos.
the class ConfigParser method parseYamlConfig.
private static <TConfig extends Message> TConfig parseYamlConfig(ByteBuf configData, TConfig defaultConfig) throws InvalidProtocolBufferException {
var json = Unpooled.EMPTY_BUFFER;
try (var stream = (InputStream) new ByteBufInputStream(configData)) {
var yamlFactory = new YAMLFactory();
var jsonFactory = new JsonFactory();
var reader = new YAMLMapper(yamlFactory);
var writer = new JsonMapper(jsonFactory);
var obj = reader.readValue(stream, Object.class);
var jsonBytes = writer.writeValueAsBytes(obj);
json = Unpooled.wrappedBuffer(jsonBytes);
return parseJsonConfig(json, defaultConfig);
} catch (IOException e) {
throw new EStartup(e.getMessage(), e);
} finally {
if (json != Unpooled.EMPTY_BUFFER)
json.release();
}
}
use of com.accenture.trac.common.exception.EStartup in project tracdap by finos.
the class LocalConfigLoader method loadTextFile.
@Override
public String loadTextFile(URI uri) {
var ERROR_MSG_TEMPLATE = "Failed to load config file: %2$s [%1$s]";
Path path = null;
try {
path = Paths.get(uri);
return Files.readString(path, StandardCharsets.UTF_8);
} catch (IllegalArgumentException e) {
// This should not happen
// ConfigManager should only pass file URLs to this loader
// Treat this as an internal error
var message = String.format("URL is not a file path: [%s]", uri);
throw new ETracInternal(message, e);
} catch (NoSuchFileException e) {
var message = String.format(ERROR_MSG_TEMPLATE, path, "File does not exist");
throw new EStartup(message, e);
} catch (AccessDeniedException e) {
var message = String.format(ERROR_MSG_TEMPLATE, path, "Access denied");
throw new EStartup(message, e);
} catch (IOException e) {
var message = String.format(ERROR_MSG_TEMPLATE, path, e.getMessage());
throw new EStartup(message, e);
}
}
use of com.accenture.trac.common.exception.EStartup in project tracdap by finos.
the class TracPlatformGateway method doStartup.
@Override
protected void doStartup(Duration startupTimeout) throws InterruptedException {
GatewayConfig gatewayConfig;
short proxyPort;
List<Route> routes;
try {
log.info("Preparing gateway config...");
var rawGatewayConfig = configManager.loadRootConfigObject(GatewayConfig.class);
gatewayConfig = ConfigTranslator.translateServiceRoutes(rawGatewayConfig);
proxyPort = (short) gatewayConfig.getPort();
routes = RouteBuilder.buildAll(gatewayConfig.getRoutesList());
log.info("Gateway config looks ok");
} catch (Exception e) {
var errorMessage = "There was an error preparing the gateway config: " + e.getMessage();
log.error(errorMessage, e);
throw new EStartup(errorMessage, e);
}
try {
log.info("Starting the gateway server on port {}...", proxyPort);
// The protocol negotiator is the top level initializer for new inbound connections
var protocolNegotiator = new HttpProtocolNegotiator(gatewayConfig, routes);
// TODO: Review configuration of thread pools and channel options
bossGroup = new NioEventLoopGroup(2, new DefaultThreadFactory("boss"));
workerGroup = new NioEventLoopGroup(6, new DefaultThreadFactory("worker"));
var bootstrap = new ServerBootstrap().group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(protocolNegotiator).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
// Bind and start to accept incoming connections.
var startupFuture = bootstrap.bind(proxyPort);
// Block until the server channel is ready - it's just easier this way!
// The sync call will rethrow any errors, so they can be handled before leaving the start() method
startupFuture.await();
if (startupFuture.isSuccess()) {
var socket = startupFuture.channel().localAddress();
log.info("Server socket open: {}", socket);
} else {
var cause = startupFuture.cause();
var message = "Server socket could not be opened: " + cause.getMessage();
log.error(message);
throw new EStartup(message, cause);
}
// No need to keep a reference to the server channel
// Shutdown is managed using the event loop groups
} catch (Exception e) {
if (workerGroup != null)
workerGroup.shutdownGracefully();
if (bossGroup != null)
bossGroup.shutdownGracefully();
if (Set.of(RuntimeException.class, InterruptedException.class).contains(e.getClass()))
throw e;
else
throw new EStartup(e.getMessage(), e);
}
}
Aggregations