From e92e08c2d20913171348a5ffac9826dcb6751af4 Mon Sep 17 00:00:00 2001 From: dushanlk Date: Thu, 2 Jan 2025 18:54:14 +0530 Subject: [PATCH] Added highlevel arch diagram of API/Updated readme --- docs/lucytech.jpg | Bin 0 -> 60543 bytes readme.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 docs/lucytech.jpg diff --git a/docs/lucytech.jpg b/docs/lucytech.jpg new file mode 100644 index 0000000000000000000000000000000000000000..74ce0de894a7b0838222681df53c993f649b9060 GIT binary patch literal 60543 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 Checking statuses of URLs found on the scrapped HTML content was identified as the most expensive operation as of now in this application. Though we use `go routines`, the response latency of URLs makes a huge impact on system performance and response time of this API. To tackle this issue, we decided not to process all found URLs at the first request. We trigger only 10 URLs to check the status, and keep the rest in memory with the support of pagination. So user can request as batches of 10 URLs per request on subsequent pagination requests. With this approach we were able scrape websites with huge amount of URLs (ie: yahoo.com) effortlessly and without breaking the system. + +#### Further improvements + +* We can replace the in-memory storage with a database. +* We can use a messaging technique to pass data changes in real-time to the UI. + ## How to run using Docker * Run `docker-compose up --build` @@ -8,6 +31,36 @@ * Run `go test -coverprofile=coverage.out ./...` * To check the test coverage run `go tool cover -func=coverage.out` +* Test coverage output: + +```bash +scraper/cmd/main.go:12: main 0.0% +scraper/handlers/scrape.go:19: ScrapeHandler 94.1% +scraper/handlers/scrape.go:51: PageHandler 85.7% +scraper/logger/logger.go:14: Debug 100.0% +scraper/logger/logger.go:18: Info 0.0% +scraper/logger/logger.go:22: Error 100.0% +scraper/services/htmlparser.go:13: FetchPageInfo 100.0% +scraper/services/htmlparser.go:24: ParseHTML 90.9% +scraper/services/htmlparser.go:64: traverse 80.0% +scraper/services/htmlparser.go:74: extractHref 75.0% +scraper/services/htmlparser.go:83: resolveURL 100.0% +scraper/services/htmlparser.go:89: isInternal 100.0% +scraper/services/htmlparser.go:96: containsPasswordInput 100.0% +scraper/services/htmlparser.go:112: extractTitle 100.0% +scraper/services/htmlparser.go:125: extractHtmlVersion 50.0% +scraper/services/urlstatus.go:21: CheckURLStatus 100.0% +scraper/storage/memory.go:15: StorePageInfo 100.0% +scraper/storage/memory.go:24: RetrievePageInfo 100.0% +scraper/storage/memory.go:32: generateID 100.0% +scraper/storage/memory.go:36: randomString 100.0% +scraper/utils/helpers.go:10: CalculateTotalPages 100.0% +scraper/utils/helpers.go:14: CalculatePageBounds 100.0% +scraper/utils/helpers.go:20: min 66.7% +scraper/utils/helpers.go:27: BuildPageResponse 50.0% +total: (statements) 86.6% + +``` ## API Documentation