Skip to content

Тестовое задание компании "ТриниДата"

Notifications You must be signed in to change notification settings

insomnia-dreams-official/test_nodejs_trinidata

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Тестовое задание для компании "Тринидата"

Есть высоконагруженный веб-сервис, который должен возвращать ветки деревьев, доставаемых из медленной БД. Для упрощения тестовой задачи будем считать, что мы можем прочитать возвращаемые данные из CSV-файлов с именами tree1.csv, tree2.csv, tree3.csv. В этих файлах содержится структура трех разных деревьев. Каждый файл содержит столбцы id, name, parent, где parent – это id родителя элемента.

Запрос на ветвь имеет вид:

{
	tree: название файла с деревом,
	id: id элемента, с которого строится ветвь
}

Требуется, чтобы сервис порождал заданное количество воркеров wMax для обработки входящих HTTP-запросов, при первом обращении к сервису к какому-либо дереву:

  1. Проверял, есть ли это дерево в кэше в памяти. Если есть, и дата модификации файла данного дерева не изменилась — отдавал ветку в виде многоуровнего JSON’а:
{
    id: ...,
    name: ...,
    children: [
        {
            id: ...,
            name: ...,
            children: null
        },
        ...
    ]
}
  1. Если дата модификации дерева изменилась, либо кэша нет, то порождал воркер на создание данного кэша и отдавал ветку, вручную собрав ее из файла (со структурой как в п.1) и не дожидаясь окончания воркера перестройки кэша.

Нужно учесть, что запросов может быть до 100 и более в секунду.


Ответы на вопросы в файле questions.doc

  1. Есть высоконагруженный проект, один из его REST-интерфейсов принимает на вход структуру вида:
[
{ name: "...", type: "..." },
...
]

Элементов в данной структуре может быть от 1 до 1000. Требуется дополнить каждый элемент этой структуры свойством value, равным порядковому номеру элемента. Как бы вы это сделали?

Использовал бы метод массивов:

array.map((item, idx) => Object.assign(item, {value: idx}))
  1. Есть массив с идентификаторами элементов вида:
[
id1,
id2,
id3,
…
]

Необходимо для каждого идентификатора получить соответствующую строку таблицы table из БД Postgres (таблица имеет два столбца – id и prop), взять оттуда значение столбца prop и построить структуру вида:

[
	id1: prop1,
	id2: prop2,
	id3: prop3,
	...
]

Как бы вы реализовали такую задачу?

Поскольку мы одбираемся по where in (id1….idn), в возвращаемых строках будут фигурировать оба, интересующие нас поля (id, prop)

Думаю, что вы ошиблись со скобками, и мы говорим про объект, а не массив.

Object.fromEntries(rows.map(({id, prop}) => [id, prop]))
  1. Что предпочтительней использовать – цепочку промисов или async/await? Почему?

Если промисы не зависят друг от друга, я бы использовал Promise.all(). Если промисы должны выполняться последовательно, я бы использовал async/await для повышения читаемости кода.

  1. Равноценна ли запись f1(...).catch(...) и await f2(...).catch(...), если f1 и f2:
f1 = function(...) {
return new Promise(
( res, rej ) => {
…
}
	);
}

async f2(...) {
	...
}

Запись не равноценна, так как в первом случае мы не ждем промис, а во втором ждем. Но я думаю, что вы хотели спросить не это. А есть ли разница между функцией объявленной через async и функцией, которая возвращает промис.

Вопрос хитрый, полагаю навеянный данной статьей https://habr.com/ru/post/475260/

Сначала поглядел на статью и написал, что да. Доверяй, но проверяй. Запустил примеры в редакторе и перехватил обе ошибки. Ответ – нет. Либо, я не понял вопрос.

function fn(obj) {
  const someProp = obj.someProp
  return new Promise((_, reject) => {
    reject(someProp)
  })
}

async function asyncFn(obj) {
  const someProp = obj.someProp
  return Promise.reject(someProp)
}

(async ()=>{
  const o = {}
  await asyncFn(o).catch(err => console.error('Catched')) // => 'Catched'
  await fn(o).catch(err => console.error('Catched')) // => 'Catched'
})()
  1. Как лучше перехватить любую ошибку в цепочке промисов, при async/await? Почему?

Раз мы не обрабатываем их по отдельности, значит в них есть что-то общее и мы можем просто обернуть асинхронные вызовы в try/catch и обработать все в единственном catch.

Так как если мы не обрабатываем ошибку с async то ошибка просто вываливается в текущем контесте.

  1. Следует ли ставить ; в конце строк JS, если ее можно опустить?

Вообще компилятор сам расставляет их, но можно подорваться на этом если использовать IIFE.

const a = 'ставь точки с запятыми во имя добра'
(() => {
  console.log('точечный бог покарает тебя')
})()

В вышеописанном примере будет ошибка.

  1. Как бы вы реализовали функцию, в которую в качестве параметра передается массив URL. Функция должна получить данные с этих URL и вернуть в виде структуры:
{
url: данные,
…
}
aasync function getData(urls) {
   const promises = []
   urls.forEach(url => {
     promises.push(
       // привел пример со сторонней библиотекой, потому что нативные методы не так наглядны
       axios.get(url)
         .then(r => r)
         .catch(e => e)
     )
   })
   const data = await Promise.all(promises)
   // В зависимости от http ответов на ошибки, и того как мы хотим их отобразить в результирующем объекте
   // можно было бы дописать что-то еще
   return Object.fromEntries(
     urls.map(
       (url, idx) => [url, data[idx].status === 200 ? data[idx] : 'данные не были получены']
     )
   )
 }

About

Тестовое задание компании "ТриниДата"

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published