Source material:
...
Motivations:
Existing Evaluations have a very inflexible way to define rounds:
Code Block | ||
---|---|---|
| ||
{
"name":"SubmissionQuota",
"description":"Maximum submissions per team/participant per submission round. If round information is omitted, then this indicates the overall submission limit per team/participant.",
"properties":{
"firstRoundStart": {
"type": "string",
"format": "date-time",
"description": "The date/time at which the first round begins."
},
"roundDurationMillis":{
"type": "integer",
"description":"The duration of each round."
},
"numberOfRounds":{
"type": "integer",
"description":"The number of rounds, or null if there is no end."
},
"submissionLimit": {
"type": "integer",
"description":"the maximum number of submissions per team/participant per round."
}
}
} |
The existing way to define Round limits assume that all rounds will last for the same duration and that later rounds will begin immediately as soon as the previous round ends. Users are also forced to perform unix timestamp calculations in order to set the round end datetime. There was also no fine grained submission limit control over Submission limits per user or participating team.
Proposed Changes
The goal is to provide users with more fine grained control over each Round in an Evaluation. This means:
Clearly defined start and end dates for each round.
No more startDate + roundNumber * roundDruation math for the end date
Per-round submission limits. These limits should be changeable even during an ongoing round
cumulative limit for the entire round
per day - defined as every 24 hours from the start date
per week - defined as every 7 days from the start date
per month
monthly reset on every n-th day of the month. Use n==31, for end of month.
By default could be filled in with same day of month as the start of round
Requires adding a time zone field for the entire Evaluation queue since the day could be off by 1 depending on the time zone
OR monthly reset every 30 days.
Add/remove/modify rounds without affecting other rounds
Change start date if round not yet started
Change end date if round not yet ended
Add/delete/change new rounds that start after the current time.
User’s Submissions will be automatically tagged with the index number of the current round
Additional metadata column in Submission views
Allow Evaluation Queue Admins to schedule a Maintenance date range that disallows Submissions
Independent of defined rounds - neither the ongoing rounds nor later rounds will have their start/end date modified as a result of maintenance
API Schema
Evaluation
Add timeZone
, rounds
. Deprecate quota
timeZone
will use long names (e.g. “US/Pacific”) instead of 3-letter names (e.g. PDT, PST) to account for Daylight savings
Code Block | ||
---|---|---|
| ||
{
"description": "An Evaluation is the core object of the Evaluation API, used to support collaborative data analysis challenges in Synapse.",
"name": "Evaluation",
"properties": {
"....currently existing fields...":{}
"quota": {
"type":"object",
"description":"DEPRECATED. Maximum submissions per team/participant per submission round",
"$ref":"org.sagebionetworks.evaluation.model.SubmissionQuota"
},
"timeZone": {
"type": "string",
"description": "The time zone to be used for all round configurations."
},
"rounds": {
"type": "array",
"items": {
"$ref": "org.sagebionetworks.evaluation.model.SubmissionRound"
}
}
}
} |
SubmissionRound (EvaluationRound?)
Defines roundStart
and roundEnd
dates.
...
id
is a UUID generated to identify rounds for updating
submissionLimit
is used to set submission limits
Code Block |
---|
{
"name":"SubmissionRound",
"description":"Defines the duration of a round and sets limits for maximum submissions per round",
"properties":{
"id": {
"type": "string",
"description": "The id of the SubmissionRound"
}, 2020-08-11T16:45:10+0000
"roundStart": {
"type": "string",
"format": "date-time",
"description": "The date/time at which the first round begins.",
"required": true
},
"roundEnd":{
"type": "string",
"format": "date-time",
"description":"The date/time at which the round ends.",
"required": true
},
"submissionLimit": {
"type": {
"$ref": "org.sagebionetworks.evaluation.model.SubmissionRoundLimit"
},
"description": "Optional. Sets limits for maximum submissions in this round."
}
}
} |
SubmissionRoundLimit
Limits for day, week, month, and total
monthlySubmissionLimit
is defined in a separate object
Code Block | ||
---|---|---|
| ||
{
"name":"SubmissionRoundLimit",
"description": "Sets limits for maximum submissions in a SubmissionRound",
"properties":{
"totalSubmissionLimit": {
"type": "integer",
"description": "The maximum total number of submissions per team/participant for the entirety of the round."
},
"dailySubmissionLimit": {
"type": "integer",
"description": "The maximum total number of submissions per team/participant for each day of the round."
},
"weeklySubmissionLimit": {
"type": "integer",
"description": "The maximum total number of submissions per team/participant for every 7 days of the round."
},
"monthlySubmissionLimit": {
"type": {
"$ref": "org.sagebionetworks.evaluation.model.SubmissionRoundMonthlyLimit"
},
"description": "The maximum total number of submissions per team/participant per month. Unlike other limits, this can be configured to reset on the n-th day of every month.",
}
}
} |
SubmissionRoundMonthlyLimit
Code Block |
---|
{
"properties": {
"dayOfMonth": {
"type": "integer",
"description": "Day of the month on which this date this limit is reset."
},
"limit": {
"type": "integer",
"description": "The maximum total number of submissions per team/participant per month."
}
}
} |
Example Evaluation
id
will be back-end generated after it has been created
...
Source material:
UI Design:
https://www.figma.com/file/E5zIAPsI2fagDc8btWGU06Ol/Challenge-Evaluation-Queue
Use case/desired behavior:
https://docs.google.com/document/d/19M9og2JW7CaG7YLNi8cCRhFuFwF-y6-nx4CJDAwr6qw/edit#heading=h.y0949lyt5na0
Motivations:
Existing Evaluations have a very inflexible way to define rounds:
Code Block | ||
---|---|---|
| ||
{
"name":"SubmissionQuota",
"description":"Maximum submissions per team/participant per submission round. If round information is omitted, then this indicates the overall submission limit per team/participant.",
"properties":{
"firstRoundStart": {
"type": "string",
"format": "date-time",
"description": "The date/time at which the first round begins."
},
"roundDurationMillis":{
"type": "integer",
"description":"The duration of each round."
},
"numberOfRounds":{
"type": "integer",
"description":"The number of rounds, or null if there is no end."
},
"submissionLimit": {
"type": "integer",
"description":"the maximum number of submissions per team/participant per round."
}
}
} |
The existing way to define Round limits assume that all rounds will last for the same duration and that later rounds will begin immediately as soon as the previous round ends. Users are also forced to perform unix timestamp calculations in order to set the round end datetime. There was also no fine grained submission limit control over Submission limits per user or participating team.
High level changes
The goal is to provide users with more fine grained control over each Round in an Evaluation. This means:
Clearly defined start and end dates for each round.
Initial design will not allow unbounded start or end dates.
The old SubmissionQuota system does allow unbounded start dates, end dates , or both.
No more startDate + roundNumber * roundDruation math for the end date
Per-round submission limits. These limits should be changeable even during an ongoing round
cumulative limit for the entire round
per day - resets every day at 00:00 UTC
per week - resets every Monday at 00:00 UTC
per month - resets at 00:00 UTC on the 1st day of every month
Add/remove/modify rounds without affecting other rounds
Change start datetime if round not yet started (current time < start time) AND 0 submissions were made
If 0 submissions made, the round may still be updated/deleted even if the time is past the start date
Change end date to any time in the future (current time < end time)
Setting the end datetime to a later time is always allowed
Setting end datetime to a time in the past is not allowed.
Add/delete/change new rounds that have not yet started.
Validation
Disallow intersecting time intervals between rounds
i.e. no overlap between time ranges of any 2 rounds belonging to the same
Evaluation
SubmissionQuota
andEvaluationRounds
may not both exist. must pick one or the other
User’s Submissions will be automatically tagged with the
id
of the currentEvaluationRound
Additional metadata column in Submission views
Allow Evaluation Queue Admins to schedule a Maintenance date range that disallows SubmissionsIndependent of defined rounds - neither the ongoing rounds nor later rounds will have their start/end date modified as a result of maintenanceNot implemented
API Schema
Evaluation
Deprecate quota
.
New evaluation round will be a list of objects which will be accessible via a new API
Code Block | ||
---|---|---|
| ||
{
"description": "An Evaluation is the core object of the Evaluation API, used to support collaborative data analysis challenges in Synapse.",
"name": "Evaluation",
"properties": {
"....currently existing fields...":{}
"quota": {
"type":"object",
"description":"DEPRECATED. Maximum submissions per team/participant per submission round",
"$ref":"org.sagebionetworks.evaluation.model.SubmissionQuota"
}
}
} |
EvaluationRoundRequest
Used to retrieve all EvaluationRounds
associated with an Evaluation
. Results are paginated. Use nextPageToken
to retrieve the next page of results.
Code Block |
---|
{
"description": "Response of EntityHeaders for the children of a given parent Entity",
"properties": {
"nextPageToken": {
"type": "string",
"description": "Token that can be used to get the next page. If null, first page is returned."
}
} |
EvaluationRoundResponse
One page of EvaluationRounds
associated with an Evaluation
. Use the givennextPageToken
in the next EvaluationRoundRequest
to retrieve the next page of results.
Code Block |
---|
{ "description": "Response of EntityHeaders for the children of a given parent Entity", "properties": { "page": { "submissionLimittype":{ "array", "totalSubmissionLimitdescription":40, "The rounds in this evaluation.", "dailySubmissionLimititems":8, { "weeklySubmissionLimit$ref":12, "org.sagebionetworks.evaluation.model.EvaluationRound" } "monthlySubmissionLimit":{ }, "dayOfMonth"nextPageToken":31, { "limittype":20 "string", "description": "Token }that can be used to get the next page. }Null if there are no more results." } ] } |
EvaluationMaintenance
disallows all submissions
only 1 allowed per queue
Code Block |
---|
{ "properties": { "start": { } } |
EvaluationRound
Defines roundStart
and roundEnd
dates.
id
can used for updates if we store rounds in a separate table
limits
is used to set limits on submissions
Code Block | ||
---|---|---|
| ||
{ "description":"Defines the duration of a round and sets limits for maximum submissions per round", "properties":{ "id": { "type": "string", "description": "The id of the EvaluationRound" }, "etag": { "formattype": "date-timestring", "description": "Synapse employs an Optimistic Concurrency Control (OCC) scheme "description": "The date/time at which the maintenance begins.", "required": true }, "end":{ to handle concurrent updates. The eTag changes every time an EvaluationRound is updated; it is used to detect when a client's copy of an Evaluation is out-of-date." }, "evaluationId": { "type": "string", "format "description": "date-time",The Evaluation to which this EvaluationRound "description":"The date/time at which the maintenance ends.", belongs", "required": true }, "roundStart": { "type": "string", "format": "date-time", "description": "The date/time at which the first round begins.", "required": true }, } } |
API Endpoints
Endpoint | Request body | Return Body | Description |
---|---|---|---|
None | Evaluation | EXISTING endpoint to get evaluation | |
Evaluation | Evaluation | EXISTING endpoint to create an evaluation | |
Evaluation | Evaluation | EXISTING endpoint to update evaluation | |
POST /evaluation/{evalId}/maintainance | EvaluationMaintenance | None or EvaluationMaintenance | Schedule a maintainance. Additional calls will override the existing maintenance window |
DELETE /evaluation/{evalId}/maintainance | None | None | Delete the existing maintenance window, if any |
API/Database Transition
A SubmissionQuota
can easily be mapped into into a list of SubmissionRound
s using math, but the reverse is not true.
For the time being, I’m considering making the old deprecated quota
field remain stored in the database, but enforce a rule such that user must choose between quota
and rounds
when configuring a Evaluation
. This allows time for clients to implement support for the new rounds
field.
Once we fully decide to remove SubmissionQuota
, we can perform the conversion and store quotas asSubmissionRound
.
...
},
"roundEnd":{
"type": "string",
"format": "date-time",
"description":"The date/time at which the round ends.",
"required": true
},
"limits": {
"type": "array",
"items": {
"$ref": "org.sagebionetworks.evaluation.model.EvaluationRoundLimit"
},
"description": "Optional. Sets limits for maximum submissions in this round."
}
}
} |
EvaluationRoundLimit
Limits for total submission limit for the round, and a list of periodically resetting limits.
Code Block | ||
---|---|---|
| ||
{
"description": "Sets limits for maximum submissions in a SubmissionRound. Each limitType may only appear once in an EvaluationRound's list of limits",
"properties":{
"limitType":{
"type": "string",
"name": "EvaluationRoundLimitType",
"required": true,
"enum": [
{
"name": "TOTAL",
"description": "Limits maximum submissions for the entire duration of the round."
},
{
"name": "DAILY",
"description": "Limits maximum submissions per day. Resets daily at 00:00:00 UTC"
},
{
"name": "WEEKLY",
"description": "Limits maximum submissions per calendar week. Resets every Monday at 00:00:00 UTC"
},
{
"name": "MONTHLY",
"description": "Limits maximum submissions per calendar month. Resets on the 1st day of every calendar month at 00:00:00 UTC"
}
]
},
"maximumSubmissions": {
"type": "integer",
"required": true,
"description": "maximum number of submissions allowed within the time period defined by the the limitType"
}
}
} |
Example Evaluation
id
will be back-end generated after it has been created. For roundStart
and roundEnd
, both UNIX timestamp in milliseconds and ISO time format are accepted
Code Block | ||
---|---|---|
| ||
{
"....currently existing fields...":{},
"timeZone":"US/Pacific",
"rounds":[
{
"id":"1",
"roundStart":1231412213213123123,
"roundEnd":"2020-08-11T16:45:10−08:00",
"submissionLimit":[
{
"limitType": "TOTAL"
"maximumSubmissions":5
},
{
"limitType": "WEEKLY"
"maximumSubmissions":2
}
]
},
{
"id":"2",
"roundStart":1231412213213123123,
"roundEnd":"2020-08-11T16:45:10−08:00",
"submissionLimit":[
{
"limitType": "DAILY"
"maximumSubmissions":2
},
{
"limitType": "MONTHLY"
"maximumSubmissions":8
}
]
}
]
} |
EvaluationMaintenance Not implemented
disallows all submissionsonly 1 allowed per queue
Code Block | ||
---|---|---|
| ||
{
"properties": {
"start": {
"type": "string",
"format": "date-time",
"description": "The date/time at which the maintenance begins.",
"required": true
},
"end":{
"type": "string",
"format": "date-time",
"description":"The date/time at which the maintenance ends.",
"required": true
},
}
} |
API Endpoints
Endpoint | Request body | Response Body | Description |
---|---|---|---|
None | Evaluation | EXISTING endpoint to get evaluation | |
Evaluation | Evaluation | EXISTING endpoint to create an evaluation | |
Evaluation | Evaluation | EXISTING endpoint to update evaluation | |
POST /evaluation/{evalId}/round/ | EvaluationRound | EvaluationRound | Update rounds for this evaluation. |
|
|
| |
GET /evaluation/{evalId}/round/list | EvaluationRoundRequest | EvaluationRoundResponse | Retrieves all rounds associated with this evaluation. Results are paginated |
GET /evaluation/{evalId}/round/{evalRoundId} | EvaluationRound | Retrieves an EvaluationRound identified by its evalRoundId | |
PUT /evaluation/{evalId}/round/{evalRoundId} | EvaluationRound | EvaluationRound | Updates an existing EvaluationRound |
DELETE /evaluation/{evalId}/round/{evalRoundId} | Deletes an existing EvaluationRound | ||
|
|
|
|
|
|
|
|
|
|
|
|
API/Database Transition
A SubmissionQuota
can easily be mapped into into a list of SubmissionRound
s using math, but the reverse is not true.
For the time being, I’m considering making the old deprecated quota
field remain stored in the database, but enforce a rule such that user must choose between quota
and the new EvaluationRounds API when configuring a Evaluation
. This allows time for clients to implement support for the new API.
Once we fully decide to remove SubmissionQuota
, we can perform the conversion and store quotas asSubmissionRound
.SubmissionQuota
currently allows unbounded round start/end dates by setting null
. This would not be desired behavior for EvaluationRounds
because it would complicate queries that involve date ranges. We can mimic the unbounded time range by migrating the start/end to some time far in the past or future ( best of luck to the devs dealing with this in 2324 AD ! ).
Database Tables
2 Options:
Separate Table For Rounds (primary key is evaluationId , ID) index on roundStart and roundEnd
Allows us to pull out one specific R limit
Limits are enforced in Java code so we can store the them as JSON
generated unique ID makes it easy to perform updates on evaluations
evaluationId(BIGINT)(Foreign Key to Evaluations Table) | ID(BIGINT) | roundStart(DATETIME) | roundEnd(DATETIME) | Limits(JSON) | ||
---|---|---|---|---|---|---|
123 | 1 |
|
|
| ||
123 | 2 |
|
| … | ||
456 | 1 |
|
| … | ||
789 | 1 |
|
| … |
Evaluation_maintenance table
Records maintenance windows for each evaluation.
evaluationId(BIGINT)(Foreign Key to Evaluations Table) | startDate(TIMESTAMP) | endDate(TIMESTAMP) |
---|---|---|
|
|
|
|
|
|
JDOSUBMISSION table
Add EVALUATION_ROUND, which is the round number during which it was submitted. This will be replicated into Submission Views.
Existing table:
Code Block | ||
---|---|---|
| ||
ID BIGINT NOT NULL,
NAME varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
EVALUATION_ID BIGINT NOT NULL,
USER_ID BIGINT NOT NULL,
SUBMITTER_ALIAS varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
ENTITY_ID BIGINT NOT NULL,
ENTITY_BUNDLE mediumblob,
ENTITY_VERSION BIGINT NOT NULL,
CREATED_ON BIGINT NOT NULL,
TEAM_ID BIGINT,
DOCKER_REPO_NAME varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
DOCKER_DIGEST varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, |