Go version used: 1.13.4
This is a test solution that caches data from http-data source to redis. I tried to consider most corner cases in this solution and created additional interfaces/functions to create a thin wrap over existing and standard implementations for me to able to test business logic.
contact_id that is used as a key for values in Redis.GET response. Task didn't mention whether it should be
done or not, so I decided not to cache them. That's why responses might differ - cache-miss GET requests will have all
headers, provided by external API, cache-hit GET requests will have only Content-Type header, besides default ones.
If it is required to cache headers - can be implemented rather easily, as there are corresponding abstractions in the code.interfaces to make abstraction over something and sometimes I define a type to func. I use interfaces when methods are related to one another and use common data/objects, and I use functions, when there will be an interface/object with a single method.This project contains packages that can be treated as utility packages:
and solution package:
http://<binded-host:binded-port>/v1/contact/<contact-id> - gets information about contacthttp://<binded-host:binded-port>/v1/contact - creates/updates contact (depends on behaviour of external API)http://<binded-host:binded-port>/v1/contact - updates contact (depends on behaviour of external API)http://<binded-host:binded-port>/ping - health check endpointPackage logic/sources is covered with tests, as it contains a core business logic.
Package logic/handles contains unit-tests only for a common part of handlers.
logic package
and to cover code with tests in utils and logs packages.OPTIONS-method for existing handlers.
This can be done either using a proxy/load-balancer before hitting this service or (worst case scenario) via using
ambassador template with nginx inside container, that will run in the same network-namespace as a container with this service.Modify file ./config.json:
api_url - URL to external API (https://my.test.com/v1/api/entity).cache_ttl_seconds - for how long we should keep cached value (in seconds).redis - block of redis configuration. Supports only address (host:port) and DB. Redis password is provided via
command line.bind - which IP and port should be used by the service.app_timeout_seconds - when SIGINT or SIGTERM is caught, application is informed and should stop withing this
time interval, otherwise it will be killed.go build && ./test -config=./config.json -redispwd='securepassword'
We will pull redis container and run it without any authentication.
docker run -d --name redistest redis:latestdocker build . -t cachetestdocker run -d --network=container:redistest --name cachetest cachetest -redispwd=""Those commands will spin a redis container without authentication, will create a container with the service, building it from source code and will spin that container with the service inside, providing same network namespace as redis container will have.
To remove everything execute following commands:
docker rm -f cachetest && docker rmi cachetestdocker rm -f redistest && docker rmi redis:latestIf you have redis wuth authentication running in another container or on host, you can execute docker run for cachetest,
providing redis password in -redispwd parameter:
docker run -d --name cachetest cachetest -redispwd="securepassword"
Also you can use precompiled container (this one), substituting config.json file:
docker run -d -v $(pwd)/build/config.json:/go/src/app/config.json --network=container:redistest --name cachetest coldze/svctest -redispwd=""
Container is build automatically via integration with hub.docker.com.
Those commands can be executed both from host and from inside container, but from root of repo (json files are required for post/put methods):
curl -H "autopilotapikey: <your-api-key>" http://<service-container-ip>/v1/contact/<contact-id>curl -X "POST" -H "autopilotapikey: <your-api-key>" -H "Content-Type: application/json" -d @test_data/post.json http://<service-container-ip>/v1/contactcurl -X "POST" -H "autopilotapikey: <your-api-key>" -H "Content-Type: application/json" -d @test_data/put.json http://<service-container-ip>/v1/contactFrom root of repo run following command:
go test ./...
With coverage:
go test -cover -coverprofile=coverage.out ./... && go tool cover -html=coverage.out
Content type
-
Digest
Size
301.1 MB
Last updated
almost 7 years ago
docker pull coldze/svctest