Skip to content

Commit

Permalink
fix: move updated date to ms (#107)
Browse files Browse the repository at this point in the history
Move lastUpdatedDate saved in the server to ms to have more precision
when asking for listings to the signature server
  • Loading branch information
Melisa Anabella Rossi authored Nov 3, 2023
1 parent d5162a3 commit f9e0bc7
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 57 deletions.
3 changes: 2 additions & 1 deletion src/adapters/rentals.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { RentalListing } from '@dcl/schemas'

export type TileRentalListing = Pick<RentalListing, 'expiration' | 'periods'>
export type TileRentalListing = Pick<RentalListing, 'expiration' | 'periods' | 'updatedAt'>

export function convertRentalListingToTileRentalListing(
rentalListing: RentalListing
): TileRentalListing {
return {
expiration: rentalListing.expiration,
periods: rentalListing.periods,
updatedAt: rentalListing.updatedAt
}
}
7 changes: 3 additions & 4 deletions src/controllers/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ export async function setupRouter(
const router = new Router<GlobalContext>()

const { district, map } = components
const getLastModifiedTime = () => map.getLastUpdatedAt() * 1000
const lastModifiedMiddlewareByMapDate =
lastModifiedMiddleware(getLastModifiedTime)
lastModifiedMiddleware(map.getLastUpdatedAt)

router.get(
'/v1/tiles',
Expand All @@ -52,15 +51,15 @@ export async function setupRouter(
)
router.get(
'/v1/minimap.png',
lastModifiedMiddleware(getLastModifiedTime, {
lastModifiedMiddleware(map.getLastUpdatedAt, {
maxAge: 600,
staleWhileRevalidate: 600,
}),
miniMapHandler
)
router.get(
'/v1/estatemap.png',
lastModifiedMiddleware(getLastModifiedTime, {
lastModifiedMiddleware(map.getLastUpdatedAt, {
maxAge: 600,
staleWhileRevalidate: 600,
}),
Expand Down
69 changes: 45 additions & 24 deletions src/modules/api/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export async function createApiComponent(components: {
}

async function fetchUpdatedData(
updatedAfter: number,
updatedAfterInMs: number,
oldTiles: Record<string, Tile>
) {
try {
Expand All @@ -255,7 +255,7 @@ export async function createApiComponent(components: {
orderBy: updatedAt,
orderDirection: asc,
where: {
updatedAt_gt: "${updatedAfter}",
updatedAt_gt: "${fromMillisecondsToSeconds(updatedAfterInMs)}",
category: parcel
}
) ${parcelFields}
Expand All @@ -264,7 +264,7 @@ export async function createApiComponent(components: {
orderBy: updatedAt,
orderDirection: asc,
where: {
updatedAt_gt: "${updatedAfter}",
updatedAt_gt: "${fromMillisecondsToSeconds(updatedAfterInMs)}",
category: estate
}
) {
Expand All @@ -277,9 +277,10 @@ export async function createApiComponent(components: {
}
}`
)
const updatedRentalListings = rentals.getUpdatedRentalListings(
fromSecondsToMilliseconds(updatedAfter)
)
const updatedRentalListings =
// timestamp in signatures server has microsecond precision. Adding one to avoid returning
// the same rental listing previously saved
rentals.getUpdatedRentalListings(updatedAfterInMs + 1)

let parcels: ParcelFragment[] = []
let estates: EstateFragment[] = []
Expand Down Expand Up @@ -329,7 +330,7 @@ export async function createApiComponent(components: {
tiles: [],
parcels: [],
estates: [],
updatedAt: updatedAfter,
updatedAt: updatedAfterInMs,
}
}

Expand Down Expand Up @@ -371,8 +372,10 @@ export async function createApiComponent(components: {
isNftIdFromParcel(rentalListing.nftId) &&
tilesByTokenId[tokenId]
) {
const currentTile = tilesByTokenId[tokenId]
return {
...tilesByTokenId[tokenId],
...currentTile,
updatedAt: Math.max(currentTile.updatedAt, rentalListing.updatedAt),
rentalListing: isRentalListingOpen(rentalListing)
? convertRentalListingToTileRentalListing(rentalListing)
: undefined,
Expand All @@ -383,6 +386,7 @@ export async function createApiComponent(components: {
) {
return tilesByEstateId[tokenId].map((tile) => ({
...tile,
updatedAt: Math.max(tile.updatedAt, rentalListing.updatedAt),
rentalListing: isRentalListingOpen(rentalListing)
? convertRentalListingToTileRentalListing(rentalListing)
: undefined,
Expand Down Expand Up @@ -449,39 +453,53 @@ export async function createApiComponent(components: {
estates: [...updatedEstates, ...updatedEstatesFromEstates],
}

// tiles already have the updateAt value in ms
const tilesLastUpdatedAt = batch.tiles.reduce<number>(
(updatedAt, tile) => Math.max(updatedAt, tile.updatedAt),
0
)
const estatesLastUpdatedAt = estates.reduce<number>(
(updatedAt, estate) =>
Math.max(updatedAt, parseInt(estate.updatedAt, 10)),
0
)
const rentalListingsUpdatedAt = fromMillisecondsToSeconds(
Object.values(rentalListingByNftId).reduce<number>(
(updatedAt, rentalListing) =>
Math.max(updatedAt, rentalListing.updatedAt),

// using estes from graph so we need to convert the updatedAt in ms as they come in seconds
const estatesLastUpdatedAt = fromSecondsToMilliseconds(
estates.reduce<number>(
(updatedAt, estate) =>
Math.max(updatedAt, parseInt(estate.updatedAt, 10)),
0
)
)

const rentalListingsUpdatedAt = Object.values(
rentalListingByNftId
).reduce<number>(
(updatedAt, rentalListing) =>
Math.max(updatedAt, rentalListing.updatedAt),
0
)

// As both values are obtained simultaneously we can get the max from both of them and no data loss
// will ocurr
const lastUpdatedParcelOrEstate = Math.max(
tilesLastUpdatedAt,
estatesLastUpdatedAt
)

// Gets the minimum last updated time or the original updatedAfter time.
// Getting the minimum is required due to the rental listings being fetched multiple times, making
// it possible to have an estate or parcel update in the meantime.
const updatedAt = Math.max(
Math.min(
tilesLastUpdatedAt === 0 ? Number.MAX_VALUE : tilesLastUpdatedAt,
estatesLastUpdatedAt === 0 ? Number.MAX_VALUE : estatesLastUpdatedAt,
lastUpdatedParcelOrEstate === 0
? Number.MAX_VALUE
: lastUpdatedParcelOrEstate,
rentalListingsUpdatedAt === 0
? Number.MAX_VALUE
: rentalListingsUpdatedAt
),
updatedAfter
updatedAfterInMs
)

console.log(
`Last updates | tiles: ${tilesLastUpdatedAt} - estates: ${estatesLastUpdatedAt} - rentals: ${rentalListings} - saved: ${updatedAt}`
componentLogger.info(
`Last updates | tiles: ${tilesLastUpdatedAt} - estates: ${estatesLastUpdatedAt} - rentals: ${rentalListingsUpdatedAt} - saved: ${updatedAt}`
)

const result: Result = {
Expand Down Expand Up @@ -522,8 +540,11 @@ export async function createApiComponent(components: {
const owner = (estate && estate.nft.owner) || parcelOwner
const activeOrder = (estate && estate.nft.activeOrder) || parcelActiveOrder
const updatedAt = Math.max(
estate ? parseInt(estate.nft.updatedAt, 10) : 0,
parseInt(parcelUpdatedAt, 10)
fromSecondsToMilliseconds(
estate ? parseInt(estate.nft.updatedAt, 10) : 0
),
fromSecondsToMilliseconds(parseInt(parcelUpdatedAt, 10)),
rentalListing?.updatedAt || 0
)

// special tiles are plazas, districts and roads
Expand Down
2 changes: 1 addition & 1 deletion src/modules/map/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function createMapComponent(components: {
let estates = future<Record<string, NFT>>()
let tokens = future<Record<string, NFT>>()
let ready = false
let lastUpdatedAt = 0
let lastUpdatedAt = 0 // in ms

// sort
const sortByCoords = (a: Tile, b: Tile) =>
Expand Down
2 changes: 1 addition & 1 deletion src/modules/map/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export type Tile = {
left: boolean
/** True if it has a tile on its top left. */
topLeft: boolean
/** UTC timestamp in seconds of the last time the tile was updated. */
/** UTC timestamp in miliseconds of the last time the tile was updated. */
updatedAt: number
/** The name of the tile, taken either from the estate or from the parcel it belongs to. */
name?: string
Expand Down
1 change: 1 addition & 0 deletions tests/adapters/legacy-tiles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('when converting tiles into a legacy tiles', () => {
{ minDays: 1, maxDays: 1, pricePerDay: '10000' },
{ minDays: 2, maxDays: 2, pricePerDay: '20000' },
],
updatedAt: Date.now(),
}
})

Expand Down
1 change: 1 addition & 0 deletions tests/adapters/rentals.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe('when converting a rental listing to a tile rental listing', () => {
expect(convertRentalListingToTileRentalListing(rentalListing)).toEqual({
expiration: rentalListing.expiration,
periods: rentalListing.periods,
updatedAt: rentalListing.updatedAt
})
})
})
Loading

0 comments on commit f9e0bc7

Please sign in to comment.