Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving the FileObserver class definition #265

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
321 changes: 159 additions & 162 deletions src/Unit-1/lesson4/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,72 +241,8 @@ The goal of this exercise is to show you how to make a parent/child actor relati
### Phase 1: Make your first parent/child actors!
We're ready to create our actor classes that will form a parent/child relationship.

Recall that in the hierarchy we're going for, there is a `TailCoordinatorActor` that coordinates child actors to actually monitor and tail files. For now it will only supervise one child, `TailActor`, but in the future it can easily expand to have many children, each observing/tailing a different file.

#### Add `TailCoordinatorActor`
Create a new class called `TailCoordinatorActor` in a file of the same name.

Add the following code, which defines our coordinator actor (which will soon be our first parent actor).

```csharp
// TailCoordinatorActor.cs
using System;
using Akka.Actor;

namespace WinTail
{
public class TailCoordinatorActor : UntypedActor
{
#region Message types

/// <summary>
/// Start tailing the file at user-specified path.
/// </summary>
public class StartTail
{
public StartTail(string filePath, IActorRef reporterActor)
{
FilePath = filePath;
ReporterActor = reporterActor;
}

public string FilePath { get; private set; }

public IActorRef ReporterActor { get; private set; }
}

/// <summary>
/// Stop tailing the file at user-specified path.
/// </summary>
public class StopTail
{
public StopTail(string filePath)
{
FilePath = filePath;
}

public string FilePath { get; private set; }
}

#endregion

protected override void OnReceive(object message)
{
if (message is StartTail)
{
var msg = message as StartTail;
// YOU NEED TO FILL IN HERE
}
}
}
}
```



#### Add `TailActor`
Now, add a class called `TailActor` in its own file. This actor is the actor that is actually responsible for tailing a given file. `TailActor` will be created and supervised by `TailCoordinatorActor` in a moment.

Add a class called `TailActor` in its own file. This actor is the actor that is actually responsible for tailing a given file. `TailActor` will be created and supervised by `TailCoordinatorActor` in a moment.
For now, add the following code in `TailActor.cs`:

```csharp
Expand Down Expand Up @@ -427,11 +363,167 @@ namespace WinTail
}
```


#### Add `FileObserver`
This is a utility class that we're providing for you to use. It does the low-level work of actually watching a file for changes.
Create a new class called `FileObserver` and type in the code for [FileObserver.cs](Completed/FileObserver.cs). If you're running this on Mono, note the extra environment variable that has to be uncommented in the `Start()` method:

```csharp
// FileObserver.cs
using System;
using System.IO;
using Akka.Actor;

namespace WinTail
{
/// <summary>
/// Turns <see cref="FileSystemWatcher"/> events about a specific file into
/// messages for <see cref="TailActor"/>.
/// </summary>
public class FileObserver : IDisposable
{
private readonly IActorRef _tailActor;
private readonly string _absoluteFilePath;
private FileSystemWatcher _watcher;
private readonly string _fileDir;
private readonly string _fileNameOnly;

public FileObserver(IActorRef tailActor, string absoluteFilePath)
{
_tailActor = tailActor;
_absoluteFilePath = absoluteFilePath;
_fileDir = Path.GetDirectoryName(absoluteFilePath);
_fileNameOnly = Path.GetFileName(absoluteFilePath);
}

/// <summary>
/// Begin monitoring file.
/// </summary>
public void Start()
{
// Need this for Mono 3.12.0 workaround
// uncomment next line if you're running on Mono!
// Environment.SetEnvironmentVariable("MONO_MANAGED_WATCHER", "enabled");

// make watcher to observe our specific file
_watcher = new FileSystemWatcher(_fileDir, _fileNameOnly);

// watch our file for changes to the file name,
// or new messages being written to file
_watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;

// assign callbacks for event types
_watcher.Changed += OnFileChanged;
_watcher.Error += OnFileError;

// start watching
_watcher.EnableRaisingEvents = true;
}

/// <summary>
/// Stop monitoring file.
/// </summary>
public void Dispose()
{
_watcher.Dispose();
}

/// <summary>
/// Callback for <see cref="FileSystemWatcher"/> file error events.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnFileError(object sender, ErrorEventArgs e)
{
_tailActor.Tell(new TailActor.FileError(_fileNameOnly,
e.GetException().Message),
ActorRefs.NoSender);
}

/// <summary>
/// Callback for <see cref="FileSystemWatcher"/> file change events.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnFileChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Changed)
{
// here we use a special ActorRefs.NoSender
// since this event can happen many times,
// this is a little microoptimization
_tailActor.Tell(new TailActor.FileWrite(e.Name), ActorRefs.NoSender);
}
}
}
}
```

