Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Object Store Project

An HTTP service for storing, retrieving, and deleting objects organized by buckets.

Core Features

  • PUT / GET / DELETE at /objects/{bucket}/{objectID}
  • Per-bucket content deduplication via SHA-256 hashing
  • Concurrent-safe in-memory storage with RWMutex
  • Configurable port via --port flag
  • Graceful shutdown on SIGINT/SIGTERM

Requirements

  • Go 1.22+

Dependencies

  • net/http - HTTP server and routing
  • encoding/json - JSON responses
  • crypto/sha256 + encoding/hex - deduplication hashing
  • sync - RWMutex for safe concurrent access
  • flag or os.Getenv - configurable port
  • log/slog (Go 1.21+) - structured logging

Running the Service

make run               
go run main.go --port=8080

Running Tests

# Runs all tests with race detector
make test   

# Or directly with go in the root directory
go test ./... -race -v

# Test PUT/GET/DELETE

# In terminal 1:
go run main.go

# In terminal 2 run each curl command
curl -X PUT http://localhost:8080/objects/bucket1/obj1 -d "hello world" -v
curl -X GET http://localhost:8080/objects/bucket1/obj1 -v
curl -X GET http://localhost:8080/objects/bucket1/missing -v   # expect a 400 error
curl -X DELETE http://localhost:8080/objects/bucket1/obj1 -v
curl -X DELETE http://localhost:8080/objects/bucket1/missing -v  # expect a 400 error

API Reference

Method Endpoint Request Body Success Response Not Found
PUT /objects/{bucket}/{objectID} Raw text body 201 Created + {"id": "<objectID>"} N/A
GET /objects/{bucket}/{objectID} None 200 OK + object body 400 Bad Request
DELETE /objects/{bucket}/{objectID} None 200 OK 400 Bad Request

Design Notes

  • Deduplication: Objects are deduplicated per bucket using SHA-256 content hashing. Two objectIDs pointing to identical content share one stored copy. Content is garbage-collected when the last referencing objectID is deleted.

Spec Compliance Note - HTTP Status Code for Not Found

The provided API specification prescribes 400 for object-not-found responses on both GET and DELETE:

Response if object is not found: Status 400 Not Found

This deviates from standard HTTP semantics, where 404 Not Found is the correct status code for a resource that does not exist. 400 Bad Request conventionally indicates a malformed or invalid request from the client - not an absent resource.

This implementation follows the spec as written and returns 400.

In a production codebase - this would be raised as a design review item before implementation the distinction matters for API consumers, monitoring systems, and anyone writing client-side error handling logic that branches on status codes. A 400 response would typically prompt a client to fix its request; a 404 signals the resource simply doesn't exist yet and may be retried or handled differently.

AI Tool Usage

Go is not my primary production language Python is, having used it across Oracle, Twilio, and Cisco. I chose Go for this task deliberately to align with the team's primary language and to begin building production-level Go experience. I used GitHub Copilot to validate idiomatic Go patterns (error handling, RWMutex usage, stdlib HTTP routing) and cross-referenced the official Go documentation throughout. All core design decisions, the deduplication. model, two-level locking strategy, and DELETE garbage collection, were my own.

Tools used: Perplexity AI, GitHub Copilot (VSCode inline suggestions)

Where AI assisted:

  • Boilerplate generation: Copilot suggested initial struct field layouts for bucket and Store types. I reviewed and restructured the locking model, the suggestion used a single global mutex; I changed it to two-level locking (store-level for bucket map access, bucket-level for object map access) to reduce contention.

  • Test case scaffolding: Copilot generated the initial TestPutAndGet function signature and table. I added the deduplication tests and the cross-bucket isolation test myself, as these were not suggested and represent the core requirement.

  • Error handling patterns: Copilot suggested errors.Is() usage in handlers. I accepted this as it aligns with Go idioms and my own practice.

Perplexity AI:

  • Used for research and architectural guidance during the design phase, specifically to understand idiomatic Go project structure, two-level RWMutex locking patterns for concurrent map access, and SHA-256 based content deduplication approaches.
  • Used to clarify Go module path resolution and standard library HTTP routing conventions (Go 1.22+ net/http method-based routing).
  • All design decisions, the two-map deduplication model, DELETE garbage collection logic, and graceful shutdown implementation — were my own, informed by the research but not generated by it.

GitHub Copilot:

  • Provided inline suggestions for struct boilerplate and test scaffolding.
  • Accepted selectively - locking model and deduplication logic were restructured from suggestions based on my own design reasoning.
  • All suggestions validated by running go test ./... -race and manual code review.

Where I did not use AI:

  • The deduplication design (two-map approach: objectID -> hash, hash -> body) was my own design decision after reasoning through the GC implications of DELETE.
  • The graceful shutdown implementation was written from memory based on prior production experience.
  • All test assertions were written manually.

How I validated AI output:

  • Reviewed every Copilot suggestion before accepting, no blind tab-completions.
  • Ran go test ./... -race after each significant change to verify correctness and absence of data races.
  • Read the generated code against the spec line-by-line for the handler logic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages