✨Dvurechensky✨
AdPlatformService is a high-performance in-memory web service for storing and searching advertising platforms by location.
📄 Task documentation is also available in PDF: TASK.NET.pdf
📄 Test input file: test_input_data.txt
- ⭐ Table of Contents
dotnet run --project AdRegionService👉 API: http://localhost:5411 👉 Swagger UI: http://localhost:5411/swagger
👉 API: http://localhost:5411 👉 Swagger UI: http://localhost:5411/swagger
Show API details
POST /api/load
Content-Type: multipart/form-data
file=@platforms.txt{
"message": "Data loaded",
"loaded": 123,
"skipped": 5
}GET /api/search?location=/ru/svrd[
{ "name": "Cool Ads", "locations": ["/ru/svrd"] },
{
"name": "Revdinsky Worker",
"locations": ["/ru/svrd/revda", "/ru/svrd/pervik"]
}
]-
📂 Load advertising platforms from file (
Stream) -
⚡ In-memory storage using immutable collections
-
📊 Load statistics (
loaded / skipped) -
🔍 Hierarchical location search:
/loc1matches all platforms under this level/loc1/loc2also includes/loc1
-
🛡 Error handling:
OperationCanceledExceptionOutOfMemoryException- General errors are logged, state remains consistent
Method:
LoadFromStreamAsync(Stream stream, CancellationToken cancellationToken = default)-
✅ Accepts
Stream(supports files and network sources) -
✅ Ignores invalid lines:
- empty lines
- missing
: - empty platform name
- no valid locations
-
✅ Location indexing Stored in:
ImmutableDictionary<string, ImmutableHashSet<AdPlatform>>- ✅ Load statistics (
LoadStats) - ✅ Progress logging every 100,000 lines
- ✅ Error resilience:
- keeps previous state on failure
- logs all exceptions
Yandex.Direct:/ru
Revdinsky Worker:/ru/svrd/revda,/ru/svrd/pervik
Ural Moscow Newspaper:/ru/msk,/ru/permobl,/ru/chelobl
Cool Ads:/ru/svrd- ✅ Method:
Search(string location) - ✅ Uses indexed lookup (no full scan)
- ✅ Supports hierarchical matching
- ✅ Returns
IEnumerable<AdPlatform> - ✅ Thread-safe
- ⚡ Efficient up to:
- 1–2 million entries
- 100–500 MB data
For >10M entries → consider external storage (PostgreSQL, full-text search, etc.)
ImmutableArrayImmutableDictionaryImmutableHashSet
➡️ Thread-safe without locks
Search /a/b/c → checks:
/a/a/b/a/b/c
ILogger- Progress logging
- Error tracking
- Ready for integration (Seq, Kibana, etc.)
- Invalid data is skipped
- State is preserved on failure
- Search never throws exceptions
- Uses
HashSet<AdPlatform> - Removes duplicates automatically
- Returns lightweight enumerable
- ⚡ High performance (1–2M entries)
- 🛡 Robust error handling
- 🔗 Easy REST integration
- 🧵 Thread-safe architecture
-
xUnit tests
-
Covers:
- loading
- search
- edge cases
-
Run:
dotnet test- Docker build on push to
main - Publish to GitHub Container Registry
dotnet build+dotnet test
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key.pem -out cert.pem -subj "/CN=localhost"docker-compose up --builddocker pull ghcr.io/dvurechensky/net_junior_ads_test_task/adservice:latestdocker run -it --rm -p 5411:5411 ghcr.io/dvurechensky/net_junior_ads_test_task/adservice:latest✨Dvurechensky✨
