# Hello Perigee!

## Resources

{% embed url="<https://www.youtube.com/watch?v=vCAROWxkKgM>" %}
Want to watch the intro to Perigee instead?
{% endembed %}

{% file src="<https://2203366127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FloJjRj49SSQfSrp7vuw9%2Fuploads%2FXJVx9jLTzStvHCQ4EUfJ%2F1_HelloWorld.zip?alt=media&token=27824805-c0ea-4aae-a4f0-91be0ac2516a>" %}
Completed Project Files
{% endfile %}

## Our first application

Go ahead and create a new .NET 5/6+ console application. Open up `Program.cs`, and head to the first step to get started!

{% hint style="warning" %}
If you haven't gone through the installation step, please do so first!
{% endhint %}

{% content-ref url="installation-and-project-setup" %}
[installation-and-project-setup](https://docs.perigee.software/getting-started/installation-and-project-setup)
{% endcontent-ref %}

### Step 1) The application starting point

Let's start with the basics. First let's create a new application in `Program.cs`. Depending on the version of .NET you started with, you'll see two different things when you open `Program.cs`

### Net 6++

The <mark style="color:orange;">**.NET 6**</mark> ++ version looks like this:&#x20;

```csharp
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

//YOUR CODE HERE
```

If this is the case, delete <mark style="color:blue;">**Line 2**</mark> - `Console.WriteLine("Hello, World!");` and start there.

### Net  5 and lower

The <mark style="color:orange;">**.NET 5**</mark> and below versions looks like this:

```csharp
class Program
{

    static void Main(string[] args)
    {
        //YOUR CODE HERE
    }
}
```

If this is the case, start coding on <mark style="color:blue;">**Line 6**</mark>.&#x20;

### The application code

Now that we know where to start, here's a simple <mark style="color:blue;">**Perigee**</mark> application.

{% code lineNumbers="true" %}

```csharp
//A fully managed perigee application! 
PerigeeApplication.ApplicationNoInit("FirstApp", 
(taskConfig) => { 

});
```

{% endcode %}

Let's look what what we have here in the constructor:

* <mark style="color:blue;">**Line 2**</mark> - `"FirstApp"` -  The name of the application, this can be whatever you like!
* <mark style="color:blue;">**Line 3**</mark> - `taskConfig block` - This block is where we add any and all thread managed tasks.&#x20;

{% hint style="info" %}
Make sure you have everything included in your `using` statements by clicking the :bulb: icon or press `ctrl+.` to find missing namespaces

```csharp
using Microsoft.Extensions.Logging;
using Perigee;
```

{% endhint %}

### Step 2) Adding thread managed code

This wouldn't be a hello tutorial without writing "Hello, World!", so let's add a [CRON](https://docs.perigee.software/perigee-and-beyond/all-about-cron#what-about-a-cron) method to [log](https://docs.perigee.software/hello-logs#logging-introduction) <mark style="color:red;">`Hello Perigee`</mark> every 15 seconds!

The `.AddCron` method adds a new thread to the system. Each thread is managed by Perigee and is independent of every other thread. This is an important aspect of [Perigee Application Design](https://docs.perigee.software/perigee-application-design#anatomy-of-a-perigee-application) as it allows for individual thread management. Threads do not affect each other, and Perigee's internal thread management system has mechanisms in place to automatically restart downed threads.

```csharp
//A fully managed perigee application! 
using Microsoft.Extensions.Logging;
using Perigee;

PerigeeApplication.ApplicationNoInit("FirstApp", (taskConfig) => {

    taskConfig.AddCRON("HelloWorld", "*/15 * * * * *", (ct, log) => {
        log.LogInformation("Hello Perigee from {appName}", taskConfig.AppName);
    });

});
```

* <mark style="color:blue;">**Line 4**</mark> - We use fluent syntax to `.AddCRON()` - This method takes a `name`, `CRON string`, and a `callback(cancelToken, ILogger)`.&#x20;
* <mark style="color:blue;">**Line 5**</mark> - We use the built in logger passed to us to log information in a templated format, passing in the name of the application to the logger.

Running the application produces a log new line every 15 seconds!

<figure><img src="https://2203366127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FloJjRj49SSQfSrp7vuw9%2Fuploads%2FzhaIeROQGBWsC9SU8VaT%2Fimage.png?alt=media&#x26;token=97e913e9-df32-44cb-b181-922da0eb6c3b" alt=""><figcaption></figcaption></figure>

To close this application using graceful shutdown, press <mark style="color:orange;">**CTRL-C**</mark>, it will start the safe shutdown procedure allowing the application to properly stop all running tasks before just exiting out.

<figure><img src="https://2203366127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FloJjRj49SSQfSrp7vuw9%2Fuploads%2Fx8Fd0ZPgjpTlT08Gxi0U%2Fimage.png?alt=media&#x26;token=c92e0444-9a2d-45d2-b636-3c7b3ff8af53" alt=""><figcaption></figcaption></figure>

## Hello Perigee - Extended

My oh my, we logged something! :thumbsup:Exciting right? Let's take our first demo application a step further and watch for [CSV](https://docs.perigee.software/core-modules/file-formats/csv#read) files, read them in, and report the row and data counts.

Simply replace `.AddCron()` with the [directory watcher](https://docs.perigee.software/core-modules/event-sources/watchers/directory-watch#demo-application) instead, full code below:

```csharp
PerigeeApplication.ApplicationNoInit("FirstApp", (taskConfig) => {

    taskConfig.AddDirectoryWatch("CSV", "C:\\Watch", "*.csv", SearchOption.TopDirectoryOnly, (ct, l, path) => {

        //Read the CSV
        var CSVData = CSVReader.ToDataTable(path, out var rRes);

        //Reprt on it
        l.LogInformation("Read CSV {file}[{encoding}]. Columns/Rows: {col}/{row}; Delimiter: {delChar}; Jagged? {jagged}",
            Path.GetFileName(path), rRes.FileEncoding.EncodingName, rRes.ColumnCount,
            CSVData.Rows.Count, rRes.FinalDelimiter, rRes.RowShifts.Count > 0 ? "YES" : "NO");

        //Remove it - OR let the failed folder policy kick in
        //File.Delete(path);

    }, policy: ThreadRegistry.DirectoryWatchFailurePolicy.MoveToFailedFolder);

});
```

Here's a `sample.csv`:

```csv
Name, Age, Email, Phone
John Doe, 30, john.doe@example.com, 123-456-7890
Jane Smith, 25, jane.smith@example.com, 987-654-3210
Bob Johnson, 40, bob.johnson@example.com, 555-555-5555
Mary Lee, 28, mary.lee@example.com, 111-222-3333
Hash Brown, 35, hash.brown@example.com, 444-444-4444
```

{% hint style="success" %}
Make sure you have everything included in your **`using`** statements by clicking the :bulb: icon or press `ctrl+.` to find missing namespaces

```csharp
using Microsoft.Extensions.Logging;
using Perigee;
using Perigee.FileFormats.CSV;
using System.Data;
```

{% endhint %}

Voila! You're now watching for CSV files, reading them in, and reporting on the number of rows and columns.&#x20;

For an intro to Perigee we accomplished quite a lot.&#x20;

* We learned about [threads](https://docs.perigee.software/perigee-application-design#managed-threads) - how they're added and independent of each other.
* We learned about [logging](https://docs.perigee.software/getting-started/hello-logs) information to the available sinks.
* [CRON](https://docs.perigee.software/perigee-and-beyond/all-about-cron#what-about-a-cron) strings and how to use a CRON thread.
* How to configure Perigee.
* What "Graceful Shutdown" looks like.
* We even got to see the [CSV](https://docs.perigee.software/core-modules/file-formats/csv#read) reader in action.

Let's hop over to the next section and continue!