Recall that in the hierarchy we're going for, there is a `TailCoordinatorActor` that coordinates child actors to actually monitor and tail files. For now it will only supervise one child, `TailActor`, but in the future it can easily expand to have many children, each observing/tailing a different file.

#### Add `TailCoordinatorActor`
Create a new class called `TailCoordinatorActor` in a file of the same name.

Add the following code, which defines our coordinator actor (which will soon be our first parent actor).

```csharp
// TailCoordinatorActor.cs
using System;
using Akka.Actor;

namespace WinTail
{
public class TailCoordinatorActor : UntypedActor
{
#region Message types

/// <summary>
/// Start tailing the file at user-specified path.
/// </summary>
public class StartTail
{
public StartTail(string filePath, IActorRef reporterActor)
{
FilePath = filePath;
ReporterActor = reporterActor;
}

public string FilePath { get; private set; }

public IActorRef ReporterActor { get; private set; }
}

/// <summary>
/// Stop tailing the file at user-specified path.
/// </summary>
public class StopTail
{
public StopTail(string filePath)
{
FilePath = filePath;
}

public string FilePath { get; private set; }
}

#endregion

protected override void OnReceive(object message)
{
if (message is StartTail)
{
var msg = message as StartTail;
// YOU NEED TO FILL IN HERE
}
}
}
}
```


#### Add `TailActor` as a child of `TailCoordinatorActor`
Quick review: `TailActor` is to be a child of `TailCoordinatorActor` and will therefore be supervised by `TailCoordinatorActor`.

This also means that `TailActor` must be created in the context of `TailCoordinatorActor`.

Go to `TailCoordinatorActor.cs` and replace `OnReceive()` with the following code to create your first child actor!

```csharp
Expand Down Expand Up @@ -563,101 +655,6 @@ private void DoPrintInstructions()
}
```

#### Add `FileObserver`
This is a utility class that we're providing for you to use. It does the low-level work of actually watching a file for changes.

Create a new class called `FileObserver` and type in the code for [FileObserver.cs](Completed/FileObserver.cs). If you're running this on Mono, note the extra environment variable that has to be uncommented in the `Start()` method:

```csharp
// FileObserver.cs
using System;
using System.IO;
using Akka.Actor;

namespace WinTail
{
/// <summary>
/// Turns <see cref="FileSystemWatcher"/> events about a specific file into
/// messages for <see cref="TailActor"/>.
/// </summary>
public class FileObserver : IDisposable
{
private readonly IActorRef _tailActor;
private readonly string _absoluteFilePath;
private FileSystemWatcher _watcher;
private readonly string _fileDir;
private readonly string _fileNameOnly;

public FileObserver(IActorRef tailActor, string absoluteFilePath)
{
_tailActor = tailActor;
_absoluteFilePath = absoluteFilePath;
_fileDir = Path.GetDirectoryName(absoluteFilePath);
_fileNameOnly = Path.GetFileName(absoluteFilePath);
}

/// <summary>
/// Begin monitoring file.
/// </summary>
public void Start()
{
// Need this for Mono 3.12.0 workaround
// uncomment next line if you're running on Mono!
// Environment.SetEnvironmentVariable("MONO_MANAGED_WATCHER", "enabled");

// make watcher to observe our specific file
_watcher = new FileSystemWatcher(_fileDir, _fileNameOnly);

// watch our file for changes to the file name,
// or new messages being written to file
_watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;

// assign callbacks for event types
_watcher.Changed += OnFileChanged;
_watcher.Error += OnFileError;

// start watching
_watcher.EnableRaisingEvents = true;
}

/// <summary>
/// Stop monitoring file.
/// </summary>
public void Dispose()
{
_watcher.Dispose();
}

/// <summary>
/// Callback for <see cref="FileSystemWatcher"/> file error events.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnFileError(object sender, ErrorEventArgs e)
{
_tailActor.Tell(new TailActor.FileError(_fileNameOnly,
e.GetException().Message),
ActorRefs.NoSender);
}

/// <summary>
/// Callback for <see cref="FileSystemWatcher"/> file change events.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnFileChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Changed)
{
// here we use a special ActorRefs.NoSender
// since this event can happen many times,
// this is a little microoptimization
_tailActor.Tell(new TailActor.FileWrite(e.Name), ActorRefs.NoSender);
}
}
}
}
```



Expand Down