blakenetz / which-weather

0 stars 0 forks source link

Grid Layout #5

Open blakenetz opened 3 days ago

blakenetz commented 3 days ago

Columns should be shared across client rows and should represent a consistent time.

Details

Currently, each client row is scrollable and has unique intervals between cards. For example, AccuWeather displays forecast data in 24 hour intervals, while OpenWeather displays it in 3 hour intervals. To make the comparisons more useful, the grid element should only have a single x-axis scroll and the intervals should be consistent.

Hurdles

Currently, each client has its own endpoint. This is so if one fails or is slow, the others can still display data as it comes in. If we continue with this approach, we would need one of 2 options:

  1. Make forecast return value extremely strict and drop/merge data that doesn't fit in established interval
  2. Reformat data on the FE once data comes in.

If going with option 1, internationalization will be a factor. Since the server location of the API client is unknown, there is uncertainty of what time the first forecast element will be and how that impacts what the web client will display. If going with option 2, the React client will jump and re-paint numerous times, leading to poor UX .

blakenetz commented 2 days ago

I've been thinking further about this and have a solution that will allow for asynchronous data fetching per client, while still showing data in a uniform fashion, however the UI will have to be updated to reflect the different data types. Essentially, the server will return 2 data types: aggregated forecast data and individual client data

  1. Create a single endpoint that fetches data for all client: /forecast
  2. Once the request is received, create a readable stream
  3. Asynchronously fetch data from all the clients
  4. When one resolves, write to the results to the readable stream
  5. When all resolve, unify the data, end stream, and return to client.

Here's the psuedo-code:

// start stream
response.setHeader(...)
response.write("{")

const data = await Promise.all(
    clients.map(client => {
        return service.fetchForecastByClient(client, resonseBody).then((results) => {
            // write to stream
            response.write(client + ":"  + JSON.stringify(results) + ',')
            return results
        }) 
    })
)

response.write("}")
response.end()

const gridData = standardizeDataAcrossDates(data)
return gridData