diff --git a/Design.md b/Design.md index 343af40..b054e4f 100644 --- a/Design.md +++ b/Design.md @@ -8,7 +8,7 @@ To allow users to enter up to 8 locations and have the highs and lows display on | SE | | | CQ | | | CQ | WS | | -## Explanation +## Definitions The wheel is based on the movement of the sun and determines the seasons of the year. @@ -168,7 +168,7 @@ than half of their latitudes as negatives. ## 2. Database -### Description +#: TBD ### Requirements @@ -255,7 +255,13 @@ access the tables, or a setting / parameter can be set to default to them. Today's high and low are accessible when joining to the `LOC_WEATHER` table, which is necessary anyways to get to the `WEATHER_DATE` and `ZIP_CODE`. -Extended high and low are for `WEATHER_DATE + 7`, so a week from the date. +Extended high and low are for the furthest accessible day up to a week out. +```sql +SELECT loc_weather_id, max(weather_date) + FROM loc_weather + WHERE weather_date <= sysdate+7 + GROUP BY loc_weather_id; +``` ### Roles @@ -338,6 +344,47 @@ For each `ZIP_CODE`, calculate the following: - Weekly Mean - Weekly Median - Weekly Mode +- Tomorrow + ```sql + -- Can be done the same as Extended, just change the sysdate+7 to sysdate+1. + ``` +- Extended + - Example: + ```sql + -- Need to get the max(weather_date) per loc_id, identify its loc_weather_id, then use that to join against the agg table. + + -- Temp view of the latest date that each location has. + SELECT lw.loc_id, max(lw.weather_date) + FROM loc_weather lw + WHERE lw.weather_date <= sysdate + 7 + GROUP BY lw.loc_id; + + -- Joining the temp view to the table to get the individual records. + SELECT lw.loc_weather_id, lw.high, lw.low + FROM loc_weather lw + , (SELECT lw.loc_id, max(lw.weather_date) as weather_date + FROM loc_weather lw + WHERE lw.weather_date <= sysdate + 7 + GROUP BY lw.loc_id) t + WHERE lw.loc_id = t.loc_id + AND lw.weather_date = t.weather_date; + + -- Merging the data into the agg table. + MERGE INTO loc_weather_agg o + USING (SELECT lw.loc_weather_id, lw.high, lw.low + FROM loc_weather lw + , (SELECT lw.loc_id, max(lw.weather_date) as max_weather_date + FROM loc_weather lw + WHERE lw.weather_date <= sysdate + 7 + GROUP BY lw.loc_id) t + WHERE lw.loc_id = t.loc_id + AND lw.weather_date = t.max_weather_date) i + ON (o.loc_weather_id = i.loc_weather_id) + WHEN MATCHED THEN UPDATE + SET o.extended_high = i.high + , o.extended_low = i.low; + commit; + ``` ## 4. Response API @@ -359,8 +406,33 @@ Listener API which receives requests from the front end and queries the database - Program shall post any new zip codes in the `loc` table. - program shall update `loc.last_accessed_date` for the zip codes it retrieved data for. +### Flow + +1. Initialize. +1. Parse request. (Appendix #1) +1. Merge zip codes to `loc`. +1. Notify `weatherman` if new zip codes exist. + - Wait until a continue or error is replied. + - If continue, proceed to next steps. + - If error, provide error to user (Appendix #8) +1. Pull weather data from `loc_weather` and `loc_weather_agg`. +1. Form and deliver response. (Appendix #2) + # Appendix - JSON Requests and Responses +Between the programs being developed there are 3 themes being used regarding message intent. + +**data** +: These messages pass information back and forth. + +**command** +: These are used to notify programs that actions need taken. + +**error** +: These notify that something went wrong and may provide a message with which to return to the front end. + +Theintent is passed at the JSON object's root level `"message_type"` attribute. The rest of the payload lies within an attribute named the same as the message type. + ## 1. Request: Front End to Response API - Data shall be de-duplicated so that any one zip only appears once. @@ -371,6 +443,7 @@ response to provide, in case the format changes in the future. ```json { "version": "1.0", + "message_type": "data", "data": [ "zip_code": "85901", "zip_code": "86004", @@ -389,6 +462,7 @@ response to provide, in case the format changes in the future. ```json { "version": "1.0", + "message_type": "data", "data": [ { "zip_code": "85901", @@ -449,25 +523,28 @@ response to provide, in case the format changes in the future. Notification from the `reporter` for the `weatherman` to kick off an ad hoc run. -This data never leaves the server and cannot come from outside sources, the endpoint will not available to the public, it is accessed via localhost. - -Zip codes do not need provided since the `reporter` has already inserted and committed them to `loc`. +- This data never leaves the server and cannot come from outside sources, the endpoint will not available to the public, it is accessed via localhost. +- Zip codes do not need provided since the `reporter` has already inserted and committed them to `loc`. +- `reporter` runs this in a synchronous fashion, waiting for the response before continuing to reply to the user. ```json { - "data": "run", + "message_type": "command", + "command": "run", } ``` ## 6. Response: ZIP_CODE Data Now Available -Response from `weatherman` program to `reporter`. +Response from `weatherman` program to `reporter` that the new zip codes inserted into the DB have data. + +- If the `reporter` sees this, then it continues with building a response for the front end user. -If the `reporter` sees this, then it continues with building a response for the front end. ```json { - "data": "ready", + "message_type": "command", + "command": "continue", } ``` @@ -479,7 +556,18 @@ If the `reporter` happens to see this, it provides ```json { - "data": "error", + "message_type": "error", "error": "Message about what went wrong, which may get forwarded to the user.", } ``` + +## 8. Response: Error to Front End + +Sometimes the `reporter` may need to let the user know things did not go as planned. + +```json +{ + "message_type": "error", + "error": "Failed to pull weather information. REASON.", +} +```