Concurrent Crawling

Предадени решения

Краен срок:
11.12.2014 17:00
Точки:
10

Срокът за предаване на решения е отминал


Нипишете функция SeekAndDestroy, която приема като аргументи: callback func(string) bool, chunkedUrlsToCheck <-chan []string, workersCount int и връща string, error.

Функцията трябва паралелно (с до workersCount горутини) да обходи подадените ѝ чрез urls адреси и да върне като резултат първия URL адрес, чието съдържание, подадено на callback, връща true.

Трябва да бъдат спазени следните условуя:

  • Ако подадените параметри са грешни (пр. workersCount е неположително число или каналът не е инициализиран), функцията трябва веднага да върне грешка.
  • Каналът urls не трябва да бъде блокиран. Дори и по него да се получат повече от workersCount адреси, те трябва да бъдат буферирани от функцията, така че каналът да остане отворен за писане.
  • Функцията трябва да се опитва, ако има достатъчно "работа", да поддържа броят "работници" да бъде workersCount. Възможно е обаче по канала urls да се подадат по-малко на брой URL адреси от лимитът паралелни работници workersCount - тогава няма нужда да се създават idle workers.
  • След като callback функцията върне позитивен резултат за някой от подадените по urls адреси, функцията трябва да приключи веднага и да върне съответният адрес. Всички останали непроверени адреси трябва да се игнорират.
  • Всеки HTTP request до подадените urls трябва да има timeout от 3 секунди.
  • Ако някой HTTP request надвиши timeout времето или има грешка при зареждането (невалиден домейн, HTTP status != 2xx, etc.), съответният URL се счита за невалиден резултат.
  • Ако каналът urls бъде затворен или до 15 секунди никой от подадените URL адреси не отговаря на изискванията, функцията трябва да върне грешка.

Бонус точки ще бъдат давани на решенията, които не създават idle работници и чиито работници биват "убивани" максимално бързо след намерен резултат или глобален timeout (т.е. техните http заявки не се изчакват да приключат).

Пример:

urls := make(chan []string)
go func() {
    urls <- []string{"http://www.abv.bg", "http://www.dir.bg"}
    time.Sleep(5 * time.Second)
    urls <- []string{"http://www.google.com", "invalid.url....", "http://en.wikipedia.org/wiki/Lorem_ipsum"}
}()

callback := func(contents string) bool {
    return strings.Contains(contents, "Lorem ipsum")
}

result, _ := SeekAndDestroy(callback, urls, 3)

fmt.Println(result)
// Output: http://en.wikipedia.org/wiki/Lorem_ipsum

Disclaimer: ако някой промени горните страници или имате мрежови проблеми, резултатът от горния код вече може да се различава :)