Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maintain created time when reingesting an item #196

Merged
merged 6 commits into from
Feb 25, 2022
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
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"rules": {
"dot-notation": "off",
"implicit-arrow-linebreak": "off",
"no-restricted-syntax": [
"off",
"BinaryExpression[operator='of']"
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"editor.formatOnSave": true,
"editor.rulers": [
80
90
],
"eslint.format.enable": true,
"eslint.packageManager": "npm",
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Open-ended datetime intervals using either empty string or '..' now work
- Correct content types are now returned
- Searching for a nonexistent collection returns empty results
- Re-ingesting an Item maintains the existing value of properties.created and sets properties.updated to now

### Changed

Expand Down
45 changes: 38 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"@tsconfig/node14": "^1.0.1",
"@types/compression": "^1.7.2",
"@types/js-yaml": "^3.0.0",
"@types/luxon": "^2.0.9",
"@types/memorystream": "^0.3.0",
"@types/node": "^14.18.12",
"@types/sinon": "^10.0.11",
Expand All @@ -71,6 +72,7 @@
"eslint-plugin-jsdoc": "^3.5.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.7.0",
"luxon": "^2.3.1",
"nock": "^12.0.3",
"nodemon": "^2.0.15",
"prettier": "^2.0.5",
Expand Down
18 changes: 18 additions & 0 deletions src/lib/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,27 @@ async function search(parameters, page = 1, limit = 10) {
return response
}

const getItem = async (collectionId, itemId) => {
const searchResponse = await search({
collections: [collectionId],
id: itemId
})

return searchResponse.results[0]
}

const getItemCreated = async (collectionId, itemId) => {
const item = await getItem(collectionId, itemId)
if (!item) return undefined
if (!item.properties) return undefined
return item.properties.created
}

module.exports = {
getCollection,
getCollections,
getItem,
getItemCreated,
isIndexNotFoundError,
search,
editPartialItem,
Expand Down
12 changes: 9 additions & 3 deletions src/lib/esStream.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const _stream = require('stream')
const through2 = require('through2')
const logger = console //require('./logger')
const esClient = require('./esClient')
const { getItemCreated } = require('./es')

const COLLECTIONS_INDEX = process.env.COLLECTIONS_INDEX || 'collections'

Expand Down Expand Up @@ -97,7 +98,7 @@ async function stream() {
try {
const client = await esClient.client()

const toEs = through2.obj({ objectMode: true }, (data, encoding, next) => {
const toEs = through2.obj({ objectMode: true }, async (data, encoding, next) => {
let index = ''
logger.debug(`Data: ${JSON.stringify(data)}`)
if (data && data.hasOwnProperty('extent')) {
Expand All @@ -115,8 +116,12 @@ async function stream() {
const esDataObject = { ...data, links }

if (data.hasOwnProperty('properties')) {
esDataObject.properties.created = new Date().toISOString()
esDataObject.properties.updated = new Date().toISOString()
const now = (new Date()).toISOString()

const created = (await getItemCreated(data.collection, data.id)) || now

esDataObject.properties.created = created
esDataObject.properties.updated = now
}

// create ES record
Expand All @@ -130,6 +135,7 @@ async function stream() {
doc_as_upsert: true
}
}

next(null, record)
})

Expand Down
22 changes: 21 additions & 1 deletion tests/helpers/api-client.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const got = require('got')
// @ts-check

const { default: got } = require('got')

const apiClient = got.extend({
prefixUrl: 'http://localhost:3000/',
Expand All @@ -12,10 +14,28 @@ const apiClient = got.extend({
const getCollectionIds = async () => {
const response = await apiClient.get('collections')

// @ts-expect-error We need to be validating this response
return response.collections.map((c) => c.id)
}

/**
* @param {string} collectionId
* @returns {Promise<unknown>}
*/
const getCollection = async (collectionId) =>
apiClient.get(`collections/${collectionId}`)

/**
* @param {string} collectionId
* @param {string} itemId
* @returns {Promise<unknown>}
*/
const getItem = async (collectionId, itemId) =>
apiClient.get(`collections/${collectionId}/items/${itemId}`)

module.exports = {
apiClient,
getCollection,
getItem,
getCollectionIds
}
3 changes: 1 addition & 2 deletions tests/system/test-api-get-collection.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: anyTest } = require('ava')
const { apiClient } = require('../helpers/api-client')
const { deleteAllIndices } = require('../helpers/es')
Expand Down Expand Up @@ -49,6 +47,7 @@ test('GET /collections/:collectionId returns a collection', async (t) => {

const response = await apiClient.get(`collections/${collectionId}`)

// @ts-expect-error We need to validate these responses
t.is(response.id, collectionId)
})

Expand Down
2 changes: 0 additions & 2 deletions tests/system/test-api-get-collections.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: anyTest } = require('ava')
const { apiClient } = require('../helpers/api-client')
const { ingestItem } = require('../helpers/ingest')
Expand Down
2 changes: 0 additions & 2 deletions tests/system/test-api-get-conformance.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: test } = require('ava')
const { apiClient } = require('../helpers/api-client')

Expand Down
2 changes: 0 additions & 2 deletions tests/system/test-api-get-item.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: anyTest } = require('ava')
const { apiClient } = require('../helpers/api-client')
const { deleteAllIndices } = require('../helpers/es')
Expand Down
2 changes: 0 additions & 2 deletions tests/system/test-api-get-items.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: anyTest } = require('ava')
const { apiClient } = require('../helpers/api-client')
const { deleteAllIndices } = require('../helpers/es')
Expand Down
2 changes: 0 additions & 2 deletions tests/system/test-api-get-root.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: anyTest } = require('ava')
const { apiClient } = require('../helpers/api-client')
const { deleteAllIndices } = require('../helpers/es')
Expand Down
2 changes: 0 additions & 2 deletions tests/system/test-api-get-search.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: anyTest } = require('ava')
const { apiClient } = require('../helpers/api-client')
const { deleteAllIndices } = require('../helpers/es')
Expand Down
2 changes: 0 additions & 2 deletions tests/system/test-api-post-search.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check

const { default: anyTest } = require('ava')
const { promisify } = require('util')
const fs = require('fs')
Expand Down
56 changes: 55 additions & 1 deletion tests/system/test-ingest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

const { default: anyTest } = require('ava')
const nock = require('nock')
const { getCollectionIds } = require('../helpers/api-client')
const { DateTime } = require('luxon')
const { getCollectionIds, getItem } = require('../helpers/api-client')
const { handler } = require('../../src/lambdas/ingest')
const { loadFixture, randomId } = require('../helpers/utils')
const { nullLoggerContext } = require('../helpers/context')
const { refreshIndices, deleteAllIndices } = require('../helpers/es')
const { sqsTriggerLambda, purgeQueue } = require('../helpers/sqs')
const awsClients = require('../../src/lib/aws-clients')
const systemTests = require('../helpers/system-tests')
const { ingestItem } = require('../helpers/ingest')

/**
* @template T
Expand Down Expand Up @@ -135,3 +137,55 @@ test('The ingest lambda supports ingesting a collection sourced from http', asyn

t.true(collectionIds.includes(collection.id))
})

test('Reingesting an item maintains the `created` value and updates `updated`', async (t) => {
const { ingestQueueUrl, ingestTopicArn } = t.context
if (ingestQueueUrl === undefined) throw new Error('ingestQueueUrl undefined')
if (ingestTopicArn === undefined) throw new Error('ingestTopicArn undefined')

const collection = await loadFixture(
'landsat-8-l1-collection.json',
{ id: randomId('collection') }
)

await ingestItem({
ingestTopicArn,
ingestQueueUrl,
item: collection
})

const item = await loadFixture(
'stac/LC80100102015082LGN00.json',
{
id: randomId('item'),
collection: collection.id
}
)

await ingestItem({
ingestQueueUrl,
ingestTopicArn,
item
})

const originalItem = await getItem(collection.id, item.id)
// @ts-expect-error Need to validate these responses
const originalCreated = DateTime.fromISO(originalItem.properties.created)
// @ts-expect-error Need to validate these responses
const originalUpdated = DateTime.fromISO(originalItem.properties.updated)

await ingestItem({
ingestQueueUrl,
ingestTopicArn,
item
})

const updatedItem = await getItem(collection.id, item.id)
// @ts-expect-error Need to validate these responses
const updatedCreated = DateTime.fromISO(updatedItem.properties.created)
// @ts-expect-error Need to validate these responses
const updatedUpdated = DateTime.fromISO(updatedItem.properties.updated)

t.is(updatedCreated.toISO(), originalCreated.toISO())
t.true(updatedUpdated.toISO() > originalUpdated.toISO())
})