From c2a5b48f40f96279770854dc3df56da65f4222be Mon Sep 17 00:00:00 2001 From: pranav-super Date: Wed, 23 Oct 2024 12:40:35 -0700 Subject: [PATCH] add source support WIP --- .../ExternalEventsSourceQueryGoal.java | 32 +++++++++++++++++ ....java => ExternalEventsTypeQueryGoal.java} | 2 +- .../scheduling/ExternalEventsTests.java | 35 +++++++++++++++++-- .../timeline/collections/ExternalEvents.kt | 5 +-- .../timeline/payloads/ExternalEvent.kt | 6 ++-- .../timeline/payloads/ExternalSource.kt | 15 ++++++++ .../procedural/timeline/plan/EventQuery.kt | 9 +++-- .../scheduler/solver/PrioritySolver.java | 7 ++-- .../plan/SchedulerToProcedurePlanAdapter.kt | 4 ++- .../GraphQLMerlinDatabaseService.java | 7 ++-- 10 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsSourceQueryGoal.java rename e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/{ExternalEventsQueryGoal.java => ExternalEventsTypeQueryGoal.java} (94%) create mode 100644 procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/payloads/ExternalSource.kt diff --git a/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsSourceQueryGoal.java b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsSourceQueryGoal.java new file mode 100644 index 0000000000..bc285a9d98 --- /dev/null +++ b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsSourceQueryGoal.java @@ -0,0 +1,32 @@ +package gov.nasa.jpl.aerie.e2e.procedural.scheduling.procedures; + +import gov.nasa.ammos.aerie.procedural.scheduling.Goal; +import gov.nasa.ammos.aerie.procedural.scheduling.annotations.SchedulingProcedure; +import gov.nasa.ammos.aerie.procedural.scheduling.plan.EditablePlan; +import gov.nasa.ammos.aerie.procedural.timeline.payloads.ExternalSource; +import gov.nasa.ammos.aerie.procedural.timeline.payloads.activities.DirectiveStart; +import gov.nasa.ammos.aerie.procedural.timeline.plan.EventQuery; +import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +@SchedulingProcedure +public record ExternalEventsSourceQueryGoal() implements Goal { + @Override + public void run(@NotNull final EditablePlan plan) { + + // demonstrate more complicated query functionality + EventQuery eventQuery = new EventQuery( + null, + null, + List.of(new ExternalSource("NewTest.json", "TestGroup_2")) + ); + + for (final var e: plan.events(eventQuery)) { + plan.create("BiteBanana", new DirectiveStart.Absolute(e.getInterval().start), Map.of("biteSize", SerializedValue.of(1))); + } + plan.commit(); + } +} diff --git a/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsQueryGoal.java b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsTypeQueryGoal.java similarity index 94% rename from e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsQueryGoal.java rename to e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsTypeQueryGoal.java index dcd3644786..c6793d8f82 100644 --- a/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsQueryGoal.java +++ b/e2e-tests/src/main/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/procedures/ExternalEventsTypeQueryGoal.java @@ -12,7 +12,7 @@ import java.util.Map; @SchedulingProcedure -public record ExternalEventsQueryGoal() implements Goal { +public record ExternalEventsTypeQueryGoal() implements Goal { @Override public void run(@NotNull final EditablePlan plan) { diff --git a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java index db3de04e7f..0b9d1b68f0 100644 --- a/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java +++ b/e2e-tests/src/test/java/gov/nasa/jpl/aerie/e2e/procedural/scheduling/ExternalEventsTests.java @@ -164,10 +164,10 @@ void testExternalEventSimple() throws IOException { } @Test - void testExternalEventQuery() throws IOException { + void testExternalEventTypeQuery() throws IOException { // first, run the goal try (final var gateway = new GatewayRequests(playwright)) { - int procedureJarId = gateway.uploadJarFile("build/libs/ExternalEventsQueryGoal.jar"); + int procedureJarId = gateway.uploadJarFile("build/libs/ExternalEventsTypeQueryGoal.jar"); // Add Scheduling Procedure procedureId = hasura.createSchedulingSpecProcedure( "Test Scheduling Procedure", @@ -205,4 +205,35 @@ void testExternalEventQuery() throws IOException { assertEquals(activityStartTime.toString(), expected.get(i).start_time()); } } + + @Test + void testExternalEventSourceQuery() throws IOException { + // first, run the goal + try (final var gateway = new GatewayRequests(playwright)) { + int procedureJarId = gateway.uploadJarFile("build/libs/ExternalEventsSourceQueryGoal.jar"); + // Add Scheduling Procedure + procedureId = hasura.createSchedulingSpecProcedure( + "Test Scheduling Procedure", + procedureJarId, + specId, + 0 + ); + } + hasura.awaitScheduling(specId); + final var plan = hasura.getPlan(planId); + final var activities = plan.activityDirectives(); + + // ensure the orderings line up + activities.sort(Comparator.comparing(Plan.ActivityDirective::startOffset)); + + // compare arrays + assertEquals(additionalExternalEvents.size(), activities.size()); + for (int i = 0; i < activities.size(); i++) { + Instant activityStartTime = Duration.addToInstant( + Instant.parse(planStartTimestamp), + Duration.fromString(activities.get(i).startOffset()) + ); + assertEquals(activityStartTime.toString(), additionalExternalEvents.get(i).start_time()); + } + } } diff --git a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/collections/ExternalEvents.kt b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/collections/ExternalEvents.kt index 59b7decf0c..00ea957b43 100644 --- a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/collections/ExternalEvents.kt +++ b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/collections/ExternalEvents.kt @@ -6,6 +6,7 @@ import gov.nasa.ammos.aerie.procedural.timeline.payloads.activities.Instance import gov.nasa.ammos.aerie.procedural.timeline.ops.* import gov.nasa.ammos.aerie.procedural.timeline.ops.coalesce.CoalesceNoOp import gov.nasa.ammos.aerie.procedural.timeline.payloads.ExternalEvent +import gov.nasa.ammos.aerie.procedural.timeline.payloads.ExternalSource import gov.nasa.ammos.aerie.procedural.timeline.util.preprocessList /** @@ -23,8 +24,8 @@ data class ExternalEvents(private val timeline: Timeline { - override fun withNewInterval(i: Interval) = ExternalEvent(key, type, source, derivationGroup, i) + override fun withNewInterval(i: Interval) = ExternalEvent(key, type, source, i) } diff --git a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/payloads/ExternalSource.kt b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/payloads/ExternalSource.kt new file mode 100644 index 0000000000..a9a88feb11 --- /dev/null +++ b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/payloads/ExternalSource.kt @@ -0,0 +1,15 @@ +package gov.nasa.ammos.aerie.procedural.timeline.payloads + +import gov.nasa.ammos.aerie.procedural.timeline.Interval +import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue + +/** + * An external source instance. Used for querying purposes - see EventQuery.kt. + * The included fields represent the primary key used to identify External Sources. + */ +data class ExternalSource( + /** The string name of this source. */ + val key: String, + /** The derivation group that this source is a member of. */ + val derivationGroup: String, +) diff --git a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt index a9c80c4be1..8e83478780 100644 --- a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt +++ b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/EventQuery.kt @@ -1,5 +1,7 @@ package gov.nasa.ammos.aerie.procedural.timeline.plan +import gov.nasa.ammos.aerie.procedural.timeline.payloads.ExternalSource + /** Fields for filtering events as they are queried. */ data class EventQuery( /** @@ -17,13 +19,14 @@ data class EventQuery( val eventTypes: List?, /** - * A nullable list of sources; the event must belong to one of them if present. + * A nullable list of sources (described as a tuple of the source's (key, derivation group name)); the event must + * belong to one of them if present. * * If null, all sources are allowed. */ - val sources: List?, + val sources: List?, ) { - constructor(derivationGroup: String?, eventType: String?, source: String?): this( + constructor(derivationGroup: String?, eventType: String?, source: ExternalSource?): this( derivationGroup?.let { listOf(it) }, eventType?.let { listOf(it) }, source?.let { listOf(it) } diff --git a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java index fe17cffee1..f14be89a03 100644 --- a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java +++ b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/solver/PrioritySolver.java @@ -46,7 +46,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static gov.nasa.jpl.aerie.merlin.protocol.types.Duration.MICROSECOND; import static gov.nasa.jpl.aerie.merlin.protocol.types.Duration.ZERO; -import static gov.nasa.jpl.aerie.merlin.protocol.types.Duration.min; /** * prototype scheduling algorithm that schedules activities for a plan @@ -618,7 +617,7 @@ private Optional makeActivityNetworkConflict( curPreviouslyInstantiated = null; } taskNetwork.startsAfterStart( - allActivitiesInNetwork.getLast(), + allActivitiesInNetwork.get(allActivitiesInNetwork.size()), activityName, missingRecurrenceConflict.minMaxConstraints.start, missingRecurrenceConflict.minMaxConstraints.end); @@ -635,12 +634,12 @@ private Optional makeActivityNetworkConflict( //add constraints between last task and end boundary if (missingRecurrenceConflict.afterBoundIsActivity) { taskNetwork.addStartInterval( - allActivitiesInNetwork.getLast(), + allActivitiesInNetwork.get(allActivitiesInNetwork.size()), missingRecurrenceConflict.nextStart.minus(missingRecurrenceConflict.minMaxConstraints.end), missingRecurrenceConflict.nextStart.minus(missingRecurrenceConflict.minMaxConstraints.start)); } else { taskNetwork.addStartInterval( - allActivitiesInNetwork.getLast(), + allActivitiesInNetwork.get(allActivitiesInNetwork.size()), missingRecurrenceConflict.nextStart.minus(missingRecurrenceConflict.minMaxConstraints.end) , missingRecurrenceConflict.nextStart); } diff --git a/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt b/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt index c23b5cbdbc..192253eda7 100644 --- a/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt +++ b/scheduler-driver/src/main/kotlin/gov/nasa/jpl/aerie/scheduler/plan/SchedulerToProcedurePlanAdapter.kt @@ -66,7 +66,9 @@ data class SchedulerToProcedurePlanAdapter( } else eventsByDerivationGroup.values.flatten() if (query.eventTypes != null) result = result.filter { it.type in query.eventTypes!! } - if (query.sources != null) result = result.filter { it.source in query.sources!! } + if (query.sources != null) result = result.filter { event -> + query.sources!!.map { it.key }.contains(event.source.key) && query.sources!!.map { it.derivationGroup }.contains(event.source.key) + } return ExternalEvents(result) } override fun > resource( diff --git a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinDatabaseService.java b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinDatabaseService.java index 1b1ca72a2b..100d90ef29 100644 --- a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinDatabaseService.java +++ b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/services/GraphQLMerlinDatabaseService.java @@ -2,6 +2,7 @@ import gov.nasa.ammos.aerie.procedural.timeline.Interval; import gov.nasa.ammos.aerie.procedural.timeline.payloads.ExternalEvent; +import gov.nasa.ammos.aerie.procedural.timeline.payloads.ExternalSource; import gov.nasa.jpl.aerie.constraints.model.DiscreteProfile; import gov.nasa.jpl.aerie.constraints.model.LinearProfile; import gov.nasa.jpl.aerie.json.BasicParsers; @@ -1185,8 +1186,10 @@ private List parseExternalEvents(final JsonArray eventsJson, fina result.add(new ExternalEvent( e.getString("event_key"), e.getString("event_type_name"), - e.getString("source_key"), - e.getString("derivation_group_name"), + new ExternalSource( + e.getString("source_key"), + e.getString("derivation_group_name") + ), Interval.between(start, end) )); }