Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Convert the remaining events to the C# #2253

Merged
merged 2 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
193 changes: 110 additions & 83 deletions src/ApiService/ApiService/OneFuzzTypes/Events.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
using System.Text.Json;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
using Region = System.String;

namespace Microsoft.OneFuzz.Service;

/// <summary>
/// Identifies the enum type associated with the event class
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class EventTypeAttribute : Attribute {
public EventTypeAttribute(EventType eventType) {
this.EventType = eventType;
}

public EventType EventType { get; }
}


public enum EventType {
Expand Down Expand Up @@ -38,62 +50,51 @@ public enum EventType {
}

public abstract record BaseEvent() {

private static readonly IReadOnlyDictionary<Type, EventType> typeToEvent;
private static readonly IReadOnlyDictionary<EventType, Type> eventToType;

static BaseEvent() {

EventType ExtractEventType(Type type) {
var attr = type.GetCustomAttribute<EventTypeAttribute>();
if (attr is null) {
throw new InvalidOperationException($"Type {type} is missing {nameof(EventTypeAttribute)}");
}
return attr.EventType;
}

typeToEvent =
typeof(BaseEvent).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(BaseEvent)))
.ToDictionary(x => x, ExtractEventType);

eventToType = typeToEvent.ToDictionary(x => x.Value, x => x.Key);

// check that all event types are accounted for
var allEventTypes = Enum.GetValues<EventType>();
var missingEventTypes = allEventTypes.Except(eventToType.Keys).ToList();
if (missingEventTypes.Any()) {
throw new InvalidOperationException($"Missing event types: {string.Join(", ", missingEventTypes)}");
}
}


public EventType GetEventType() {
return
this switch {
EventNodeHeartbeat _ => EventType.NodeHeartbeat,
EventTaskHeartbeat _ => EventType.TaskHeartbeat,
EventPing _ => EventType.Ping,
EventInstanceConfigUpdated _ => EventType.InstanceConfigUpdated,
EventProxyCreated _ => EventType.ProxyCreated,
EventProxyDeleted _ => EventType.ProxyDeleted,
EventProxyFailed _ => EventType.ProxyFailed,
EventProxyStateUpdated _ => EventType.ProxyStateUpdated,
EventCrashReported _ => EventType.CrashReported,
EventRegressionReported _ => EventType.RegressionReported,
EventFileAdded _ => EventType.FileAdded,
EventTaskFailed _ => EventType.TaskFailed,
EventTaskStopped _ => EventType.TaskStopped,
EventTaskStateUpdated _ => EventType.TaskStateUpdated,
EventScalesetFailed _ => EventType.ScalesetFailed,
EventScalesetResizeScheduled _ => EventType.ScalesetResizeScheduled,
EventScalesetStateUpdated _ => EventType.ScalesetStateUpdated,
EventNodeStateUpdated _ => EventType.NodeStateUpdated,
EventNodeDeleted _ => EventType.NodeDeleted,
EventNodeCreated _ => EventType.NodeCreated,
EventJobStopped _ => EventType.JobStopped,
EventTaskCreated _ => EventType.TaskCreated,
var x => throw new NotSupportedException($"Unknown event type: {x.GetType()}"),
};
var type = this.GetType();
if (typeToEvent.TryGetValue(type, out var eventType)) {
return eventType;
}

throw new NotSupportedException($"Unknown event type: {type.GetType()}");
}

public static Type GetTypeInfo(EventType eventType) {
return (eventType) switch {
EventType.NodeHeartbeat => typeof(EventNodeHeartbeat),
EventType.InstanceConfigUpdated => typeof(EventInstanceConfigUpdated),
EventType.TaskHeartbeat => typeof(EventTaskHeartbeat),
EventType.Ping => typeof(EventPing),
EventType.ProxyCreated => typeof(EventProxyCreated),
EventType.ProxyDeleted => typeof(EventProxyDeleted),
EventType.ProxyFailed => typeof(EventProxyFailed),
EventType.ProxyStateUpdated => typeof(EventProxyStateUpdated),
EventType.CrashReported => typeof(EventCrashReported),
EventType.RegressionReported => typeof(EventRegressionReported),
EventType.FileAdded => typeof(EventFileAdded),
EventType.TaskFailed => typeof(EventTaskFailed),
EventType.TaskStopped => typeof(EventTaskStopped),
EventType.TaskStateUpdated => typeof(EventTaskStateUpdated),
EventType.NodeStateUpdated => typeof(EventNodeStateUpdated),
EventType.ScalesetFailed => typeof(EventScalesetFailed),
EventType.ScalesetResizeScheduled => typeof(EventScalesetResizeScheduled),
EventType.ScalesetStateUpdated => typeof(EventScalesetStateUpdated),
EventType.NodeDeleted => typeof(EventNodeDeleted),
EventType.NodeCreated => typeof(EventNodeCreated),
EventType.JobStopped => typeof(EventJobStopped),
EventType.TaskCreated => typeof(EventTaskCreated),
_ => throw new ArgumentException($"Unknown event type: {eventType}"),
};
if (eventToType.TryGetValue(eventType, out var type)) {
return type;
}

throw new ArgumentException($"Unknown event type: {eventType}");
}
};

Expand All @@ -103,14 +104,15 @@ public Type GetTypeInfo(object input) {
}
}

[EventType(EventType.TaskStopped)]
public record EventTaskStopped(
Guid JobId,
Guid TaskId,
UserInfo? UserInfo,
TaskConfig Config
) : BaseEvent();


[EventType(EventType.TaskFailed)]
public record EventTaskFailed(
Guid JobId,
Guid TaskId,
Expand All @@ -120,20 +122,22 @@ TaskConfig Config
) : BaseEvent();


