Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,27 @@ import org.opensearch.core.xcontent.ToXContentObject
import org.opensearch.core.xcontent.XContentBuilder
import org.opensearch.core.xcontent.XContentParser
import org.opensearch.core.xcontent.XContentParserUtils
import java.time.Instant

/**
* Represents the payload for an externally scheduled monitor job.
*
* Written to the schedule target (e.g. SQS) by the monitor CRUD path,
* and parsed back by the job poller at execution time.
*
* [jobStartTime] is a String to support both scheduler placeholders
* (e.g. "<aws.scheduler.scheduled-time>") on the producer side and
* actual ISO-8601 timestamps on the consumer side.
*/
data class ScheduleJobPayload(
val monitorId: String,
val jobStartTime: Instant,
val jobStartTime: String,
val monitorConfig: String
) : ToXContentObject {

override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder {
builder.startObject()
builder.field(MONITOR_ID_FIELD, monitorId)
builder.field(JOB_START_TIME_FIELD, jobStartTime.toString())
builder.field(JOB_START_TIME_FIELD, jobStartTime)
builder.field(MONITOR_CONFIG_FIELD, monitorConfig)
builder.endObject()
return builder
Expand All @@ -56,7 +59,7 @@ data class ScheduleJobPayload(

fun parse(xcp: XContentParser): ScheduleJobPayload {
var monitorId: String? = null
var jobStartTime: Instant? = null
var jobStartTime: String? = null
var monitorConfig: String? = null

XContentParserUtils.ensureExpectedToken(
Expand All @@ -69,7 +72,7 @@ data class ScheduleJobPayload(
xcp.nextToken()
when (fieldName) {
MONITOR_ID_FIELD -> monitorId = xcp.text()
JOB_START_TIME_FIELD -> jobStartTime = Instant.parse(xcp.text())
JOB_START_TIME_FIELD -> jobStartTime = xcp.text()
MONITOR_CONFIG_FIELD -> monitorConfig = xcp.text()
else -> xcp.skipChildren()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import org.opensearch.commons.alerting.parser
import org.opensearch.commons.alerting.randomQueryLevelMonitor
import org.opensearch.commons.alerting.xContentRegistry
import org.opensearch.core.xcontent.ToXContent
import java.time.Instant

class ScheduleJobPayloadTests {

Expand All @@ -26,7 +25,7 @@ class ScheduleJobPayloadTests {
val monitor = randomQueryLevelMonitor().copy(id = "mon-123")
val payload = ScheduleJobPayload(
monitorId = monitor.id,
jobStartTime = Instant.parse("2026-04-23T10:00:00Z"),
jobStartTime = "2026-04-23T10:00:00Z",
monitorConfig = serializeMonitor(monitor)
)

Expand All @@ -36,16 +35,33 @@ class ScheduleJobPayloadTests {

val parsed = ScheduleJobPayload.parse(parser(json))
assertEquals("mon-123", parsed.monitorId)
assertEquals(Instant.parse("2026-04-23T10:00:00Z"), parsed.jobStartTime)
assertEquals("2026-04-23T10:00:00Z", parsed.jobStartTime)
assertEquals(payload.monitorConfig, parsed.monitorConfig)
}

@Test
fun `round-trip with EB placeholder as jobStartTime`() {
val monitor = randomQueryLevelMonitor().copy(id = "mon-eb")
val payload = ScheduleJobPayload(
monitorId = monitor.id,
jobStartTime = "<aws.scheduler.scheduled-time>",
monitorConfig = serializeMonitor(monitor)
)

val builder = org.opensearch.common.xcontent.XContentFactory.jsonBuilder()
payload.toXContent(builder, ToXContent.EMPTY_PARAMS)
val json = builder.toString()

val parsed = ScheduleJobPayload.parse(parser(json))
assertEquals("<aws.scheduler.scheduled-time>", parsed.jobStartTime)
}

@Test
fun `toMonitor preserves id and fields`() {
val monitor = randomQueryLevelMonitor().copy(id = "mon-456")
val payload = ScheduleJobPayload(
monitorId = monitor.id,
jobStartTime = Instant.now(),
jobStartTime = "2026-04-23T10:00:00Z",
monitorConfig = serializeMonitor(monitor)
)

Expand All @@ -63,7 +79,7 @@ class ScheduleJobPayloadTests {
)
val payload = ScheduleJobPayload(
monitorId = monitor.id,
jobStartTime = Instant.now(),
jobStartTime = "2026-04-23T10:00:00Z",
monitorConfig = serializeMonitor(monitor)
)

Expand All @@ -84,4 +100,15 @@ class ScheduleJobPayloadTests {
ScheduleJobPayload.parse(parser(json))
}
}

@Test
fun `parse throws on missing jobStartTime`() {
val monitor = randomQueryLevelMonitor()
val json = "{\"monitorId\":\"mon-123\"," +
"\"monitorConfig\":\"${serializeMonitor(monitor).replace("\"", "\\\"")}\"}"

org.junit.jupiter.api.assertThrows<IllegalArgumentException> {
ScheduleJobPayload.parse(parser(json))
}
}
}
Loading