first successful key lookup problem

This commit is contained in:
blindlobstar 2025-04-03 20:25:19 +02:00
parent 50fd93c5a0
commit 0d33364a90
4 changed files with 90 additions and 0 deletions

View File

@ -0,0 +1,14 @@
# First Successful Key Lookup
You are given a function `get(ctx, address, key)`, which retrieves a value for a given key from a remote address. However, you don't know which address has the value, and network calls can fail.
Your task is to implement the Get function that:
* Calls get for each address in parallel.
* Returns the first successful response.
* If all requests fail, returns an error.
## Tags
`Concurrency`
## Source
- [Mock-собеседование по Go от Team Lead из Яндекса](https://www.youtube.com/watch?v=x689QxR3AIc) by **it-interview**

View File

@ -0,0 +1,52 @@
package solution
import (
"context"
"errors"
"time"
)
var ErrNotFound = errors.New("key not found")
func get(ctx context.Context, address string, key string) (string, error) {
return "", nil
}
func Get(ctx context.Context, addresses []string, key string) (string, error) {
// Creating context with timeout, so we can cancel it when receive first response (or timeout)
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
// Channels MUST be buffered, in other case there is a goroutine leakage
resCh, errCh := make(chan string, len(addresses)), make(chan error, len(addresses))
for _, address := range addresses {
go func() {
if val, err := get(ctx, address, key); err != nil {
errCh <- err
} else {
// There is a potential goroutine leak, if channel was unbuffered.
// If the result is not first, we WILL NOT read this channel
// and this goroutine will stuck forever
resCh <- val
}
}()
}
var errCount int
for {
select {
case err := <-errCh:
// If error count is equal to addresses count
// it means that no goroutine left and we can return an error
errCount++
if errCount == len(addresses) {
return "", err
}
case val := <-resCh:
return val, nil
case <-ctx.Done():
return "", context.Canceled
}
}
}

View File

@ -0,0 +1,19 @@
package main
import (
"context"
"errors"
)
var ErrNotFound = errors.New("key not found")
func get(ctx context.Context, address string, key string) (string, error) {
// Already implemented
return "", nil
}
// Call `get` function for each received address in parallel
// Return first response or an error if all requests fail
func Get(ctx context.Context, adresses []string, key string) (string, error) {
return "", nil
}

View File

@ -7,6 +7,11 @@ for technical interviews. These problems focus on real-world scenarios, includin
Here is a list of the problems available in the repository. Problems are organized by their respective tags:
### Concurrency
* [First Successful Key Lookup](01-first-successful-key-lookup/)
## Contributing
We welcome contributions from anyone looking to add more problems, improve solutions, or provide better documentation. Please refer to