//record EventJobCreated(
// Guid JobId,
// JobConfig Config,
// UserInfo? UserInfo
// ) : BaseEvent();
[EventType(EventType.JobCreated)]
record EventJobCreated(
Guid JobId,
JobConfig Config,
UserInfo? UserInfo
) : BaseEvent();


public record JobTaskStopped(
Guid TaskId,
TaskType TaskType,
Error? Error
) : BaseEvent();
);


[EventType(EventType.JobStopped)]
public record EventJobStopped(
Guid JobId,
JobConfig Config,
Expand All @@ -142,14 +146,15 @@ List<JobTaskStopped> TaskInfo
) : BaseEvent();


[EventType(EventType.TaskCreated)]
record EventTaskCreated(
Guid JobId,
Guid TaskId,
TaskConfig Config,
UserInfo? UserInfo
) : BaseEvent();


[EventType(EventType.TaskStateUpdated)]
public record EventTaskStateUpdated(
Guid JobId,
Guid TaskId,
Expand All @@ -159,101 +164,116 @@ TaskConfig Config
) : BaseEvent();


[EventType(EventType.TaskHeartbeat)]
public record EventTaskHeartbeat(
Guid JobId,
Guid TaskId,
TaskConfig Config
) : BaseEvent();

[EventType(EventType.Ping)]
public record EventPing(
Guid PingId
) : BaseEvent();

//record EventScalesetCreated(
// Guid ScalesetId,
// PoolName PoolName,
// string VmSku,
// string Image,
// Region Region,
// int Size) : BaseEvent();

[EventType(EventType.ScalesetCreated)]
record EventScalesetCreated(
Guid ScalesetId,
PoolName PoolName,
string VmSku,
string Image,
Region Region,
int Size) : BaseEvent();


[EventType(EventType.ScalesetFailed)]
public record EventScalesetFailed(
Guid ScalesetId,
PoolName PoolName,
Error Error
) : BaseEvent();


//record EventScalesetDeleted(
// Guid ScalesetId,
// PoolName PoolName,
[EventType(EventType.ScalesetDeleted)]
record EventScalesetDeleted(
Guid ScalesetId,
PoolName PoolName

// ) : BaseEvent();
) : BaseEvent();


[EventType(EventType.ScalesetResizeScheduled)]
public record EventScalesetResizeScheduled(
Guid ScalesetId,
PoolName PoolName,
long size
) : BaseEvent();


//record EventPoolDeleted(
// PoolName PoolName
// ) : BaseEvent();
[EventType(EventType.PoolDeleted)]
record EventPoolDeleted(
PoolName PoolName
) : BaseEvent();


//record EventPoolCreated(
// PoolName PoolName,
// Os Os,
// Architecture Arch,
// bool Managed,
// AutoScaleConfig? Autoscale
// ) : BaseEvent();
[EventType(EventType.PoolCreated)]
record EventPoolCreated(
PoolName PoolName,
Os Os,
Architecture Arch,
bool Managed
// ignoring AutoScaleConfig because it's not used anymore
//AutoScaleConfig? Autoscale
) : BaseEvent();


[EventType(EventType.ProxyCreated)]
public record EventProxyCreated(
Region Region,
Guid? ProxyId
) : BaseEvent();


[EventType(EventType.ProxyDeleted)]
public record EventProxyDeleted(
Region Region,
Guid? ProxyId
) : BaseEvent();


[EventType(EventType.ProxyFailed)]
public record EventProxyFailed(
Region Region,
Guid? ProxyId,
Error Error
) : BaseEvent();


[EventType(EventType.ProxyStateUpdated)]
public record EventProxyStateUpdated(
Region Region,
Guid ProxyId,
VmState State
) : BaseEvent();


[EventType(EventType.NodeCreated)]
public record EventNodeCreated(
Guid MachineId,
Guid? ScalesetId,
PoolName PoolName
) : BaseEvent();



[EventType(EventType.NodeHeartbeat)]
public record EventNodeHeartbeat(
Guid MachineId,
Guid? ScalesetId,
PoolName PoolName
) : BaseEvent();


[EventType(EventType.NodeDeleted)]
public record EventNodeDeleted(
Guid MachineId,
Guid? ScalesetId,
Expand All @@ -262,26 +282,31 @@ public record EventNodeDeleted(
) : BaseEvent();


[EventType(EventType.ScalesetStateUpdated)]
public record EventScalesetStateUpdated(
Guid ScalesetId,
PoolName PoolName,
ScalesetState State
) : BaseEvent();

[EventType(EventType.NodeStateUpdated)]
record EventNodeStateUpdated(
Guid MachineId,
Guid? ScalesetId,
PoolName PoolName,
NodeState state
) : BaseEvent();

[EventType(EventType.CrashReported)]
public record EventCrashReported(
Report Report,
Container Container,
[property: JsonPropertyName("filename")] String FileName,
TaskConfig? TaskConfig
) : BaseEvent();


[EventType(EventType.RegressionReported)]
public record EventRegressionReported(
RegressionReport RegressionReport,
Container Container,
Expand All @@ -290,12 +315,14 @@ public record EventRegressionReported(
) : BaseEvent();


[EventType(EventType.FileAdded)]
public record EventFileAdded(
Container Container,
[property: JsonPropertyName("filename")] String FileName
) : BaseEvent();


[EventType(EventType.InstanceConfigUpdated)]
public record EventInstanceConfigUpdated(
InstanceConfig Config
) : BaseEvent();
Expand Down
15 changes: 15 additions & 0 deletions src/ApiService/Tests/EventsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using Microsoft.OneFuzz.Service;
using Xunit;

namespace Tests;

public class EventTests {

[Fact]
static void CheckAllEventClass() {
// instantiate one event to force the static constructor to run
var testEvent = new EventPing(Guid.Empty);

}
}