diff --git a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/DurationLike.java b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/DurationLike.java deleted file mode 100644 index eaead3b433..0000000000 --- a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/DurationLike.java +++ /dev/null @@ -1,7 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.driver.engine; - -import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; - -public interface DurationLike { - Duration project(); -} diff --git a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/JobSchedule.java b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/JobSchedule.java index a93ec25818..d4ffdd731c 100644 --- a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/JobSchedule.java +++ b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/JobSchedule.java @@ -11,7 +11,7 @@ import java.util.PriorityQueue; import java.util.Set; -public final class JobSchedule> { +public final class JobSchedule { /** The scheduled time for each upcoming job. */ private final Map scheduledJobs = new HashMap<>(); diff --git a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/SchedulingInstant.java b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/SchedulingInstant.java index fe18a7f751..76e891e978 100644 --- a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/SchedulingInstant.java +++ b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/SchedulingInstant.java @@ -3,9 +3,8 @@ import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; public record SchedulingInstant(Duration offsetFromStart, SubInstant priority) - implements DurationLike, Comparable + implements Comparable { - @Override public Duration project() { return this.offsetFromStart; } @@ -14,10 +13,6 @@ public Duration project() { public int compareTo(final SchedulingInstant o) { final var x = this.offsetFromStart.compareTo(o.offsetFromStart); if (x != 0) return x; - - final var y = this.priority.compareTo(o.priority); - if (y != 0) return y; - - return 0; + return this.priority.compareTo(o.priority); } } diff --git a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/TaskSource.java b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/TaskSource.java deleted file mode 100644 index b71f3402b6..0000000000 --- a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/engine/TaskSource.java +++ /dev/null @@ -1,8 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.driver.engine; - -import gov.nasa.jpl.aerie.merlin.protocol.model.Task; - -/** The source of the definition of a task's behavior. */ -public interface TaskSource { - Task createTask(); -} diff --git a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/timeline/EffectExpressionDisplay.java b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/timeline/EffectExpressionDisplay.java index 724847e2ab..c16c841f5f 100644 --- a/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/timeline/EffectExpressionDisplay.java +++ b/merlin-driver/src/main/java/gov/nasa/jpl/aerie/merlin/driver/timeline/EffectExpressionDisplay.java @@ -3,7 +3,6 @@ import gov.nasa.jpl.aerie.merlin.protocol.model.EffectTrait; import java.util.Objects; -import java.util.Optional; import java.util.function.Function; /** diff --git a/merlin-framework/src/main/java/gov/nasa/jpl/aerie/merlin/framework/CellRef.java b/merlin-framework/src/main/java/gov/nasa/jpl/aerie/merlin/framework/CellRef.java index 9d3153b871..aff20238e7 100644 --- a/merlin-framework/src/main/java/gov/nasa/jpl/aerie/merlin/framework/CellRef.java +++ b/merlin-framework/src/main/java/gov/nasa/jpl/aerie/merlin/framework/CellRef.java @@ -4,7 +4,6 @@ import gov.nasa.jpl.aerie.merlin.protocol.driver.Topic; import gov.nasa.jpl.aerie.merlin.protocol.model.CellType; -import java.util.Objects; import java.util.function.Function; public final class CellRef { diff --git a/merlin-sdk/kernels/e41.mk b/merlin-sdk/kernels/e41.mk deleted file mode 100644 index 239f8ac2f1..0000000000 --- a/merlin-sdk/kernels/e41.mk +++ /dev/null @@ -1,9 +0,0 @@ -\begindata -PATH_VALUES = ('kernels') -PATH_SYMBOLS = ('KERNEL_PATH') - -KERNELS_TO_LOAD = ( -'$KERNEL_PATH/moon_080317.tf' -,'$KERNEL_PATH/phobos512.bds' -) - diff --git a/merlin-sdk/kernels/moon_080317.tf b/merlin-sdk/kernels/moon_080317.tf deleted file mode 100644 index 4f39138c5b..0000000000 --- a/merlin-sdk/kernels/moon_080317.tf +++ /dev/null @@ -1,606 +0,0 @@ -KPL/FK - - - SPICE Lunar Reference Frame Specification Kernel - ===================================================================== - - Original file name: moon_080317.tf - Creation date: 2008 March 17 20:10 - Created by: Nat Bachman (NAIF/JPL) - Date of last revision: 2008 March 21 16:07 - Purpose of revision: - - Changed names of PA system and frame from "principal axis" to - "principal axes." - - - Version description: - - This frame kernel contains lunar frame specifications compatible - with the current lunar binary PCK file - - moon_pa_de421_1900-2050.bpc - - The above PCK contains lunar orientation data from the DE-421 JPL - Planetary Ephemeris. - - The previous NAIF lunar frame specification kernel was - - moon_071218.tf - - That kernel is compatible with the DE-418-based lunar binary PCK - file - - moon_pa_de418_1950-2050.bpc - - The comment section below titled "Lunar body-fixed frame - associations" discusses lunar frame association kernels. These - kernels direct portions of the SPICE system that rely on default - body-fixed reference frames to associate with the Moon either the - MOON_ME or MOON_PA reference frames. - - - This file was modified on 26-FEB-2009 by Nat Bachman. The initial - blank line was removed and this change description was added. - Nothing else has been changed. - - - Frames Specified by this Kernel - ===================================================================== - - Frame Name Relative to Type Frame ID - -------------- ----------------- ----- -------- - MOON_PA MOON_PA_DE421 FIXED 31000 - MOON_ME MOON_ME_DE421 FIXED 31001 - MOON_PA_DE421 ICRF/J2000 PCK 31006 - MOON_ME_DE421 MOON_PA_DE421 FIXED 31007 - - - Introduction - ===================================================================== - - This kernel specifies lunar body-fixed reference frames for use by - SPICE-based application software. These reference frames are - associated with high-accuracy lunar orientation data provided by the - JPL Solar System Dynamics Group's planetary ephemerides (both - trajectory and lunar orientation data are stored in these ephemeris - files). These ephemerides have names of the form DE-nnn (DE stands - for "developmental ephemeris"). - - The frames specified by this kernel are realizations of two different - lunar reference systems: - - Principal Axes (PA) system - -------------------------- - The axes of this system are defined by the principal axes of the - Moon. Due to the nature of the Moon's orbit and - rotation, the Z axis of this system does not coincide with the - Moon's mean spin axis, nor does the X axis coincide with the mean - direction to the center of the Earth (in contrast with the ME - system defined below). - - Lunar principal axes frames realizing the lunar PA system and - specified by this kernel are associated with JPL planetary - ephemerides. Each new JPL planetary ephemeris can (but does not - necessarily) define a new realization of the lunar principal axes - system. Coordinates of lunar surface features expressed in lunar - PA frames can change slightly from one lunar ephemeris version to - the next. - - - Mean Earth/Polar Axis (ME) system - --------------------------------- - The Lunar mean Earth/polar axis system is a lunar body-fixed - reference system used in the IAU/IAG Working Group Report [2] to - describe the orientation of the Moon relative to the ICRF frame. - The +Z axis of this system is aligned with the north mean lunar - rotation axis, while the prime meridian contains the the mean - Earth direction. - - This system is also sometimes called the "mean Earth/mean - rotation axis" system or "mean Earth" system. - - The mean directions used to define the axes of a mean Earth/polar - axis reference frame realizing the lunar ME system and specified - by this kernel are associated with a given JPL planetary - ephemeris version. The rotation between the mean Earth frame for - a given ephemeris version and the associated principal axes frame - is given by a constant matrix (see [1]). - - - For the current JPL planetary ephemeris (DE), this kernel includes - specifications of the corresponding principal axes and mean Earth/ - polar axis frames. The names of these frames have the form - - MOON_PA_DEnnn - - and - - MOON_ME_DEnnn - - respectively, where nnn is the version number of the DE. The set of - DE-dependent frame specifications will grow over time; frame - specifications pertaining to older DEs can be obtained from earlier - versions of this frame kernel. - - For each of the two reference systems, there is a corresponding - "generic" frame specification: these generic frames are simply - aliases for the PA and ME frames associated with the latest DE. The - generic frame names are - - MOON_PA - MOON_ME - - These generic frame names are provided to enable SPICE-based - applications to refer to the latest DE-based (or other) lunar - rotation data without requiring code modifications as new kernels - become available. SPICE users may, if they wish, modify this kernel - to assign these frame aliases to other frames than those selected - here, for example, older DE-based frames. NAIF recommends that, if - this frame kernel is modified, the name of this file also be changed - to avoid confusion. - - - Comparison of PA and ME frames - ------------------------------ - - The rotation between the mean Earth frame for a given DE and the - associated principal axes frame for the same DE is given by a - constant matrix (see [1]). For DE-421, the rotation angle of this - matrix is approximately 0.0288473 degrees; this is equivalent to - approximately 875 m when expressed as a displacement along a great - circle on the Moon's surface. - - - Comparison of DE-based and IAU/IAG report-based ME frames - --------------------------------------------------------- - - Within the SPICE system, a lunar ME frame specified by the - rotational elements from the IAU/IAG Working Group report [2] is - given the name IAU_MOON; the data defining this frame are provided - in a generic text PCK. - - The orientation of the lunar ME frame obtained by applying the - DE-based PA-to-ME rotation described above to the DE-based lunar - libration data does not agree closely with the lunar ME frame - orientation given by the rotational elements from the IAU/IAG - Working Group report (that is, the IAU_MOON frame). The difference - is due to truncation of the libration series used in the report's - formula for lunar orientation (see [1]). - - In the case of DE-421, for the time period ~2000-2020, the - time-dependent difference of these ME frame implementations has an - amplitude of approximately 0.0051 degrees, which is equivalent to - approximately 155 m, measured along a great circle on the Moon's - surface, while the average value is approximately 0.00249 degrees, - or 76 m. - - - Comparison of DE-421 and DE-418 Lunar Reference Frames - ====================================================== - - The magnitudes of the rotational offsets between the - DE-418 and DE-421 realizations of the MOON_PA and MOON_ME - frames are discussed below. - - Note that the angle ranges shown below are ordered as signed values, - *not* by absolute value. - - MOON_PA frame orientation differences - ------------------------------------- - - Tests performed by NAIF indicate an approximately 0.45 microradian - maximum rotation between the MOON_PA_DE418 and MOON_PA_DE421 frames, - based on a sampling of orientation data over the time period - 2000-2020. This offset corresponds to a displacement of about 0.79 m - along a great circle on the Moon's surface. - - When the transformation from the MOON_PA_DE418 frame to the - MOON_PA_DE421 frame is decomposed as a 1-2-3 Euler angle sequence, - the offset angle ranges for each axis are: - - X axis: -3.8063e-07 to -2.9746e-07 radians - Y axis: -2.5322e-07 to -1.8399e-07 radians - Z axis: -9.9373e-08 to 6.0046e-08 radians - - - MOON_ME frame orientation differences - ------------------------------------- - - Tests performed by NAIF indicate an approximately 0.27 microradian - maximum rotation between the MOON_ME_DE418 and MOON_ME_DE421 frames, - based on a sampling of orientation data over the time period - 2000-2020. This offset corresponds to a displacement of about 0.46 m - along a great circle on the Moon's surface. - - When the transformation from the MOON_ME_DE418 frame to the - MOON_ME_DE421 frame is decomposed as a 1-2-3 Euler angle sequence, - the offset angle ranges for each axis are: - - X axis: 7.2260e-09 to 9.0391e-08 radians - Y axis: 3.7643e-08 to 1.0691e-07 radians - Z axis: -2.4471e-07 to -8.5296e-08 radians - - - Regarding Use of the ICRF in SPICE - ================================== - - The IERS Celestial Reference Frame (ICRF) is offset from the J2000 - reference frame (equivalent to EME 2000) by a small rotation: the - J2000 pole offset magnitude is about 18 milliarcseconds (mas) and - the equinox offset magnitude is approximately 78 milliarcseconds - (see [3]). - - Certain SPICE data products use the frame label "J2000" for data - that actually are referenced to the ICRF. This is the case for SPK - files containing JPL version DE-4nn planetary ephemerides, for - orientation data from generic text PCKs, and for binary PCKs, - including binary lunar PCKs used in conjunction with this lunar - frame kernel. - - Consequently, when SPICE computes the rotation between the "J2000" - frame and either of the lunar PA or ME frames, what's computed is - actually the rotation between the ICRF and the respective lunar - frame. - - Similarly, when SPICE is used to compute the state given by a JPL DE - planetary ephemeris SPK file of one ephemeris object relative to - another (for example, the state of the Moon with respect to the - Earth), expressed relative to the frame "J2000," the state is - actually expressed relative to the ICRF. - - Because SPICE is already using the ICRF, users normally need not - use the J2000-to-ICRF transformation to adjust results computed - with SPICE. - - Lunar body-fixed frame associations - ===================================================================== - - By default, the SPICE system considers the body-fixed reference - frame associated with the Moon to be the one named IAU_MOON. This - body-frame association affects the outputs of the SPICE frame system - routines - - CIDFRM - CNMFRM - - and of the SPICE time conversion and geometry routines - - ET2LST - ILLUM - SRFXPT - SUBPT - SUBSOL - - Also, any code that calls these routines to obtain results involving - lunar body-fixed frames are affected. Within SPICE, the only - higher-level system that is affected is the dynamic frame system. - - NAIF provides "frame association" kernels that simplify changing the - body-fixed frame associated with the Moon. Using FURNSH to load - either of the kernels named below changes the Moon's body-fixed - frame from its current value, which initially is IAU_MOON, to that - shown in the right-hand column: - - Kernel name Lunar body-fixed frame - ----------- ---------------------- - moon_assoc_me.tf MOON_ME - moon_assoc_pa.tf MOON_PA - - For further information see the in-line comments in the association - kernels themselves. Also see the Frames Required Reading section - titled "Connecting an Object to its Body-fixed Frame." - - In the N0062 SPICE Toolkit, the routines - - ILLUM - SRFXPT - SUBPT - SUBSOL - - are superseded, respectively, by the routines - - ILUMIN - SINCPT - SUBPNT - SUBSLR - - The newer routines don't require frame association kernels: the name - of the target body's body-fixed reference frame is an input argument - to these routines. - - - Using this Kernel - ===================================================================== - - In order for a SPICE-based application to use reference frames - specified by this kernel, the application must load both this kernel - and a binary lunar PCK containing lunar orientation data for the - time of interest. Normally the kernels need be loaded only once - during program initialization. - - SPICE users may find it convenient to use a meta-kernel (also called - a "FURNSH kernel") to name the kernels to be loaded. Below, we show - an example of such a meta-kernel, as well as the source code of a - small Fortran program that uses lunar body fixed frames. The - program's output is included as well. - - The kernel names shown here are simply used as examples; users must - select the kernels appropriate for their applications. - - Numeric results shown below may differ very slightly from those - obtained on users' computer systems. - - - Meta-kernel - ----------- - - - KPL/MK - - - Example meta-kernel showing use of - - - binary lunar PCK - - generic lunar frame kernel (FK) - - leapseconds kernel (LSK) - - planetary SPK - - 17-MAR-2008 (NJB) - - Note: to actually use this kernel, replace the @ characters - below with backslashes (\). The backslash character cannot be - used here, within the comments of this frame kernel, because the - begindata and begintext strings would be interpreted as - directives bracketing actual load commands. - - This meta-kernel assumes that the referenced kernels exist - in the user's current working directory. - - @begindata - - KERNELS_TO_LOAD = ( 'moon_pa_de421_1900-2050.bpc' - 'moon_080317.tf' - 'leapseconds.ker' - 'de421.bsp' ) - - @begintext - - - Example program - --------------- - - PROGRAM EX1 - IMPLICIT NONE - - INTEGER FILSIZ - PARAMETER ( FILSIZ = 255 ) - - CHARACTER*(FILSIZ) META - - DOUBLE PRECISION ET - DOUBLE PRECISION LT - DOUBLE PRECISION STME ( 6 ) - DOUBLE PRECISION STPA ( 6 ) - - C - C Prompt user for meta-kernel name. - C - CALL PROMPT ( 'Enter name of meta-kernel > ', META ) - - C - C Load lunar PCK, generic lunar frame kernel, - C leapseconds kernel, and planetary ephemeris - C via metakernel. - C - CALL FURNSH ( META ) - - C - C Convert a time of interest from UTC to ET. - C - CALL STR2ET ( '2008 MAR 17 20:10:00', ET ) - - WRITE (*,*) 'ET (sec past J2000 TDB): ', ET - WRITE (*,*) ' State of Earth relative to Moon' - - C - C Find the geometric state of the Earth relative to the - C Moon at ET, expressed relative to the ME frame. - C - CALL SPKEZR ( 'Earth', ET, 'MOON_ME', - . 'NONE', 'Moon', STME, LT ) - - WRITE (*,*) ' In MOON_ME frame:' - WRITE (*,*) STME - - C - C Find the geometric state of the Earth relative to the - C Moon at ET, expressed relative to the PA frame. - C - CALL SPKEZR ( 'Earth', ET, 'MOON_PA', - . 'NONE', 'Moon', STPA, LT ) - - WRITE (*,*) ' In MOON_PA frame:' - WRITE (*,*) STPA - - END - - - Program output - -------------- - - Enter name of meta-kernel > meta - ET (sec past J2000 TDB): 259056665. - State of Earth relative to Moon - In MOON_ME frame: - 379892.825 33510.118 -12661.5278 0.0400357582 0.0117963334 0.115130508 - In MOON_PA frame: - 379908.634 33385.003 -12516.8859 0.0399957879 0.0117833314 0.115145731 - - - - References - ===================================================================== - - [1] J.G. Williams, D.H. Boggs and W.M. Folkner. "DE421 Lunar - Orbit, Physical Librations, and Surface Coordinates," - preprint of JPL IOM 335-JW,DB,WF-20080314-001, dated - March 14, 2008. - - [2] Seidelmann, P.K., Abalakin, V.K., Bursa, M., Davies, M.E., - Bergh, C. de, Lieske, J.H., Oberst, J., Simon, J.L., Standish, - E.M., Stooke, P., and Thomas, P.C. (2002). "Report of the - IAU/IAG Working Group on Cartographic Coordinates and Rotational - Elements of the Planets and Satellites: 2000," Celestial - Mechanics and Dynamical Astronomy, v.82, Issue 1, pp. 83-111. - - [3] Roncoli, R. (2005). "Lunar Constants and Models Document," - JPL D-32296. - - - Frame Specifications - ===================================================================== - - MOON_PA is the name of the generic lunar principal axes (PA) reference - frame. This frame is an alias for the principal axes frame defined - by the latest version of the JPL Solar System Dynamics Group's - planetary ephemeris. - - In this instance of the lunar reference frames kernel, MOON_PA is an - alias for the lunar principal axes frame associated with the - planetary ephemeris DE-421. - - \begindata - - FRAME_MOON_PA = 31000 - FRAME_31000_NAME = 'MOON_PA' - FRAME_31000_CLASS = 4 - FRAME_31000_CLASS_ID = 31000 - FRAME_31000_CENTER = 301 - - TKFRAME_31000_SPEC = 'MATRIX' - TKFRAME_31000_RELATIVE = 'MOON_PA_DE421' - TKFRAME_31000_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - - \begintext - - MOON_ME is the name of the generic lunar mean Earth/polar axis (ME) - reference frame. This frame is an alias for the mean Earth/polar - axis frame defined by the latest version of the JPL Solar System - Dynamics Group's planetary ephemeris. - - In this instance of the lunar reference frames kernel, MOON_ME is an - alias for the lunar mean Earth/polar axis frame associated with the - planetary ephemeris DE-421. - - \begindata - - FRAME_MOON_ME = 31001 - FRAME_31001_NAME = 'MOON_ME' - FRAME_31001_CLASS = 4 - FRAME_31001_CLASS_ID = 31001 - FRAME_31001_CENTER = 301 - - TKFRAME_31001_SPEC = 'MATRIX' - TKFRAME_31001_RELATIVE = 'MOON_ME_DE421' - TKFRAME_31001_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - - - \begintext - - - MOON_PA_DE421 is the name of the lunar principal axes - reference frame defined by JPL's DE-421 planetary ephemeris. - - \begindata - - FRAME_MOON_PA_DE421 = 31006 - FRAME_31006_NAME = 'MOON_PA_DE421' - FRAME_31006_CLASS = 2 - FRAME_31006_CLASS_ID = 31006 - FRAME_31006_CENTER = 301 - - FRAME_MOON_PA_DE403 = 31002 - FRAME_31002_NAME = 'MOON_PA_DE403' - FRAME_31002_CLASS = 2 - FRAME_31002_CLASS_ID = 31002 - FRAME_31002_CENTER = 301 - - - - - \begintext - - MOON_ME_DE421 is the name of the lunar mean Earth/polar - axis reference frame defined by JPL's DE-421 planetary ephemeris. - - Rotation angles are from reference [1]. - - \begindata - - FRAME_MOON_ME_DE421 = 31007 - FRAME_31007_NAME = 'MOON_ME_DE421' - FRAME_31007_CLASS = 4 - FRAME_31007_CLASS_ID = 31007 - FRAME_31007_CENTER = 301 - - TKFRAME_31007_SPEC = 'ANGLES' - TKFRAME_31007_RELATIVE = 'MOON_PA_DE421' - TKFRAME_31007_ANGLES = ( 67.92 78.56 0.30 ) - TKFRAME_31007_AXES = ( 3, 2, 1 ) - TKFRAME_31007_UNITS = 'ARCSECONDS' - - \begintext - - - Updating this Kernel - -------------------- - - When a new JPL DE providing lunar rotation data becomes available, - the new lunar PA frame associated with that data set will be named - - MOON_PA_DEnnn - - where nnn is the version number of the DE. - - The PCK body ID code associated with that data set will be - - 31008 - - The frame ID and class ID for this frame will also be 31008. - - The generic PA frame specification will be updated to point to the - new DE-specific PA frame. The rest of this frame specification - is unchanged. - - The ME frame name associated with the new data set will be named - - MOON_ME_DEnnn - - The frame ID and class ID for this frame will be - - 31009 - - The rotational offset between this frame and the new DE-specific PA - frame will need to be updated; this offset is DE-dependent. - - The generic ME frame specification will be updated to point to the - new DE-specific ME frame. The rest of this frame specification - is unchanged. - - - - ===================================================================== - End of kernel - - - - - - - - diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/AerieAppDriver.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/AerieAppDriver.java index 8f6f6b65ac..7671c509c9 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/AerieAppDriver.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/AerieAppDriver.java @@ -4,15 +4,11 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import gov.nasa.jpl.aerie.merlin.server.config.AppConfiguration; -import gov.nasa.jpl.aerie.merlin.server.config.InMemoryStore; import gov.nasa.jpl.aerie.merlin.server.config.PostgresStore; import gov.nasa.jpl.aerie.merlin.server.config.Store; import gov.nasa.jpl.aerie.merlin.server.http.LocalAppExceptionBindings; import gov.nasa.jpl.aerie.merlin.server.http.MerlinBindings; import gov.nasa.jpl.aerie.merlin.server.http.MissionModelRepositoryExceptionBindings; -import gov.nasa.jpl.aerie.merlin.server.mocks.InMemoryMissionModelRepository; -import gov.nasa.jpl.aerie.merlin.server.mocks.InMemoryPlanRepository; -import gov.nasa.jpl.aerie.merlin.server.remotes.InMemoryResultsCellRepository; import gov.nasa.jpl.aerie.merlin.server.remotes.MissionModelRepository; import gov.nasa.jpl.aerie.merlin.server.remotes.PlanRepository; import gov.nasa.jpl.aerie.merlin.server.remotes.ResultsCellRepository; @@ -25,8 +21,6 @@ import gov.nasa.jpl.aerie.merlin.server.services.GetSimulationResultsAction; import gov.nasa.jpl.aerie.merlin.server.services.LocalMissionModelService; import gov.nasa.jpl.aerie.merlin.server.services.LocalPlanService; -import gov.nasa.jpl.aerie.merlin.server.services.SynchronousSimulationAgent; -import gov.nasa.jpl.aerie.merlin.server.services.ThreadedSimulationAgent; import gov.nasa.jpl.aerie.merlin.server.services.TypescriptCodeGenerationServiceAdapter; import gov.nasa.jpl.aerie.merlin.server.services.UnexpectedSubtypeError; import io.javalin.Javalin; @@ -67,10 +61,7 @@ public static void main(final String[] args) { Runtime.getRuntime().addShutdownHook(new Thread(constraintsDSLCompilationService::close)); // Assemble the core non-web object graph. - final var simulationAgent = ThreadedSimulationAgent.spawn( - "simulation-agent", - new SynchronousSimulationAgent(planController, missionModelController)); - final var simulationController = new CachedSimulationService(simulationAgent, stores.results()); + final var simulationController = new CachedSimulationService(stores.results()); final var simulationAction = new GetSimulationResultsAction( planController, missionModelController, @@ -130,13 +121,6 @@ private static Stores loadStores(final AppConfiguration config) { new PostgresPlanRepository(hikariDataSource), new PostgresMissionModelRepository(hikariDataSource), new PostgresResultsCellRepository(hikariDataSource)); - } else if (store instanceof InMemoryStore c) { - final var inMemoryPlanRepository = new InMemoryPlanRepository(); - return new Stores( - inMemoryPlanRepository, - new InMemoryMissionModelRepository(), - new InMemoryResultsCellRepository(inMemoryPlanRepository)); - } else { throw new UnexpectedSubtypeError(Store.class, store); } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/config/InMemoryStore.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/config/InMemoryStore.java deleted file mode 100644 index 8f477baf1a..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/config/InMemoryStore.java +++ /dev/null @@ -1,3 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.config; - -public record InMemoryStore() implements Store {} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/config/Store.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/config/Store.java index 9e32802598..bfd9a6dca9 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/config/Store.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/config/Store.java @@ -1,5 +1,5 @@ package gov.nasa.jpl.aerie.merlin.server.config; public sealed interface Store - permits PostgresStore, InMemoryStore + permits PostgresStore {} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/NoSuchActivityInstanceException.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/NoSuchActivityInstanceException.java deleted file mode 100644 index 2153947101..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/NoSuchActivityInstanceException.java +++ /dev/null @@ -1,23 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.exceptions; - -import gov.nasa.jpl.aerie.merlin.driver.ActivityDirectiveId; -import gov.nasa.jpl.aerie.merlin.server.models.PlanId; - -public class NoSuchActivityInstanceException extends Exception { - private final PlanId planId; - private final ActivityDirectiveId activityDirectiveId; - - public NoSuchActivityInstanceException(final PlanId planId, final ActivityDirectiveId activityDirectiveId) { - super("No activity exists with id `" + activityDirectiveId + "` in plan with id `" + planId + "`"); - this.planId = planId; - this.activityDirectiveId = activityDirectiveId; - } - - public ActivityDirectiveId getInvalidActivityId() { - return this.activityDirectiveId; - } - - public PlanId getPlanId() { - return this.planId; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/UnexpectedMissingMissionModelException.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/UnexpectedMissingMissionModelException.java deleted file mode 100644 index 9ecd6af9cf..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/UnexpectedMissingMissionModelException.java +++ /dev/null @@ -1,14 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.exceptions; - -public class UnexpectedMissingMissionModelException extends RuntimeException { - private final String missionModelId; - - public UnexpectedMissingMissionModelException(final String missionModelId, final Throwable cause) { - super("MissionModel with id `" + missionModelId + "` is unexpectedly missing", cause); - this.missionModelId = missionModelId; - } - - public String getMissionModelId() { - return this.missionModelId; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/ValidationException.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/ValidationException.java deleted file mode 100644 index a2cd27125b..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/exceptions/ValidationException.java +++ /dev/null @@ -1,20 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.exceptions; - -import gov.nasa.jpl.aerie.merlin.server.services.Breadcrumb; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.Collections; -import java.util.List; - -public class ValidationException extends Exception { - private final List, String>> errors; - - public ValidationException(final List, String>> errors) { - super(errors.toString()); - this.errors = Collections.unmodifiableList(errors); - } - - public List, String>> getValidationErrors() { - return this.errors; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindings.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindings.java index 15ea773628..873e9d0bea 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindings.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindings.java @@ -71,54 +71,22 @@ public void apply(final Javalin javalin) { javalin.routes(() -> { before(ctx -> ctx.contentType("application/json")); - path("resourceTypes", () -> { - post(this::getResourceTypes); - }); - path("getSimulationResults", () -> { - post(this::getSimulationResults); - }); - path("resourceSamples", () -> { - post(this::getResourceSamples); - }); - path("constraintViolations", () -> { - post(this::getConstraintViolations); - }); - path("refreshModelParameters", () -> { - post(this::postRefreshModelParameters); - }); - path("refreshActivityTypes", () -> { - post(this::postRefreshActivityTypes); - }); - path("refreshActivityValidations", () -> { - post(this::postRefreshActivityValidations); - }); - path("validateActivityArguments", () -> { - post(this::validateActivityArguments); - }); - path("validateModelArguments", () -> { - post(this::validateModelArguments); - }); - path("validatePlan", () -> { - post(this::validatePlan); - }); - path("getModelEffectiveArguments", () -> { - post(this::getModelEffectiveArguments); - }); - path("getActivityEffectiveArguments", () -> { - post(this::getActivityEffectiveArguments); - }); - path("addExternalDataset", () -> { - post(this::addExternalDataset); - }); - path("extendExternalDataset", () -> { - post(this::extendExternalDataset); - }); - path("constraintsDslTypescript", () -> { - post(this::getConstraintsDslTypescript); - }); - path("health", () -> { - get(ctx -> ctx.status(200)); - }); + path("resourceTypes", () -> post(this::getResourceTypes)); + path("getSimulationResults", () -> post(this::getSimulationResults)); + path("resourceSamples", () -> post(this::getResourceSamples)); + path("constraintViolations", () -> post(this::getConstraintViolations)); + path("refreshModelParameters", () -> post(this::postRefreshModelParameters)); + path("refreshActivityTypes", () -> post(this::postRefreshActivityTypes)); + path("refreshActivityValidations", () -> post(this::postRefreshActivityValidations)); + path("validateActivityArguments", () -> post(this::validateActivityArguments)); + path("validateModelArguments", () -> post(this::validateModelArguments)); + path("validatePlan", () -> post(this::validatePlan)); + path("getModelEffectiveArguments", () -> post(this::getModelEffectiveArguments)); + path("getActivityEffectiveArguments", () -> post(this::getActivityEffectiveArguments)); + path("addExternalDataset", () -> post(this::addExternalDataset)); + path("extendExternalDataset", () -> post(this::extendExternalDataset)); + path("constraintsDslTypescript", () -> post(this::getConstraintsDslTypescript)); + path("health", () -> get(ctx -> ctx.status(200))); }); // This exception is expected when the request body entity is not a legal JsonValue. diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinParsers.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinParsers.java index 85eb1ac068..f4eccf5dbc 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinParsers.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinParsers.java @@ -61,7 +61,7 @@ public JsonValue unparse(final Timestamp value) { microseconds -> Duration.of(microseconds, Duration.MICROSECONDS), duration -> duration.in(Duration.MICROSECONDS)); - public static final JsonParser activityInstanceIdP + public static final JsonParser activityDirectiveIdP = longP . map( ActivityDirectiveId::new, diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/NewMissionModelValidationException.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/NewMissionModelValidationException.java deleted file mode 100644 index dc5a7f1dc4..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/http/NewMissionModelValidationException.java +++ /dev/null @@ -1,16 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.http; - -import java.util.List; - -public class NewMissionModelValidationException extends Exception { - private final List errors; - - public NewMissionModelValidationException(final String message, final List errors) { - super(message + ": " + errors.toString()); - this.errors = List.copyOf(errors); - } - - public List getValidationErrors() { - return this.errors; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/FakeFile.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/FakeFile.java deleted file mode 100644 index 3abeabaf62..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/FakeFile.java +++ /dev/null @@ -1,13 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.mocks; - -public final class FakeFile { - public final String filename; - public final String contentType; - public final String contents; - - public FakeFile(final String filename, final String contentType, final String contents) { - this.filename = filename; - this.contentType = contentType; - this.contents = contents; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryMissionModelRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryMissionModelRepository.java deleted file mode 100644 index 2a047a3659..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryMissionModelRepository.java +++ /dev/null @@ -1,109 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.mocks; - -import gov.nasa.jpl.aerie.merlin.protocol.model.InputType.Parameter; -import gov.nasa.jpl.aerie.merlin.protocol.model.InputType.ValidationNotice; -import gov.nasa.jpl.aerie.merlin.server.models.ActivityDirectiveId; -import gov.nasa.jpl.aerie.merlin.server.models.ActivityType; -import gov.nasa.jpl.aerie.merlin.server.models.Constraint; -import gov.nasa.jpl.aerie.merlin.server.models.MissionModelJar; -import gov.nasa.jpl.aerie.merlin.server.models.PlanId; -import gov.nasa.jpl.aerie.merlin.server.models.Timestamp; -import gov.nasa.jpl.aerie.merlin.server.remotes.MissionModelAccessException; -import gov.nasa.jpl.aerie.merlin.server.remotes.MissionModelRepository; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import static gov.nasa.jpl.aerie.merlin.server.utilities.FileUtils.getUniqueFilePath; - -public final class InMemoryMissionModelRepository implements MissionModelRepository { - private final Path MISSION_MODEL_FILE_PATH; - private final Map missionModels = new HashMap<>(); - private int nextMissionModelId; - - public InMemoryMissionModelRepository() { - try { - MISSION_MODEL_FILE_PATH = Files.createTempDirectory("mock_missionModel_files").toAbsolutePath(); - } catch (final IOException ex) { - throw new RuntimeException(ex); - } - } - - public String createMissionModel(final MissionModelJar missionModelJar) { - // Store MissionModel JAR - final Path location = getUniqueFilePath(missionModelJar, MISSION_MODEL_FILE_PATH); - try { - Files.copy(missionModelJar.path, location); - } catch (final IOException e) { - throw new MissionModelAccessException(missionModelJar.path, e); - } - - final MissionModelJar newJar = new MissionModelJar(missionModelJar); - newJar.path = location; - - final String missionModelId = Objects.toString(this.nextMissionModelId++); - this.missionModels.put(missionModelId, newJar); - - return missionModelId; - } - - @Override - public void updateModelParameters(final String missionModelId, final List modelParameters) - throws NoSuchMissionModelException - { - } - - @Override - public void updateActivityTypes(final String missionModelId, final Map activityTypes) - throws NoSuchMissionModelException - { - } - - @Override - public void updateActivityDirectiveValidations(final ActivityDirectiveId directiveId, final PlanId planId, final Timestamp argumentsModifiedTime, final List notices) - { - } - - public void deleteMissionModel(final String missionModelId) throws NoSuchMissionModelException { - final MissionModelJar missionModelJar = getMissionModel(missionModelId); - - // Delete mission model JAR - try { - Files.deleteIfExists(missionModelJar.path); - } catch (final IOException e) { - throw new MissionModelAccessException(missionModelJar.path, e); - } - - this.missionModels.remove(missionModelId); - } - - @Override - public MissionModelJar getMissionModel(final String missionModelId) throws NoSuchMissionModelException { - final MissionModelJar missionModel = Optional - .ofNullable(this.missionModels.get(missionModelId)) - .orElseThrow(NoSuchMissionModelException::new); - - return new MissionModelJar(missionModel); - } - - @Override - public Map getConstraints(final String missionModelId) throws NoSuchMissionModelException { - return Map.of(); - } - - @Override - public Map getAllMissionModels() { - return new HashMap<>(this.missionModels); - } - - @Override - public Map getActivityTypes(final String missionModelId) { - return Map.of(); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryPlanRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryPlanRepository.java index 2834ad143d..9c5579da2e 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryPlanRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryPlanRepository.java @@ -2,13 +2,11 @@ import gov.nasa.jpl.aerie.merlin.driver.ActivityDirectiveId; import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; -import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; import gov.nasa.jpl.aerie.merlin.protocol.types.ValueSchema; import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchPlanException; import gov.nasa.jpl.aerie.merlin.driver.ActivityDirective; import gov.nasa.jpl.aerie.merlin.server.models.Constraint; import gov.nasa.jpl.aerie.merlin.server.models.DatasetId; -import gov.nasa.jpl.aerie.merlin.server.models.NewPlan; import gov.nasa.jpl.aerie.merlin.server.models.Plan; import gov.nasa.jpl.aerie.merlin.server.models.PlanId; import gov.nasa.jpl.aerie.merlin.server.models.ProfileSet; @@ -16,7 +14,6 @@ import gov.nasa.jpl.aerie.merlin.server.remotes.PlanRepository; import org.apache.commons.lang3.tuple.Pair; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -75,49 +72,17 @@ public InMemoryRevisionData getPlanRevisionData(final PlanId planId) throws NoSu .getLeft()); } - @Override - public Map getAllActivitiesInPlan(final PlanId planId) throws NoSuchPlanException { - final Plan plan = this.plans.get(planId).getRight(); - if (plan == null) { - throw new NoSuchPlanException(planId); - } - - return new HashMap<>(plan.activityDirectives); - } - - public CreatedPlan createPlan(final NewPlan newPlan) { + public CreatedPlan storePlan(final Plan other) { final PlanId planId = new PlanId(this.nextPlanId++); - - final Plan plan = new Plan(); - plan.name = newPlan.name; - plan.startTimestamp = newPlan.startTimestamp; - plan.endTimestamp = newPlan.endTimestamp; - plan.configuration = newPlan.configuration; - plan.missionModelId = newPlan.missionModelId; - plan.activityDirectives = new HashMap<>(); - - final List activityIds; - if (newPlan.activityDirectives == null) { - activityIds = new ArrayList<>(); - } else { - activityIds = new ArrayList<>(newPlan.activityDirectives.size()); - for (final var activity : newPlan.activityDirectives) { - final ActivityDirectiveId activityId = new ActivityDirectiveId(this.nextActivityId++); - - activityIds.add(activityId); - plan.activityDirectives.put(activityId, activity); - } - } + final Plan plan = new Plan(other); + final List activityIds = + other.activityDirectives != null ? List.copyOf(plan.activityDirectives.keySet()) : List.of(); + if (other.activityDirectives == null) plan.activityDirectives = new HashMap<>(); this.plans.put(planId, Pair.of(0L, plan)); - return new CreatedPlan(planId, activityIds); } - public PlanTransaction updatePlan(final PlanId planId) { - return new MockPlanTransaction(planId); - } - public void deletePlan(final PlanId planId) throws NoSuchPlanException { if (!this.plans.containsKey(planId)) { throw new NoSuchPlanException(planId); @@ -153,13 +118,12 @@ public void deleteAllActivities(final PlanId planId) throws NoSuchPlanException } @Override - public Map getAllConstraintsInPlan(final PlanId planId) throws NoSuchPlanException { + public Map getAllConstraintsInPlan(final PlanId planId) { return Map.of(); } @Override public long addExternalDataset(final PlanId planId, final Timestamp datasetStart, final ProfileSet profileSet) - throws NoSuchPlanException { return 0; } @@ -170,68 +134,12 @@ public void extendExternalDataset(final DatasetId datasetId, final ProfileSet pr } @Override - public List> getExternalDatasets(final PlanId planId) throws NoSuchPlanException { + public List> getExternalDatasets(final PlanId planId) { return List.of(); } @Override - public Map getExternalResourceSchemas(final PlanId planId) throws NoSuchPlanException { + public Map getExternalResourceSchemas(final PlanId planId) { return Map.of(); } - - private class MockPlanTransaction implements PlanTransaction { - private final PlanId planId; - - private Optional name = Optional.empty(); - private Optional startTimestamp = Optional.empty(); - private Optional endTimestamp = Optional.empty(); - private Optional> configuration = Optional.empty(); - private Optional missionModelId = Optional.empty(); - - public MockPlanTransaction(final PlanId planId) { - this.planId = planId; - } - - @Override - public void commit() throws NoSuchPlanException { - final var entry = InMemoryPlanRepository.this.plans.get(this.planId); - if (entry == null) throw new NoSuchPlanException(this.planId); - - final var plan = entry.getRight(); - final var revision = entry.getLeft() + 1; - - this.name.ifPresent(name -> plan.name = name); - this.startTimestamp.ifPresent(startTimestamp -> plan.startTimestamp = startTimestamp); - this.endTimestamp.ifPresent(endTimestamp -> plan.endTimestamp = endTimestamp); - this.configuration.ifPresent(configuration -> plan.configuration = configuration); - this.missionModelId.ifPresent(missionModelId -> plan.missionModelId = missionModelId); - - InMemoryPlanRepository.this.plans.put(this.planId, Pair.of(revision, plan)); - } - - @Override - public PlanTransaction setName(final String name) { - this.name = Optional.of(name); - return this; - } - - @Override - public PlanTransaction setStartTimestamp(final Timestamp timestamp) { - this.startTimestamp = Optional.of(timestamp); - return this; - } - - @Override - public PlanTransaction setEndTimestamp(final Timestamp timestamp) { - this.endTimestamp = Optional.of(timestamp); - return this; - } - - @Override - public PlanTransaction setConfiguration(final Map configuration) - { - this.configuration = Optional.of(configuration); - return this; - } - } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryRevisionData.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryRevisionData.java index 1634714dbd..54c7f5615f 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryRevisionData.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryRevisionData.java @@ -2,7 +2,7 @@ import gov.nasa.jpl.aerie.merlin.server.services.RevisionData; -public final record InMemoryRevisionData( +public record InMemoryRevisionData( long planRevision ) implements RevisionData { diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/CreatedEntity.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/CreatedEntity.java deleted file mode 100644 index 92089e353d..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/CreatedEntity.java +++ /dev/null @@ -1,9 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.models; - -public final class CreatedEntity { - public final String id; - - public CreatedEntity(final String id) { - this.id = id; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java index 1ca70fd370..c8dc222eba 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java @@ -19,14 +19,6 @@ public final class MissionModelJar { public MissionModelJar() {} - public MissionModelJar(final MissionModelJar other) { - this.name = other.name; - this.version = other.version; - this.mission = other.mission; - this.owner = other.owner; - this.path = other.path; - } - @Override public boolean equals(final Object object) { if (object.getClass() != MissionModelJar.class) { diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewMissionModel.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewMissionModel.java deleted file mode 100644 index 5cb0654299..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewMissionModel.java +++ /dev/null @@ -1,65 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.models; - -import java.io.InputStream; -import java.util.Objects; - -public final class NewMissionModel { - public final String name; - public final String version; - public final String mission; - public final String owner; - public final InputStream jarSource; - - private NewMissionModel(final Builder builder) { - this.name = Objects.requireNonNull(builder.name); - this.version = Objects.requireNonNull(builder.version); - this.mission = Objects.requireNonNull(builder.mission); - this.owner = Objects.requireNonNull(builder.owner); - this.jarSource = Objects.requireNonNull(builder.jarSource); - } - - public static Builder builder() { - return new Builder(); - } - - public static final class Builder { - private String name = null; - private String version = null; - private String mission = null; - private String owner = null; - private InputStream jarSource = null; - - private Builder() {} - - public Builder setName(final String name) { - this.name = Objects.requireNonNull(name); - return this; - } - - public Builder setVersion(final String version) { - this.version = Objects.requireNonNull(version); - return this; - } - - public Builder setMission(final String mission) { - this.mission = Objects.requireNonNull(mission); - return this; - } - - public Builder setOwner(final String owner) { - this.owner = Objects.requireNonNull(owner); - return this; - } - - public Builder setJarSource(final InputStream jarSource) { - this.jarSource = Objects.requireNonNull(jarSource); - return this; - } - - public NewMissionModel build() { - final var result = new NewMissionModel(this); - this.jarSource = null; - return result; - } - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewPlan.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewPlan.java deleted file mode 100644 index fb32a74e18..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewPlan.java +++ /dev/null @@ -1,80 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.models; - -import gov.nasa.jpl.aerie.merlin.driver.ActivityDirective; -import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public final class NewPlan { - public String name; - public String missionModelId; - public Timestamp startTimestamp; - public Timestamp endTimestamp; - public List activityDirectives; - public Map configuration = new HashMap<>(); - - public NewPlan() {} - - public NewPlan(final Plan template) { - this.name = template.name; - this.missionModelId = template.missionModelId; - this.startTimestamp = template.startTimestamp; - this.endTimestamp = template.endTimestamp; - - if (template.activityDirectives != null) { - this.activityDirectives = new ArrayList<>(); - this.activityDirectives.addAll(template.activityDirectives.values()); - } - - if (template.configuration != null) this.configuration = new HashMap<>(template.configuration); - } - - public NewPlan( - final String name, - final String missionModelId, - final Timestamp startTimestamp, - final Timestamp endTimestamp, - final List activityDirectives, - final Map configuration - ) { - this.name = name; - this.missionModelId = missionModelId; - this.startTimestamp = startTimestamp; - this.endTimestamp = endTimestamp; - this.activityDirectives = List.copyOf(activityDirectives); - if (configuration != null) this.configuration = new HashMap<>(configuration); - } - - @Override - public boolean equals(final Object object) { - if (!(object instanceof NewPlan)) { - return false; - } - - final var other = (NewPlan)object; - return - ( Objects.equals(this.name, other.name) - && Objects.equals(this.missionModelId, other.missionModelId) - && Objects.equals(this.startTimestamp, other.startTimestamp) - && Objects.equals(this.endTimestamp, other.endTimestamp) - && Objects.equals(this.activityDirectives, other.activityDirectives) - && Objects.equals(this.configuration, other.configuration) - ); - } - - @Override - public int hashCode() { - return Objects.hash( - name, - missionModelId, - startTimestamp, - endTimestamp, - activityDirectives, - configuration - ); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/InMemoryResultsCellRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/InMemoryResultsCellRepository.java index cba4ee5419..baaff0c812 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/InMemoryResultsCellRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/InMemoryResultsCellRepository.java @@ -48,14 +48,6 @@ public Optional lookup(final PlanId planId) { } } - @Override - public void deallocate(final ResultsProtocol.OwnerRole resultsCell) { - if (!(resultsCell instanceof InMemoryCell cell)) { - throw new Error("Unable to deallocate results cell of unknown type"); - } - this.cells.remove(new InMemoryResultsCellRepository.Key(cell.planId, cell.planRevision)); - } - public boolean isEqualTo(final InMemoryResultsCellRepository other) { return this.cells.equals(other.cells); } @@ -126,9 +118,7 @@ public void failWith(final SimulationFailure reason) { public boolean isEqualTo(final InMemoryCell other) { if (this.canceled != other.canceled) return false; - if (!Objects.equals(this.state, other.state)) return false; - - return true; + return Objects.equals(this.state, other.state); } @Deprecated diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/MissionModelRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/MissionModelRepository.java index 02fd02f108..aef91ac250 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/MissionModelRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/MissionModelRepository.java @@ -25,5 +25,4 @@ public interface MissionModelRepository { void updateActivityDirectiveValidations(final ActivityDirectiveId directiveId, final PlanId planId, final Timestamp argumentsModifiedTime, final List notices); final class NoSuchMissionModelException extends Exception {} - final class NoSuchActivityDirectiveException extends Exception {} } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepository.java index db87b37883..1807ddd65b 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepository.java @@ -2,12 +2,9 @@ import gov.nasa.jpl.aerie.merlin.driver.ActivityDirectiveId; import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; -import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; import gov.nasa.jpl.aerie.merlin.protocol.types.ValueSchema; -import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchActivityInstanceException; import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchPlanDatasetException; import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchPlanException; -import gov.nasa.jpl.aerie.merlin.driver.ActivityDirective; import gov.nasa.jpl.aerie.merlin.server.models.Constraint; import gov.nasa.jpl.aerie.merlin.server.models.DatasetId; import gov.nasa.jpl.aerie.merlin.server.models.Plan; @@ -35,7 +32,6 @@ public interface PlanRepository { Plan getPlanForSimulation(PlanId planId) throws NoSuchPlanException; long getPlanRevision(PlanId planId) throws NoSuchPlanException; RevisionData getPlanRevisionData(PlanId planId) throws NoSuchPlanException; - Map getAllActivitiesInPlan(PlanId planId) throws NoSuchPlanException; Map getAllConstraintsInPlan(PlanId planId) throws NoSuchPlanException; @@ -45,21 +41,4 @@ public interface PlanRepository { Map getExternalResourceSchemas(PlanId planId) throws NoSuchPlanException; record CreatedPlan(PlanId planId, List activityIds) {} - - interface PlanTransaction { - void commit() throws NoSuchPlanException; - - PlanTransaction setName(String name); - PlanTransaction setStartTimestamp(Timestamp timestamp); - PlanTransaction setEndTimestamp(Timestamp timestamp); - PlanTransaction setConfiguration(Map configuration); - } - - interface ActivityTransaction { - void commit() throws NoSuchPlanException, NoSuchActivityInstanceException; - - ActivityTransaction setType(String type); - ActivityTransaction setStartOffset(Duration offset); - ActivityTransaction setParameters(Map parameters); - } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/ResultsCellRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/ResultsCellRepository.java index edef5b76ec..611224e3d6 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/ResultsCellRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/ResultsCellRepository.java @@ -11,6 +11,4 @@ public interface ResultsCellRepository { Optional claim(PlanId planId, Long datasetId); Optional lookup(PlanId planId); - - void deallocate(ResultsProtocol.OwnerRole resultsCell); } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/AssociatePlanDatasetAction.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/AssociatePlanDatasetAction.java deleted file mode 100644 index 4970884c73..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/AssociatePlanDatasetAction.java +++ /dev/null @@ -1,42 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; - -import gov.nasa.jpl.aerie.merlin.server.models.Timestamp; -import org.intellij.lang.annotations.Language; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -/*package-local*/ final class AssociatePlanDatasetAction implements AutoCloseable { - private final @Language("SQL") String sql = """ - insert into plan_dataset (plan_id, dataset_id) - values (?, ?) - returning offset_from_plan_start - """; - - private final PreparedStatement statement; - - public AssociatePlanDatasetAction(final Connection connection) throws SQLException { - this.statement = connection.prepareStatement(sql); - } - - public PlanDatasetRecord apply( - final long planId, - final long datasetId, - final Timestamp planStart - ) throws SQLException { - this.statement.setLong(1, planId); - this.statement.setLong(2, datasetId); - - final var results = this.statement.executeQuery(); - if (!results.next()) throw new FailedInsertException("plan_dataset"); - final var offsetFromPlanStart = PostgresParsers.parseOffset(results, 1, planStart); - - return new PlanDatasetRecord(planId, datasetId, offsetFromPlanStart); - } - - @Override - public void close() throws SQLException { - this.statement.close(); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/CreateDatasetPartitionsAction.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/CreateDatasetPartitionsAction.java deleted file mode 100644 index 9bb01e4d3b..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/CreateDatasetPartitionsAction.java +++ /dev/null @@ -1,29 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; - -import org.intellij.lang.annotations.Language; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -/*package-local*/ final class CreateDatasetPartitionsAction implements AutoCloseable { - private static final @Language("SQL") String sql = """ - select from allocate_dataset_partitions(?); - """; - - private final PreparedStatement statement; - - public CreateDatasetPartitionsAction(final Connection connection) throws SQLException { - this.statement = connection.prepareStatement(sql); - } - - public void apply(final long datasetId) throws SQLException { - this.statement.setLong(1, datasetId); - this.statement.executeUpdate(); - } - - @Override - public void close() throws SQLException { - this.statement.close(); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/DeleteSimulationDatasetAction.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/DeleteSimulationDatasetAction.java deleted file mode 100644 index 65be448500..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/DeleteSimulationDatasetAction.java +++ /dev/null @@ -1,30 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; - -import org.intellij.lang.annotations.Language; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -/*package local*/ final class DeleteSimulationDatasetAction implements AutoCloseable { - private static final @Language("SQL") String sql = """ - delete from simulation_dataset - where dataset_id = ? - """; - - private final PreparedStatement statement; - - public DeleteSimulationDatasetAction(final Connection connection) throws SQLException { - this.statement = connection.prepareStatement(sql); - } - - public boolean apply(final long datasetId) throws SQLException { - this.statement.setLong(1, datasetId); - return this.statement.execute(); - } - - @Override - public void close() throws SQLException { - this.statement.close(); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetModelConstraintsAction.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetModelConstraintsAction.java index da711aafab..d5f0b88b80 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetModelConstraintsAction.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetModelConstraintsAction.java @@ -4,7 +4,6 @@ import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -36,7 +35,7 @@ public Optional> get(final long modelId) throws SQLExcept final var constraints = new ArrayList(); do { - if (isColumnNull(results, 1)) continue; + if (results.getObject(1) == null) continue; final var constraint = new ConstraintRecord( results.getLong(1), @@ -56,10 +55,4 @@ public Optional> get(final long modelId) throws SQLExcept public void close() throws SQLException { this.statement.close(); } - - private static boolean isColumnNull(final ResultSet results, final int index) throws SQLException { - // You're kidding, right? This is how you detect NULL with JDBC? - results.getObject(index); - return results.wasNull(); - } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetPlanConstraintsAction.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetPlanConstraintsAction.java index 3752a9ee61..0143f72b7e 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetPlanConstraintsAction.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetPlanConstraintsAction.java @@ -4,7 +4,6 @@ import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -36,7 +35,7 @@ public Optional> get(final long planId) throws SQLExcepti final var constraints = new ArrayList(); do { - if (isColumnNull(results, 1)) continue; + if (results.getObject(1) == null) continue; final var constraint = new ConstraintRecord( results.getLong(1), @@ -56,10 +55,4 @@ public Optional> get(final long planId) throws SQLExcepti public void close() throws SQLException { this.statement.close(); } - - private static boolean isColumnNull(final ResultSet results, final int index) throws SQLException { - // You're kidding, right? This is how you detect NULL with JDBC? - results.getObject(index); - return results.wasNull(); - } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetSpanRecords.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetSpanRecords.java index 595aa4ad20..a10ade6760 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetSpanRecords.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/GetSpanRecords.java @@ -4,11 +4,8 @@ import gov.nasa.jpl.aerie.merlin.server.models.Timestamp; import org.intellij.lang.annotations.Language; -import javax.json.Json; -import java.io.Reader; import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -49,10 +46,10 @@ public Map get(final long datasetId, final Timestamp simulatio while (resultSet.next()) { final var id = resultSet.getLong(1); final var type = resultSet.getString(2); - final var parentId = readOptionalLong(resultSet, 3); + final Optional parentId = resultSet.getObject(3) == null ? Optional.empty() : Optional.of(resultSet.getLong(3)); final var startOffset = parseOffset(resultSet, 4, simulationStart); final var start = simulationStart.toInstant().plus(startOffset.in(MICROSECONDS), ChronoUnit.MICROS); - final var duration = isNull(resultSet, 5) ? Optional.empty() : Optional.of(parseOffset( + final var duration = resultSet.getObject(5) == null ? Optional.empty() : Optional.of(parseOffset( resultSet, 5, start)); @@ -81,16 +78,6 @@ public Map get(final long datasetId, final Timestamp simulatio return spans; } - private static boolean isNull(final ResultSet resultSet, final int index) throws SQLException { - resultSet.getObject(index); - return resultSet.wasNull(); - } - - private static Optional readOptionalLong(final ResultSet resultSet, final int index) throws SQLException { - final var value = resultSet.getLong(index); - return resultSet.wasNull() ? Optional.empty() : Optional.of(value); - } - @Override public void close() throws SQLException { this.statement.close(); diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/IntegrationFailureException.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/IntegrationFailureException.java index 713b72d4ac..6ca852549e 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/IntegrationFailureException.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/IntegrationFailureException.java @@ -1,8 +1,6 @@ package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; public abstract /*sealed*/ class IntegrationFailureException extends RuntimeException { - public IntegrationFailureException() {} - public IntegrationFailureException(final String message) { super(message); } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresMissionModelRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresMissionModelRepository.java index d156554030..0e6678bfee 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresMissionModelRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresMissionModelRepository.java @@ -11,8 +11,6 @@ import gov.nasa.jpl.aerie.merlin.server.remotes.MissionModelRepository; import javax.sql.DataSource; -import java.nio.file.Files; -import java.nio.file.Path; import java.sql.SQLException; import java.util.HashMap; import java.util.List; @@ -169,13 +167,4 @@ private static MissionModelJar missionModelRecordToMissionModelJar(final Mission return model; } - - private static Path getUnusedFilename(final Path base, final String preferredName) { - var path = base.resolve(preferredName + ".jar"); - for (int i = 0; Files.exists(path); ++i) { - path = base.resolve(preferredName + "_" + i + ".jar"); - } - - return path; - } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresPlanRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresPlanRepository.java index 54ddd228b1..fdc2540e22 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresPlanRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresPlanRepository.java @@ -177,16 +177,6 @@ public PostgresPlanRevisionData getPlanRevisionData(final PlanId planId) throws } } - @Override - public Map getAllActivitiesInPlan(final PlanId planId) - throws NoSuchPlanException { - try (final var connection = this.dataSource.getConnection()) { - return getPlanActivities(connection, planId); - } catch (final SQLException ex) { - throw new DatabaseException("Failed to get all activities from plan", ex); - } - } - @Override public Map getAllConstraintsInPlan(final PlanId planId) throws NoSuchPlanException { try (final var connection = this.dataSource.getConnection()) { @@ -333,62 +323,7 @@ private static PlanDatasetRecord createPlanDataset( final Timestamp datasetStart ) throws SQLException { try (final var createPlanDatasetAction = new CreatePlanDatasetAction(connection)) { - final var pdr = createPlanDatasetAction.apply(planId.id(), planStart, datasetStart); - return pdr; - } - } - - private static final class PostgresPlanTransaction implements PlanTransaction { - private final DataSource dataSource; - private final PlanId planId; - - private Optional name = Optional.empty(); - private Optional startTime = Optional.empty(); - private Optional endTime = Optional.empty(); - - public PostgresPlanTransaction(final DataSource dataSource, final PlanId planId) { - this.dataSource = dataSource; - this.planId = planId; - } - - @Override - public void commit() throws NoSuchPlanException { - try (final var connection = this.dataSource.getConnection()) { - try (final var updatePlanAction = new UpdatePlanAction(connection)) { - updatePlanAction.apply( - this.planId.id(), - this.name.orElse(null), - this.startTime.orElse(null), - this.endTime.orElse(null)); - } - } catch (final FailedUpdateException ex) { - throw new NoSuchPlanException(this.planId); - } catch (final SQLException ex) { - throw new DatabaseException("Failed to update a plan", ex); - } - } - - @Override - public PlanTransaction setName(final String name) { - this.name = Optional.of(name); - return this; - } - - @Override - public PlanTransaction setStartTimestamp(final Timestamp timestamp) { - this.startTime = Optional.of(timestamp); - return this; - } - - @Override - public PlanTransaction setEndTimestamp(final Timestamp timestamp) { - this.endTime = Optional.of(timestamp); - return this; - } - - @Override - public PlanTransaction setConfiguration(final Map configuration) { - return this; + return createPlanDatasetAction.apply(planId.id(), planStart, datasetStart); } } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresResultsCellRepository.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresResultsCellRepository.java index 19ba692014..677a31b22f 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresResultsCellRepository.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PostgresResultsCellRepository.java @@ -12,7 +12,6 @@ import gov.nasa.jpl.aerie.merlin.protocol.types.ValueSchema; import gov.nasa.jpl.aerie.merlin.server.ResultsProtocol; import gov.nasa.jpl.aerie.merlin.server.ResultsProtocol.State; -import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchPlanException; import gov.nasa.jpl.aerie.merlin.server.models.PlanId; import gov.nasa.jpl.aerie.merlin.server.models.ProfileSet; import gov.nasa.jpl.aerie.merlin.server.models.Timestamp; @@ -132,18 +131,6 @@ public Optional lookup(final PlanId planId) { } } - @Override - public void deallocate(final ResultsProtocol.OwnerRole resultsCell) { - if (!(resultsCell instanceof PostgresResultsCell cell)) { - throw new Error("Unable to deallocate results cell of unknown type"); - } - try (final var connection = this.dataSource.getConnection()) { - deleteSimulationDataset(connection, cell.datasetId); - } catch (final SQLException ex) { - throw new DatabaseException("Failed to delete simulation", ex); - } - } - /* Database accessors */ private static SimulationRecord getSimulation( final Connection connection, @@ -229,12 +216,6 @@ private static void cancelSimulation( } } - private static boolean deleteSimulationDataset(final Connection connection, final long datasetId) throws SQLException { - try (final var deleteSimulationDatasetAction = new DeleteSimulationDatasetAction(connection)) { - return deleteSimulationDatasetAction.apply(datasetId); - } - } - private static void failSimulation( final Connection connection, final long datasetId, @@ -352,17 +333,6 @@ final var record = entry.getValue(); } } - private static PlanRecord getPlan( - final Connection connection, - final PlanId planId - ) throws SQLException, NoSuchPlanException { - try (final var getPlanAction = new GetPlanAction(connection)) { - return getPlanAction - .get(planId.id()) - .orElseThrow(() -> new NoSuchPlanException(planId)); - } - } - private static void postSimulationResults( final Connection connection, final long datasetId, diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/ProfileRecord.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/ProfileRecord.java index adfb980572..fd8314b772 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/ProfileRecord.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/ProfileRecord.java @@ -4,7 +4,7 @@ import gov.nasa.jpl.aerie.merlin.protocol.types.ValueSchema; import org.apache.commons.lang3.tuple.Pair; -public final record ProfileRecord( +public record ProfileRecord( long id, long datasetId, String name, diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UnexpectedJsonException.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UnexpectedJsonException.java deleted file mode 100644 index cde00c0a18..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UnexpectedJsonException.java +++ /dev/null @@ -1,7 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; - -public class UnexpectedJsonException extends IntegrationFailureException { - public UnexpectedJsonException(final String message, final Throwable cause) { - super(message, cause); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UnexpectedMissingPlanException.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UnexpectedMissingPlanException.java deleted file mode 100644 index b1e963e6e0..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UnexpectedMissingPlanException.java +++ /dev/null @@ -1,14 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; - -public final class UnexpectedMissingPlanException extends RuntimeException { - private final String planId; - - public UnexpectedMissingPlanException(final String planId, final Throwable cause) { - super("Plan with id `" + planId + "` is unexpectedly missing", cause); - this.planId = planId; - } - - public String getPlanId() { - return this.planId; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UpdatePlanAction.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UpdatePlanAction.java deleted file mode 100644 index 40d8cd2aac..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/UpdatePlanAction.java +++ /dev/null @@ -1,92 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; - -import gov.nasa.jpl.aerie.merlin.server.models.Timestamp; -import org.intellij.lang.annotations.Language; -import org.jetbrains.annotations.Nullable; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -/*package-local*/ final class UpdatePlanAction - implements AutoCloseable /* This isn't necessary, but it's convenient for symmetry with other actions. */ -{ - private final Connection connection; - - public UpdatePlanAction(final Connection connection) { - this.connection = connection; - } - - public void apply( - final long planId, - final @Nullable String name, - final @Nullable Timestamp startTime, - final @Nullable Timestamp endTime - ) throws SQLException, FailedUpdateException { - final var generatedSql = generateSql(planId, name, startTime, endTime); - - try (final var statement = this.connection.prepareStatement(generatedSql.sql())) { - for (var i = 1; i < generatedSql.argumentSetters().size(); i += 1) { - generatedSql.argumentSetters().get(i).set(statement, i); - } - - final var count = statement.executeUpdate(); - if (count != 1) throw new FailedUpdateException("plan"); - } - } - - - private interface ArgumentSetter { - void set(PreparedStatement statement, int index) throws SQLException; - } - - public record GeneratedSql(String sql, List argumentSetters) {} - - public static GeneratedSql generateSql( - final long planId, - final @Nullable String name, - final @Nullable Timestamp startTime, - final @Nullable Timestamp endTime - ) { - final var argumentSqlFragments = new ArrayList(4); - final var argumentSetters = new ArrayList(5); - { - if (name != null) { - argumentSqlFragments.add("name = ?"); - argumentSetters.add((statement, index) -> statement.setString(index, name)); - } - - if (startTime != null) { - if (endTime != null) { - argumentSqlFragments.add("start_time = ?, duration = ? - ?"); - argumentSetters.add((statement, index) -> PreparedStatements.setTimestamp(statement, index, startTime)); - argumentSetters.add((statement, index) -> PreparedStatements.setTimestamp(statement, index, endTime)); - argumentSetters.add((statement, index) -> PreparedStatements.setTimestamp(statement, index, startTime)); - } else { - argumentSqlFragments.add("start_time = ?, duration = end_time - ?::timestamptz"); - argumentSetters.add((statement, index) -> PreparedStatements.setTimestamp(statement, index, startTime)); - argumentSetters.add((statement, index) -> PreparedStatements.setTimestamp(statement, index, startTime)); - } - } else { - if (endTime != null) { - argumentSqlFragments.add("duration = ?::timestamptz - start_time"); - argumentSetters.add((statement, index) -> PreparedStatements.setTimestamp(statement, index, endTime)); - } else { - // pass - } - } - } - - final @Language("SQL") String sql = - "update plan set " + String.join(", ", argumentSqlFragments) + " where id = ?"; - - return new GeneratedSql(sql, argumentSetters); - } - - @Override - public void close() { - // Nothing to clean up. The method is an intentionally-blank override. - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/Window.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/Window.java deleted file mode 100644 index 9502d9a017..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/Window.java +++ /dev/null @@ -1,12 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes.postgres; - -import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; -import gov.nasa.jpl.aerie.merlin.server.models.Timestamp; - -import static gov.nasa.jpl.aerie.merlin.protocol.types.Duration.MICROSECONDS; - -public record Window(Timestamp start, Timestamp end) { - public Duration duration() { - return Duration.of(start.microsUntil(end), MICROSECONDS); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/Breadcrumb.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/Breadcrumb.java deleted file mode 100644 index 6155ed915e..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/Breadcrumb.java +++ /dev/null @@ -1,33 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.services; - -public interface Breadcrumb { - - interface Visitor { - T onListIndex(int index); - T onMapIndex(String index); - } - - T match(final Visitor visitor); - - static Breadcrumb of(final String index) { - record MapBreadcrumb(String index) implements Breadcrumb { - @Override - public T match(final Visitor visitor) { - return visitor.onMapIndex(index); - } - } - - return new MapBreadcrumb(index); - } - - static Breadcrumb of(final int index) { - record ListBreadcrumb(int index) implements Breadcrumb { - @Override - public T match(final Visitor visitor) { - return visitor.onListIndex(index); - } - } - - return new ListBreadcrumb(index); - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/BreadcrumbCursor.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/BreadcrumbCursor.java deleted file mode 100644 index 4ec9788831..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/BreadcrumbCursor.java +++ /dev/null @@ -1,27 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.services; - -import java.util.ArrayList; -import java.util.List; - -public final class BreadcrumbCursor { - private final List breadcrumbs = new ArrayList<>(); - - public List getPath() { - return new ArrayList<>(this.breadcrumbs); - } - - public BreadcrumbCursor descend(final int index) { - this.breadcrumbs.add(Breadcrumb.of(index)); - return this; - } - - public BreadcrumbCursor descend(final String index) { - this.breadcrumbs.add(Breadcrumb.of(index)); - return this; - } - - public BreadcrumbCursor ascend() { - this.breadcrumbs.remove(this.breadcrumbs.size() - 1); - return this; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/CachedSimulationService.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/CachedSimulationService.java index 7c1408916b..847bd310e5 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/CachedSimulationService.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/CachedSimulationService.java @@ -8,7 +8,6 @@ import gov.nasa.jpl.aerie.merlin.server.remotes.ResultsCellRepository; public record CachedSimulationService ( - SimulationAgent agent, ResultsCellRepository store ) implements SimulationService { diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsCodeGenService.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsCodeGenService.java deleted file mode 100644 index 62f0c95dba..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsCodeGenService.java +++ /dev/null @@ -1,11 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.services; - -import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchPlanException; -import gov.nasa.jpl.aerie.merlin.server.models.PlanId; - -import java.util.Optional; - -public interface ConstraintsCodeGenService { - String generateTypescriptTypes(String missionModelId, Optional planId) - throws MissionModelService.NoSuchMissionModelException, NoSuchPlanException; -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationService.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationService.java index fecc287f8d..ae7184070e 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationService.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ConstraintsDSLCompilationService.java @@ -23,9 +23,9 @@ public class ConstraintsDSLCompilationService { private final Process nodeProcess; - private final ConstraintsCodeGenService typescriptCodeGenerationService; + private final TypescriptCodeGenerationServiceAdapter typescriptCodeGenerationService; - public ConstraintsDSLCompilationService(final ConstraintsCodeGenService typescriptCodeGenerationService) + public ConstraintsDSLCompilationService(final TypescriptCodeGenerationServiceAdapter typescriptCodeGenerationService) throws IOException { this.typescriptCodeGenerationService = typescriptCodeGenerationService; diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/GenerateConstraintsLibAction.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/GenerateConstraintsLibAction.java index af0e17e03a..65d91783cb 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/GenerateConstraintsLibAction.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/GenerateConstraintsLibAction.java @@ -10,7 +10,7 @@ import java.util.Objects; import java.util.Optional; -public record GenerateConstraintsLibAction(ConstraintsCodeGenService typescriptCodeGenerationService) { +public record GenerateConstraintsLibAction(TypescriptCodeGenerationServiceAdapter typescriptCodeGenerationService) { public GenerateConstraintsLibAction { Objects.requireNonNull(typescriptCodeGenerationService); } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/SynchronousSimulationAgent.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/SynchronousSimulationAgent.java index c100b0d687..a01ac5b72b 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/SynchronousSimulationAgent.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/SynchronousSimulationAgent.java @@ -10,7 +10,6 @@ import gov.nasa.jpl.aerie.merlin.server.models.PlanId; import javax.json.Json; -import javax.json.JsonObjectBuilder; import java.time.temporal.ChronoUnit; import java.util.Map; import java.util.stream.Collectors; diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ThreadedSimulationAgent.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ThreadedSimulationAgent.java index 472ba567e7..86b95f6d1d 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ThreadedSimulationAgent.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/ThreadedSimulationAgent.java @@ -43,45 +43,44 @@ public void terminate() throws InterruptedException { } - private static final class Worker implements Runnable { - private final BlockingQueue requestQueue; - private final SimulationAgent simulationAgent; - - public Worker( - final BlockingQueue requestQueue, - final SimulationAgent simulationAgent) - { - this.requestQueue = Objects.requireNonNull(requestQueue); - this.simulationAgent = Objects.requireNonNull(simulationAgent); - } + private record Worker(BlockingQueue requestQueue, SimulationAgent simulationAgent) + implements Runnable + { + private Worker( + final BlockingQueue requestQueue, + final SimulationAgent simulationAgent) + { + this.requestQueue = Objects.requireNonNull(requestQueue); + this.simulationAgent = Objects.requireNonNull(simulationAgent); + } - @Override - public void run() { - while (true) { - try { - final var request = this.requestQueue.take(); - - if (request instanceof SimulationRequest.Simulate req) { - try { - this.simulationAgent.simulate(req.planId(), req.revisionData(), req.writer()); - } catch (final Throwable ex) { - ex.printStackTrace(System.err); - req.writer().failWith(b -> b - .type("UNEXPECTED_SIMULATION_EXCEPTION") - .message("Something went wrong while simulating") - .trace(ex)); + @Override + public void run() { + while (true) { + try { + final var request = this.requestQueue.take(); + + if (request instanceof SimulationRequest.Simulate req) { + try { + this.simulationAgent.simulate(req.planId(), req.revisionData(), req.writer()); + } catch (final Throwable ex) { + ex.printStackTrace(System.err); + req.writer().failWith(b -> b + .type("UNEXPECTED_SIMULATION_EXCEPTION") + .message("Something went wrong while simulating") + .trace(ex)); + } + // continue + } else if (request instanceof SimulationRequest.Terminate) { + break; + } else { + throw new UnexpectedSubtypeError(SimulationRequest.class, request); } + } catch (final Exception ex) { + ex.printStackTrace(System.err); // continue - } else if (request instanceof SimulationRequest.Terminate) { - break; - } else { - throw new UnexpectedSubtypeError(SimulationRequest.class, request); } - } catch (final Exception ex) { - ex.printStackTrace(System.err); - // continue } } } - } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/TypescriptCodeGenerationServiceAdapter.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/TypescriptCodeGenerationServiceAdapter.java index 7954ea9c1c..751e557065 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/TypescriptCodeGenerationServiceAdapter.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/TypescriptCodeGenerationServiceAdapter.java @@ -11,7 +11,7 @@ import java.util.Optional; import java.util.stream.Collectors; -public class TypescriptCodeGenerationServiceAdapter implements ConstraintsCodeGenService { +public class TypescriptCodeGenerationServiceAdapter { private final MissionModelService missionModelService; private final PlanService planService; @@ -20,7 +20,6 @@ public TypescriptCodeGenerationServiceAdapter(final MissionModelService missionM this.planService = planService; } - @Override public String generateTypescriptTypes(final String missionModelId, final Optional planId) throws MissionModelService.NoSuchMissionModelException, NoSuchPlanException { diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/utilities/FileUtils.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/utilities/FileUtils.java deleted file mode 100644 index 5629dd634d..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/utilities/FileUtils.java +++ /dev/null @@ -1,17 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.utilities; - -import gov.nasa.jpl.aerie.merlin.server.models.MissionModelJar; - -import java.nio.file.Files; -import java.nio.file.Path; - -public final class FileUtils { - public static Path getUniqueFilePath(final MissionModelJar missionModelJar, final Path basePath) { - final String basename = missionModelJar.name; - Path path = basePath.resolve(basename + ".jar"); - for (int i = 0; Files.exists(path); ++i) { - path = basePath.resolve(basename + "_" + i + ".jar"); - } - return path; - } -} diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/utils/HttpRequester.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/utils/HttpRequester.java deleted file mode 100644 index 9205451cfe..0000000000 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/utils/HttpRequester.java +++ /dev/null @@ -1,46 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.utils; - -import javax.json.JsonValue; -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.util.Optional; - -public final class HttpRequester { - private final HttpClient client; - private final URI baseUri; - - public HttpRequester(final HttpClient client, final URI baseUri) { - this.client = client; - this.baseUri = baseUri; - } - - public HttpResponse sendRequest(final String method, final String path) - throws IOException, InterruptedException - { - return sendRequest(method, path, Optional.empty()); - } - - public HttpResponse sendRequest(final String method, final String path, JsonValue body) - throws IOException, InterruptedException - { - return sendRequest(method, path, Optional.of(body)); - } - - public HttpResponse sendRequest(final String method, final String path, final Optional body) - throws IOException, InterruptedException - { - final HttpRequest.BodyPublisher bodyPublisher = body - .map(x -> HttpRequest.BodyPublishers.ofString(x.toString())) - .orElseGet(HttpRequest.BodyPublishers::noBody); - - final HttpRequest request = HttpRequest.newBuilder() - .uri(baseUri.resolve(path)) - .method(method, bodyPublisher) - .build(); - - return this.client.send(request, HttpResponse.BodyHandlers.ofString()); - } -} diff --git a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/DevAppDriver.java b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/DevAppDriver.java deleted file mode 100644 index 1917f0a327..0000000000 --- a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/DevAppDriver.java +++ /dev/null @@ -1,63 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server; - -import gov.nasa.jpl.aerie.merlin.server.http.LocalAppExceptionBindings; -import gov.nasa.jpl.aerie.merlin.server.http.MerlinBindings; -import gov.nasa.jpl.aerie.merlin.server.http.MissionModelRepositoryExceptionBindings; -import gov.nasa.jpl.aerie.merlin.server.mocks.Fixtures; -import gov.nasa.jpl.aerie.merlin.server.mocks.InMemoryMissionModelRepository; -import gov.nasa.jpl.aerie.merlin.server.services.ConstraintsDSLCompilationService; -import gov.nasa.jpl.aerie.merlin.server.services.GenerateConstraintsLibAction; -import gov.nasa.jpl.aerie.merlin.server.services.GetSimulationResultsAction; -import gov.nasa.jpl.aerie.merlin.server.services.LocalMissionModelService; -import gov.nasa.jpl.aerie.merlin.server.services.LocalPlanService; -import gov.nasa.jpl.aerie.merlin.server.services.SynchronousSimulationAgent; -import gov.nasa.jpl.aerie.merlin.server.services.TypescriptCodeGenerationServiceAdapter; -import gov.nasa.jpl.aerie.merlin.server.services.UncachedSimulationService; -import io.javalin.Javalin; - -import java.io.IOException; -import java.nio.file.Path; -import java.time.Instant; - -public final class DevAppDriver { - private static final int HTTP_PORT = 27183; - - public static void main(final String[] args) { - // Assemble the core non-web object graph. - final var fixtures = new Fixtures(); - final var missionModelController = new LocalMissionModelService(Path.of("/dev/null"), new InMemoryMissionModelRepository(), Instant.EPOCH); - final var planController = new LocalPlanService(fixtures.planRepository); - - final var typescriptCodeGenerationService = new TypescriptCodeGenerationServiceAdapter(missionModelController, planController); - - final ConstraintsDSLCompilationService constraintsDSLCompilationService; - try { - constraintsDSLCompilationService = new ConstraintsDSLCompilationService(typescriptCodeGenerationService); - } catch (IOException e) { - throw new Error("Failed to start ConstraintsDSLCompilationService", e); - } - - Runtime.getRuntime().addShutdownHook(new Thread(constraintsDSLCompilationService::close)); - - final var simulationAction = new GetSimulationResultsAction( - planController, - missionModelController, - new UncachedSimulationService(new SynchronousSimulationAgent(planController, missionModelController)), - constraintsDSLCompilationService - ); - - final var generateConstraintsLibAction = new GenerateConstraintsLibAction(typescriptCodeGenerationService); - - // Configure an HTTP server. - final Javalin javalin = Javalin.create(config -> { - config.plugins.enableDevLogging(); - config.plugins.enableCors(cors -> cors.add(it -> it.anyHost())); - config.plugins.register(new MerlinBindings(missionModelController, planController, simulationAction, generateConstraintsLibAction)); - config.plugins.register(new LocalAppExceptionBindings()); - config.plugins.register(new MissionModelRepositoryExceptionBindings()); - }); - - // Start the HTTP server. - javalin.start(HTTP_PORT); - } -} diff --git a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindingsTest.java b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindingsTest.java index 3f6a2e4374..be30bac9ba 100644 --- a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindingsTest.java +++ b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/http/MerlinBindingsTest.java @@ -1,7 +1,5 @@ package gov.nasa.jpl.aerie.merlin.server.http; -import gov.nasa.jpl.aerie.json.JsonParser; -import gov.nasa.jpl.aerie.merlin.server.mocks.FakeFile; import gov.nasa.jpl.aerie.merlin.server.mocks.StubMissionModelService; import gov.nasa.jpl.aerie.merlin.server.mocks.StubPlanService; import gov.nasa.jpl.aerie.merlin.server.services.ConstraintsDSLCompilationService; @@ -10,26 +8,17 @@ import gov.nasa.jpl.aerie.merlin.server.services.SynchronousSimulationAgent; import gov.nasa.jpl.aerie.merlin.server.services.TypescriptCodeGenerationServiceAdapter; import gov.nasa.jpl.aerie.merlin.server.services.UncachedSimulationService; -import gov.nasa.jpl.aerie.merlin.server.utils.HttpRequester; import io.javalin.Javalin; +import io.javalin.plugin.bundled.CorsPluginConfig; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import javax.json.Json; -import javax.json.stream.JsonParsingException; import java.io.IOException; -import java.io.StringReader; -import java.math.BigInteger; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Random; import static org.assertj.core.api.Assertions.assertThat; @@ -63,7 +52,7 @@ public static void setupServer() { SERVER = Javalin.create(config -> { config.showJavalinBanner = false; - config.plugins.enableCors(cors -> cors.add(it -> it.anyHost())); + config.plugins.enableCors(cors -> cors.add(CorsPluginConfig::anyHost)); config.plugins.register(new MerlinBindings(missionModelApp, planApp, simulationAction, generateConstraintsLibAction)); }); @@ -77,19 +66,6 @@ public static void shutdownServer() { private final URI baseUri = URI.create("http://localhost:" + SERVER.port()); private final HttpClient rawHttpClient = HttpClient.newHttpClient(); - private final HttpRequester client = new HttpRequester(rawHttpClient, baseUri); - - private T parseJson(final String subject, final JsonParser parser) - throws InvalidJsonException, InvalidEntityException - { - try { - final var requestJson = Json.createReader(new StringReader(subject)).readValue(); - final var result = parser.parse(requestJson); - return result.getSuccessOrThrow($ -> new InvalidEntityException(List.of($))); - } catch (JsonParsingException e) { - throw new InvalidJsonException(e); - } - } @Test public void shouldEnableCors() throws IOException, InterruptedException { @@ -108,57 +84,4 @@ public void shouldEnableCors() throws IOException, InterruptedException { // THEN assertThat(response.headers().allValues("Access-Control-Allow-Origin")).isNotEmpty(); } - - private HttpResponse sendRequest(final String method, final String path, final Map body) - throws IOException, InterruptedException - { - final String boundary = new BigInteger(256, new Random()).toString(); - final HttpRequest.BodyPublisher bodyPublisher = ofMimeMultipartData(body, boundary); - - return sendRequest(method, path, bodyPublisher, Optional.of(boundary)); - } - - private HttpResponse sendRequest(final String method, final String path, final HttpRequest.BodyPublisher bodyPublisher, final Optional boundary) - throws IOException, InterruptedException - { - final HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); - - if (boundary.isPresent()) { - requestBuilder.headers("Content-Type", "multipart/form-data;boundary=" + boundary.get()); - } - - final HttpRequest request = requestBuilder - .uri(baseUri.resolve(path)) - .method(method, bodyPublisher) - .build(); - - return this.rawHttpClient.send(request, HttpResponse.BodyHandlers.ofString()); - } - - private static HttpRequest.BodyPublisher ofMimeMultipartData(final Map data, final String boundary) { - final StringBuilder bodyBuilder = new StringBuilder(); - for (final var entry : data.entrySet()) { - if (entry.getValue() instanceof FakeFile) { - final FakeFile file = (FakeFile) entry.getValue(); - - bodyBuilder - .append("--").append(boundary).append("\r\n") - .append("Content-Disposition: form-data; ") - .append("name=\"").append(entry.getKey()).append("\"; ") - .append("filename=\"").append(file.filename).append("\"\r\n") - .append("Content-Type: ").append(file.contentType).append("\r\n") - .append("\r\n") - .append(file.contents).append("\r\n"); - } else { - bodyBuilder - .append("--").append(boundary).append("\r\n") - .append("Content-Disposition: form-data; name=\"").append(entry.getKey()).append("\"\r\n") - .append("\r\n") - .append(entry.getValue()).append("\r\n"); - } - } - bodyBuilder.append("--").append(boundary).append("--"); - - return HttpRequest.BodyPublishers.ofString(bodyBuilder.toString(), StandardCharsets.UTF_8); - } } diff --git a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/mocks/Fixtures.java b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/mocks/Fixtures.java deleted file mode 100644 index 820ea473d6..0000000000 --- a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/mocks/Fixtures.java +++ /dev/null @@ -1,77 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.mocks; - -import gov.nasa.jpl.aerie.merlin.driver.ActivityDirectiveId; -import gov.nasa.jpl.aerie.merlin.protocol.types.Duration; -import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchPlanException; -import gov.nasa.jpl.aerie.merlin.driver.ActivityDirective; -import gov.nasa.jpl.aerie.merlin.server.models.NewPlan; -import gov.nasa.jpl.aerie.merlin.server.models.PlanId; -import gov.nasa.jpl.aerie.merlin.server.models.Timestamp; - -import java.util.ArrayList; - -public final class Fixtures { - public final InMemoryPlanRepository planRepository; - public final StubMissionModelService missionModelService; - - public final String EXISTENT_MISSION_MODEL_ID; - public final PlanId EXISTENT_PLAN_ID; - public final String EXISTENT_ACTIVITY_TYPE_ID; - public final ActivityDirectiveId EXISTENT_ACTIVITY_INSTANCE_ID; - public final ActivityDirective EXISTENT_ACTIVITY_INSTANCE; - public final String NONEXISTENT_MISSION_MODEL_ID; - public final String NONEXISTENT_PLAN_ID; - public final String NONEXISTENT_ACTIVITY_TYPE_ID; - public final String NONEXISTENT_ACTIVITY_INSTANCE_ID; - - public Fixtures() { - try { - this.planRepository = new InMemoryPlanRepository(); - this.missionModelService = new StubMissionModelService(); - - this.NONEXISTENT_ACTIVITY_TYPE_ID = StubMissionModelService.NONEXISTENT_ACTIVITY_TYPE; - this.EXISTENT_ACTIVITY_TYPE_ID = StubMissionModelService.EXISTENT_ACTIVITY_TYPE; - - this.NONEXISTENT_MISSION_MODEL_ID = StubMissionModelService.NONEXISTENT_MISSION_MODEL_ID; - this.EXISTENT_MISSION_MODEL_ID = StubMissionModelService.EXISTENT_MISSION_MODEL_ID; - - this.EXISTENT_PLAN_ID = this.planRepository.createPlan(createValidNewPlan("plan 1")).planId(); - this.NONEXISTENT_PLAN_ID = "nonexistent plan"; - - this.planRepository.createPlan(createValidNewPlan("plan 2")); - this.planRepository.createPlan(createValidNewPlan("plan 3")); - - { - final ActivityDirective activity = createValidActivityInstance(); - - this.EXISTENT_ACTIVITY_INSTANCE = activity; - this.EXISTENT_ACTIVITY_INSTANCE_ID = this.planRepository.createActivity(this.EXISTENT_PLAN_ID, activity); - this.NONEXISTENT_ACTIVITY_INSTANCE_ID = "nonexistent activity"; - } - } catch (final NoSuchPlanException ex) { - throw new RuntimeException(ex); - } - } - - public NewPlan createValidNewPlan(final String name) { - final NewPlan plan = new NewPlan(); - - plan.missionModelId = this.EXISTENT_MISSION_MODEL_ID; - plan.name = name; - plan.startTimestamp = Timestamp.fromString("0000-111T22:33:44"); - plan.endTimestamp = Timestamp.fromString("1111-222T00:44:55"); - plan.activityDirectives = new ArrayList<>(); - - return plan; - } - - public ActivityDirective createValidActivityInstance() { - return new ActivityDirective( - Duration.ZERO, - this.EXISTENT_ACTIVITY_TYPE_ID, - StubMissionModelService.VALID_ACTIVITY_INSTANCE.getArguments(), - null, - true - ); - } -} diff --git a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryMissionModelRepositoryTest.java b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryMissionModelRepositoryTest.java deleted file mode 100644 index 68012d2041..0000000000 --- a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/mocks/InMemoryMissionModelRepositoryTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.mocks; - -import gov.nasa.jpl.aerie.merlin.server.remotes.MissionModelRepositoryContractTest; -import org.junit.jupiter.api.Disabled; - -@Disabled -public final class InMemoryMissionModelRepositoryTest extends MissionModelRepositoryContractTest { - @Override - protected void resetRepository() { - this.missionModelRepository = new InMemoryMissionModelRepository(); - } -} diff --git a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/remotes/MissionModelRepositoryContractTest.java b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/remotes/MissionModelRepositoryContractTest.java deleted file mode 100644 index f854bd6757..0000000000 --- a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/remotes/MissionModelRepositoryContractTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package gov.nasa.jpl.aerie.merlin.server.remotes; - -import gov.nasa.jpl.aerie.merlin.server.mocks.InMemoryMissionModelRepository; -import gov.nasa.jpl.aerie.merlin.server.models.MissionModelJar; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.net.URISyntaxException; -import java.nio.file.Path; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -// Note: -// If the tests fail, please try to update the mission model jar file. -// See the `jarFixturePath` field below for the expected (CLASSPATH-relative) location. -public abstract class MissionModelRepositoryContractTest { - private final Path jarFixturePath; - { - try { - jarFixturePath = Path.of( - this.getClass() - .getResource("/gov/nasa/jpl/ammos/mpsa/aerie/foo-missionModel-0.6.0-SNAPSHOT.jar") - .toURI()); - } catch (final URISyntaxException ex) { - throw new Error("Unable to find mission model fixture", ex); - } - } - - protected InMemoryMissionModelRepository missionModelRepository = null; - - protected abstract void resetRepository(); - - @BeforeEach - public void resetRepositoryBeforeEachTest() { - this.resetRepository(); - } - - @Test - public void testGetMissionModel() throws MissionModelRepository.NoSuchMissionModelException { - // GIVEN - final MissionModelJar newMissionModel = createValidMissionModelJar("new-missionModel"); - final String id = this.missionModelRepository.createMissionModel(newMissionModel); - - // WHEN - final MissionModelJar missionModel = this.missionModelRepository.getMissionModel(id); - - // THEN - assertThat(missionModel.mission).isEqualTo(newMissionModel.mission); - } - - @Test - public void testRetrieveAllMissionModels() { - // GIVEN - final String id1 = this.missionModelRepository.createMissionModel(createValidMissionModelJar("test1")); - final String id2 = this.missionModelRepository.createMissionModel(createValidMissionModelJar("test2")); - final String id3 = this.missionModelRepository.createMissionModel(createValidMissionModelJar("test3")); - - // WHEN - final Map missionModels = this.missionModelRepository - .getAllMissionModels(); - - // THEN - assertThat(missionModels.size()).isEqualTo(3); - assertThat(missionModels.get(id1)).isNotNull(); - assertThat(missionModels.get(id2)).isNotNull(); - assertThat(missionModels.get(id3)).isNotNull(); - } - - @Test - public void testCanDeleteAllMissionModels() throws MissionModelRepository.NoSuchMissionModelException { - // GIVEN - final String id1 = this.missionModelRepository.createMissionModel(createValidMissionModelJar("test1")); - final String id2 = this.missionModelRepository.createMissionModel(createValidMissionModelJar("test2")); - final String id3 = this.missionModelRepository.createMissionModel(createValidMissionModelJar("test3")); - - // WHEN - this.missionModelRepository.deleteMissionModel(id1); - this.missionModelRepository.deleteMissionModel(id2); - this.missionModelRepository.deleteMissionModel(id3); - - // THEN - assertThat(this.missionModelRepository.getAllMissionModels()).isEmpty(); - } - - protected MissionModelJar createValidMissionModelJar(final String mission) { - final MissionModelJar missionModel = new MissionModelJar(); - missionModel.name = "foo-missionmodel-0.6.0-SNAPSHOT"; - missionModel.version = "0.0.1"; - missionModel.mission = mission; - missionModel.owner = "Arthur"; - missionModel.path = this.jarFixturePath; - return missionModel; - } -} diff --git a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepositoryContractTest.java b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepositoryContractTest.java index 50dfc3e6c6..0333a02203 100644 --- a/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepositoryContractTest.java +++ b/merlin-server/src/test/java/gov/nasa/jpl/aerie/merlin/server/remotes/PlanRepositoryContractTest.java @@ -5,13 +5,11 @@ import gov.nasa.jpl.aerie.merlin.server.exceptions.NoSuchPlanException; import gov.nasa.jpl.aerie.merlin.server.mocks.InMemoryPlanRepository; import gov.nasa.jpl.aerie.merlin.driver.ActivityDirective; -import gov.nasa.jpl.aerie.merlin.server.models.NewPlan; import gov.nasa.jpl.aerie.merlin.server.models.Plan; import gov.nasa.jpl.aerie.merlin.server.remotes.PlanRepository.CreatedPlan; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.List; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -31,34 +29,14 @@ public void testCanStorePlan() throws NoSuchPlanException { // GIVEN // WHEN - final NewPlan newPlan = new NewPlan(); - newPlan.name = "new-plan"; + final Plan plan = new Plan(); + plan.name = "new-plan"; - final CreatedPlan ids = this.planRepository.createPlan(newPlan); + final CreatedPlan ids = this.planRepository.storePlan(plan); // THEN - final Plan plan = this.planRepository.getPlanForValidation(ids.planId()); - assertThat(plan.name).isEqualTo("new-plan"); - } - - @Test - public void testUnsavedPlanTransactionHasNoEffect() - throws NoSuchPlanException - { - // GIVEN - final NewPlan newPlan = new NewPlan(); - newPlan.name = "before"; - final CreatedPlan ids = this.planRepository.createPlan(newPlan); - - // WHEN - this.planRepository - .updatePlan(ids.planId()) - .setName("after"); - // no .commit() - - // THEN - final Plan plan = this.planRepository.getPlanForValidation(ids.planId()); - assertThat(plan.name).isEqualTo("before"); + final Plan fetchedPlan = this.planRepository.getPlanForValidation(ids.planId()); + assertThat(fetchedPlan.name).isEqualTo("new-plan"); } @Test @@ -68,17 +46,17 @@ public void testCreatePlanWithActivity() throws NoSuchPlanException { // WHEN final ActivityDirective activity = new ActivityDirective(Duration.ZERO, "abc", Map.of("abc", SerializedValue.of(1)), null, true); - final NewPlan newPlan = new NewPlan(); - newPlan.name = "new-plan"; - newPlan.activityDirectives = List.of(); + final Plan plan = new Plan(); + plan.name = "new-plan"; + plan.activityDirectives = Map.of(); - final CreatedPlan ids = this.planRepository.createPlan(newPlan); + final CreatedPlan ids = this.planRepository.storePlan(plan); this.planRepository.createActivity(ids.planId(), activity); // THEN - final Plan plan = this.planRepository.getPlanForValidation(ids.planId()); - assertThat(plan.name).isEqualTo("new-plan"); - assertThat(plan.activityDirectives.values()).containsExactly(activity); + final Plan fetchedPlan = this.planRepository.getPlanForValidation(ids.planId()); + assertThat(fetchedPlan.name).isEqualTo("new-plan"); + assertThat(fetchedPlan.activityDirectives.values()).containsExactly(activity); } @Test @@ -88,7 +66,7 @@ public void testCreatePlanWithNullActivitiesList() // GIVEN // WHEN - final CreatedPlan ids = this.planRepository.createPlan(new NewPlan()); + final CreatedPlan ids = this.planRepository.storePlan(new Plan()); // THEN assertThat(this.planRepository.getPlanForValidation(ids.planId()).activityDirectives).isNotNull().isEmpty(); @@ -97,9 +75,9 @@ public void testCreatePlanWithNullActivitiesList() @Test public void testCanDeletePlan() throws NoSuchPlanException { // GIVEN - this.planRepository.createPlan(new NewPlan()); - final CreatedPlan ids = this.planRepository.createPlan(new NewPlan()); - this.planRepository.createPlan(new NewPlan()); + this.planRepository.storePlan(new Plan()); + final CreatedPlan ids = this.planRepository.storePlan(new Plan()); + this.planRepository.storePlan(new Plan()); assertThat(this.planRepository.getAllPlans()).size().isEqualTo(3); // WHEN