top of page

5 items found for ""

  • Part 4 - Bringing It All Together

    Welcome to the concluding post of our in-depth series on Advanced Concepts in IT Incident Management using LittleHorse. We've traversed through the core elements that make workflows dynamic, responsive, and efficient. Now, it's time to see everything in action, stitching together conditionals, loops, external events, and variable mutations into a cohesive workflow that represents the peak of IT incident management. ‘Just like the Rebels' triumph in 'Return of the Jedi,' we've successfully navigated through the galaxy of LittleHorse's advanced concepts, from conditionals to external events, bringing peace and efficiency to our IT incident management galaxy! The Conductor: In our journey, plays the pivotal role of the orchestrator, setting the stage for our workflow's execution. It's here where we register our workflow, task definitions, and handle the initiation and management of external events. Let's take a closer look at how brings our project to life: public class App { // Define constants for task and event names private static final String VERIFY_TASK = "verify-incident"; private static final String PERIODIC_CHECK_TASK = "periodic-check-task"; private static final String SEND_CRITICAL_ALERT_TASK = "send-critical-alert"; private static final String EXTERNAL_EVENT_NAME = "incident-resolved"; // Method to register an external event in the LittleHorse workflow system private static void registerExternalEventDef(LittleHorseBlockingStub client) { System.out.println("Registering external event " + EXTERNAL_EVENT_NAME); // Create a new external event definition client.putExternalEventDef( PutExternalEventDefRequest.newBuilder().setName(EXTERNAL_EVENT_NAME).build() ); System.out.println("External event registered successfully."); } // Method to register workflow and task definitions private static void registerWorkflow() throws IOException { LHConfig config = new LHConfig(); // Create task worker instances for each task IncidentWorker workerInstance = new IncidentWorker(); LHTaskWorker verifyTaskWorker = new LHTaskWorker(workerInstance, VERIFY_TASK, config); LHTaskWorker periodicCheckTaskWorker = new LHTaskWorker(workerInstance, PERIODIC_CHECK_TASK, config); LHTaskWorker sendCriticalAlertTaskWorker = new LHTaskWorker(workerInstance, SEND_CRITICAL_ALERT_TASK, config); // Register each task definition verifyTaskWorker.registerTaskDef(); periodicCheckTaskWorker.registerTaskDef(); sendCriticalAlertTaskWorker.registerTaskDef(); // Register the workflow specification ConditionalsExample conditionalsExample = new ConditionalsExample(); conditionalsExample.getWorkflow().registerWfSpec(config.getBlockingStub()); System.out.println("Workflow registered successfully."); } // Method to start an individual task worker private static void startTaskWorker(LHTaskWorker worker) throws IOException { // Add a shutdown hook to ensure the worker is closed properly Runtime.getRuntime().addShutdownHook(new Thread(worker::close)); // Start the worker to begin listening for tasks worker.start(); System.out.println("Started worker for task: " + worker.getTaskDefName()); } // Method to start all necessary task workers private static void startTaskWorkers() throws IOException { LHConfig config = new LHConfig(); // Start each task worker startTaskWorker(new LHTaskWorker(new IncidentWorker(), VERIFY_TASK, config)); startTaskWorker(new LHTaskWorker(new IncidentWorker(), PERIODIC_CHECK_TASK, config)); startTaskWorker(new LHTaskWorker(new IncidentWorker(), SEND_CRITICAL_ALERT_TASK, config)); } // Main method to execute the application public static void main(String[] args) throws IOException { // Validate command line arguments if (args.length != 1 || (!args[0].equals("register") && !args[0].equals("start"))) { System.err.println("Argument required: 'register' or 'start'"); System.exit(1); } // Establish a gRPC channel to communicate with the LittleHorse server String host = "localhost"; int port = 2023; ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build(); LittleHorseBlockingStub client = LittleHorseGrpc.newBlockingStub(channel); try { // Execute registration or start tasks based on the command line argument if (args[0].equals("register")) { registerExternalEventDef(client); // Register external event registerWorkflow(); // Register workflow and task definitions } else { startTaskWorkers(); // Start task workers to handle tasks } } finally { // Ensure proper shutdown of the gRPC channel channel.shutdown(); } } } Through, we initialize our system, ensuring that each component is ready to perform its part in our IT incident management workflow. Note: To get the complete code, check out this github repository and Star it if you like it! Execution Commands: Activating the Workflow With `` orchestrating our setup, it's time to dive into the execution commands that breathe life into our workflow. These commands demonstrate the real-time application of conditionals, loops, external events, and variable mutations, showcasing the workflow's dynamic response to IT incidents. Conditionals Execution: We kickstart our journey with the conditional logic that assesses incident severity. lhctl run it-incident severity 8 incidentDetails '{"incidentId":"INC001","type":"Database Outage","severity":8,"description":"Critical Database outage affecting all transaction processing systems”, "reportedAt":"2024-01-30T08:00:00Z"}' This command simulates a major incident, allowing us to observe how our workflow categorizes and responds based on the severity level defined in our conditionals. Looping Through Checks: Our workflow enters a loop, performing periodic checks on the incident status until resolved. lhctl run it-incident severity 12 incidentDetails '{"incidentId":"INC002","type":"Network Outage","severity":12,"description":"Loss of Connectivity","reportedAt":"2024-01-30T08:00:00Z"}' resolved false As soon as we trigger the incident and mark the resolution to be false, the periodic checks start to function! Here, the loop within our workflow ensures continuous monitoring, demonstrating the persistence layer enabled by our loop implementation. Variable Mutations in Action: The external event triggers a variable mutation, updating the incident's status within our workflow. The mutation is a result of the external event. (See below) Triggering External Events: External events allow our workflow to interact with real-world triggers. So, first let us create a new incident where the incident isn’t resolved. lhctl run it-incident severity 10 incidentDetails '{"incidentId":"INC003","type":"System Failure","severity":10,"description":"Major System Crash","reportedAt":"2024-02-30T08:00:00Z"}' resolved false As you can see, the incident was created. The resolved variable has been set to false. And this setting is keeping our workflow in a loop, continually performing periodic checks. The below command will simulate an external event, which in turn will change the `incidentResolved` variable to `true`. This is a perfect example of how an external event can trigger variable mutation within the workflow. By updating the variable, we directly influence the workflow's path, transitioning it out of the loop. lhctl postEvent [WF_RUN_ID] incident-resolved BOOL true The mutation of the incidentResolved variable to true highlights the adaptability of our workflow, adjusting its path based on real-time data. To see a Live implementation of all of these, checkout our tutorial series on the same: LittleHorse Advanced Concepts - Introduction | IT Incident Management Workflow Wrapping Up Our Series As we conclude our series, it's essential to recognize the power and flexibility that LittleHorse offers in building complex, efficient, and responsive workflows. Through the practical application of conditionals, loops, external events, and variable mutations, we've demonstrated how LittleHorse can be leveraged to manage IT incidents effectively, providing a blueprint that can be adapted and extended to suit a wide range of scenarios beyond IT incident management. Thank you for joining us on this journey. We hope it has provided you with valuable insights and inspiration to explore further the possibilities that LittleHorse and workflow automation bring to the table. Here's to building more dynamic, efficient, and intelligent workflows in your future projects! Until next time, happy coding! 👋

  • Part 3 - LittleHorse Advanced Concept Series: Variable Mutations and External Events

    Welcome back to our journey through the advanced concepts of IT Incident Management using LittleHorse. After mastering conditionals and loops, it's time to learn about variable mutations and external events, which bring a whole new level of dynamism and responsiveness to our workflows. Wondering about the power of Variable Mutations? Think of variable mutations as the gears that shift your workflow in response to changing conditions. They're the updates and changes to the data your workflow acts upon, ensuring your process stays relevant and accurate to the situation at hand. In our ``, we've been managing incidents based on their severity. But what happens when an incident's status changes or is resolved? That's where variable mutations come into play. // Inside wf.registerInterruptHandler("incident-resolved", handler -> { handler.mutate(incidentResolved, VariableMutationType.ASSIGN, true); }); This snippet shows how we can use an interrupt handler to listen for an "incident-resolved" event and then mutate the `incidentResolved` variable to `true`, effectively ending our loop of periodic checks. External events are like the messengers of the workflow world, bringing news from the outside that can influence the course of our processes. They provide a way for our workflows to interact with the world beyond the code, responding to real-world actions, triggers and/or changes. In our incident management scenario, an external event might be the resolution of an IT issue, reported by an external system or a user action. Handling this in LittleHorse looks something like this: // Using LittleHorse CLI to simulate an external event lhctl postEvent [WF_RUN_ID] incident-resolved BOOL true By executing this command, we simulate the external event that our workflow is waiting for, which, in turn, triggers the variable mutation we set up earlier. Bringing It All Together: and Our `` is responsible for orchestrating the registration of workflows, task workers, and handling external events. It ensures that all parts of our system are ready and responsive to the inputs they receive. Meanwhile, `` is where the action happens. It's here that we define the tasks our workflow can perform, from verifying incidents to sending alerts and performing periodic checks. Each task is a response to the conditions and events our workflow encounters. // Inside @LHTaskMethod("periodic-check-task") public String periodicCheckTask(String incidentId) { System.out.println("Performing periodic check for Incident ID: " + incidentId); return "Periodic Check Completed"; } Testing Our Workflow with Variable Mutations and External Events Now that we've integrated variable mutations and external events into our workflow, we can start to see the full picture of how dynamic and responsive our incident management system can be. By simulating an external event using the LittleHorse CLI, we can observe how our workflow adapts, moving from active monitoring to resolution. Looking Forward As we wrap up this blog, we've seen how variable mutations and external events add layers of flexibility and responsiveness to our workflows. These concepts are not just crucial for IT Incident Management but can be applied to a wide range of scenarios where workflows need to adapt to changing conditions and external inputs. Stay tuned for our next post, where we'll tie all these concepts together in a comprehensive summary, showcasing the full potential of LittleHorse in managing complex workflows. Until then, happy coding, and may your workflows be as dynamic and adaptable as ever! Link to Part 4: Summary and Wrap up!

  • Part 2 - LittleHorse Advanced Concept Series: Loops

    Welcome back to our advanced concept blog series on IT Incident Management with LittleHorse! If you've been following along, you've already seen how conditionals can level up your workflows through different scenarios. Now, let's add another layer of sophistication with loops. Loops let your workflow persistently do things until a condition changes. Imagine a diligent droid in a Star Wars saga, tirelessly working on a task until told otherwise. That's what loops do in our incident management system. Why do Loops matter? In IT Incident Management, some tasks need repetition. Maybe we're waiting for an incident to resolve or continuously checking system health. Loops in LittleHorse let us automate these repetitive tasks efficiently, reducing manual oversight and speeding up resolution times. Let's jump back into our `` file. We're adding a loop that'll keep an eye on incidents until they're marked as resolved. Here's a sneak peek into how we set it up: Inside ConditionalsExample.define Workflow method wf.doWhile( wf.condition(incidentResolved, Comparator.EQUALS, false), loopBody -> { loopBody.execute(PERIODIC_CHECK_TASK, incidentDetails); loopBody.sleepSeconds(30); // Take a breather, then check again } ); This loop uses the doWhile construct to continuously execute the PERIODIC_CHECK_TASK as long as the incidentResolved variable is false. It's like saying, "Keep checking on this incident every 30 seconds until it's resolved.” You might be wondering what’s the role of periodic check task in this example. Remember the PERIODIC_CHECK_TASK we mentioned in Part 1? Here's where it shines. This task might involve checking logs, querying system status, or even sending out automated pings to see if an issue persists. And with our loop in place, it keeps running at regular intervals, automating what would otherwise be a tedious manual process. Introducing serves as the central hub for initializing and managing our workflow. It's where all the pieces of our system come together. Here's a basic setup to get us started: // Inside public class App { public static void main(String[] args) { // Initialize workflow and task workers ConditionalsExample workflow = new ConditionalsExample(); workflow.getWorkflow().registerWfSpec(new LHConfig().getBlockingStub()); new LHTaskWorker(new IncidentWorker(), VERIFY_TASK, new LHConfig()).start(); // Additional task workers will be started here } } This code snippet initializes our workflow and starts a task worker for `VERIFY_TASK`. Our workflow tasks, such as verifying incidents or sending alerts, are handled in individual Java files. Let's look at ``, which defines our task methods: // Inside public class IncidentWorker { @LHTaskMethod("verify-incident") public String verifyIncident(String incidentDetails) { // Logic for verifying incident details } // Additional task methods like periodic checks and sending alerts } `` contains task methods annotated with `@LHTaskMethod`, each dedicated to handling a specific part of our incident management process. With `` orchestrating the workflow and `` handling specific tasks, our system is starting to take shape. We’ve got the core (``) directing the flow, the orchestrator (``) managing execution, and the executors (`` and others) performing tasks. While we can't fully test the entire workflow yet, we’re laying down the framework for a comprehensive IT Incident Management system. We’re building towards a fully integrated workflow capable of dynamically responding to incidents with precision. What's Ahead? Next, we'll finalize our task files, refine, and explore integrating external events to further enhance our workflow's responsiveness and intelligence. Our goal is a robust system capable of managing IT incidents not just reactively, but proactively. Stay tuned, and happy coding! In the meantime, keep exploring the endless possibilities that loops and conditionals open up in the realm of workflow automation. Imagine the efficiency, the time saved, and the potential for even more complex automation. The future is bright (and looped)! Link to Part 3: Variable Mutations and External Events!

  • Part 1 - LittleHorse Advanced Concept Series: Conditionals

    Welcome to our blog series on IT Incident Management using LittleHorse! If you’re into coding, workflow automation, or just looking to up your IT game, you’re in the right place. This series will walk you through creating responsive and efficient workflows to manage IT incidents like a pro. As a bonus, this series will introduce many key LittleHorse concepts that will allow you to apply LittleHorse to any domain, not just IT incident management. While dealing with IT incident management, being able to make decisions based on different scenarios is key. That’s where conditionals come into play. Think of conditionals as the decision-makers in your workflow, helping your system figure out what to do next based on what’s happening. Conditionals allow your workflows to behave differently depending on the situation, rather than repeatedly doing the same thing over-and-over (like BB-8 above). Let’s set the stage for our incident management system. Our mission? To develop a workflow that can identify IT incidents, figure out how serious they are, and take action. We’ll break it down into two main types of incidents: the “Oh no!” kind (critical) and the “We’ve got this” kind (non-critical). Along the way, we’ll become LittleHorse pro’s so that you can apply LittleHorse to any business domain, whether related to IT incident management or otherwise. To get started, make sure you have completed the below steps: Have LittleHorse installed on your computer. Have docker up and running Once we’re all set with the above prerequisites, we’ll build a system that intelligently assesses IT incidents and decides the best course of action. Creating the Workflow Our first step is to create the file This is where we’ll map out the logic that determines how our workflow will handle incidents. Open up your favorite Java IDE or text editor, and let’s get started. Defining the Workflow Structure In, we’ll start by defining our workflow structure. Here’s a simple outline to get us started: package; import io.littlehorse.sdk.common.proto.*; import io.littlehorse.sdk.wfsdk.*; public class ConditionalsExample { public static final String WF_NAME = "it-incident"; public static final String VERIFY_TASK = "verify-incident"; public static final String SEND_CRITICAL_ALERT_TASK = "send-critical-alert-task"; public static final String PERIODIC_CHECK_TASK = "periodic-check-task"; public void defineWorkflow(WorkflowThread wf) { // We'll flesh this out in a moment } public Workflow getWorkflow() { return Workflow.newWorkflow(WF_NAME, this::defineWorkflow); } // Additional methods will go here } This sets up a class ConditionalsExample that will hold our workflow logic. We’ve also declared constants for our workflow name and task names, which will come in handy later. These constants have specific use case: WF_NAME: Identifies the workflow, used to start or reference it within LittleHorse. VERIFY_TASK: Represents a task that checks and categorizes the incident details. SEND_CRITICAL_ALERT_TASK: Triggers an alert mechanism for incidents deemed critical. PERIODIC_CHECK_TASK: Executes regular checks to update the status of an ongoing incident. The variables we define in our workflow are not standalone; they interact and often depend on each other. For instance, the incidentSeverity variable determines whether to run the VERIFY_TASK or not. Similarly, the outcome of VERIFY_TASK might affect whether SEND_CRITICAL_ALERT_TASK is executed. Implementing Conditional Logic Now, we’ll add the brains of our operation: the conditional logic. This logic checks incident severity and routes the workflow accordingly: // Inside ConditionalsExample.defineWorkflow method WfRunVariable incidentSeverity = wf.addVariable("severity", VariableType.INT); WorkflowCondition isCritical = wf.condition(incidentSeverity, Comparator.GREATER_THAN, 5); wf.doIf( isCritical, ifBody -> { ifBody.execute(VERIFY_TASK, incidentSeverity); // We'll add more here later } ); This code snippet introduces a workflow variable incidentSeverity and a conditional isCritical. If the severity of an incident is above 5, the workflow considers it critical and executes the VERIFY_TASK. You can check out our youtube tutorial on this example to develop a comprehensive idea of how conditionals work out! Building Out the Workflow With our conditionals set up, we’ll now chalk out what happens in the critical and non-critical paths. But before we do that, let’s pause and understand why this matters. Conditionals are powerful because they allow our workflow to be not just a static sequence of tasks but a dynamic, decision-making process. Depending on the severity of an incident, our workflow can trigger alerts, involve different team members, or escalate issues automatically. Why can’t we test the command yet? To test if conditionals are fully working, we need to pass a command through our terminal. We cannot run it at this point because our workflow is not fully implemented. We have just begun to sketch out the structure in The lhctl run command is used to initiate a workflow when all components, including the main application file ( and the task definition files, are complete and integrated. Next Steps In our next blog post, we’ll continue building our, adding more tasks and integrating more advanced LittleHorse features. We’ll see how our workflow can not only detect and verify incidents but also take proactive steps to resolve them. Link to Part 2: Loops!

  • LittleHorse Team Adventures and Exciting Updates!

    Hello LittleHorse community! We're thrilled to share a bunch of exciting news and updates with you in this blog post. From our recent team adventure in Ecuador to the release of LittleHorse 0.7, a brand new website, and some fantastic learning resources, we've got a lot to cover. So, let's dive in! 🌎 Colt Takes on Ecuador: A LittleHorse Team Adventure Our team recently embarked on an unforgettable journey to Ecuador, where we combined work, creativity, and fun in a fantastic blend. This was more than just a work trip, it was an opportunity to bond, brainstorm, and bring new ideas to life in a vibrant and inspiring setting. We’ve captured some great moments from our adventure, which we’re excited to share with you! It's a glimpse into the heart of our team and the energy that drives LittleHorse! 🚀 Launching LittleHorse 0.7.0 We're proud to announce the release of LittleHorse 0.7.0! This version is a big leap forward, packed with new features and improvements that we can’t wait for you to try out. From enhanced performance to new functionalities, our team has worked tirelessly to make this release special. To find out our detailed release notes, click on this link! 🌐 Introducing Our New Website: We're excited to unveil our new official website - [](! It’s been redesigned from the ground up to provide you with an easier, more intuitive way to learn about LittleHorse, its features, and how it can help you in your projects. Whether you’re new to LittleHorse or a seasoned user, our new website is the go-to resource for all things LittleHorse. 🎥 Learning LittleHorse: Tutorials Now on YouTube For those eager to learn more about LittleHorse, we've got some great news! We've released a series of quick start and advanced tutorials covering Java on our YouTube channel. These tutorials are designed to help you get up and running with LittleHorse, offering insights into its capabilities and how to leverage them in your projects. Check out our LittleHorse YouTube channel to start learning today. ☁️ LH Cloud: Early Access Now Available Last but certainly not least, we're thrilled to announce that LH Cloud is now in early access! This is your opportunity to get a first-hand experience of our cloud solution, designed to streamline and enhance your LittleHorse projects. We're looking for feedback and suggestions to make LH Cloud even better, so don't miss this chance to be among the first to try it out. That's all for now, folks! We’re incredibly excited about these developments and can't wait for you to experience them. Stay tuned for more updates, and as always, thank you for being part of our LittleHorse community! Until next time, Sohini, LittleHorse Team

bottom of page