Implement Relocation Service in Go
You are tasked with building a foundational component for a distributed system: a relocation service. This service will be responsible for managing the movement of data or resources between different locations or nodes. A robust relocation mechanism is crucial for load balancing, fault tolerance, and efficient resource utilization in complex systems.
Problem Description
Implement a RelocationService in Go that can handle the transfer of an item from a source location to a destination location. The service should simulate the process of moving an item, ensuring that it's removed from the source and successfully added to the destination.
Key Requirements:
RelocationServiceStructure: Define a struct namedRelocationServiceto encapsulate the state and operations.NewRelocationService()Constructor: Implement a constructor function that initializes and returns a newRelocationService.AddLocation(locationID string): A method to register a new location with the service. Each location will store items.AddItem(locationID string, itemID string): A method to add an item to a specific location.RemoveItem(locationID string, itemID string): A method to remove an item from a specific location. This should return an error if the item is not found at that location.RelocateItem(sourceLocationID string, destLocationID string, itemID string): The core method that performs the relocation. This method should:- Validate that both source and destination locations exist.
- Attempt to remove the item from the source location.
- If successful, add the item to the destination location.
- If the item cannot be removed from the source (e.g., not found), it should return an appropriate error and the item should not be added to the destination.
- If the item is successfully relocated, return
nilerror.
- Error Handling: The service must gracefully handle errors such as non-existent locations or items.
Expected Behavior:
- When
RelocateItemis called with valid source, destination, and item IDs, the item should be successfully moved. - If the item does not exist at the source, an error should be returned, and the item should remain at the source (or not be added to the destination).
- If either the source or destination location does not exist, an error should be returned.
Edge Cases to Consider:
- Relocating an item to its own location (should be a no-op or handled gracefully).
- Attempting to relocate an item that does not exist.
- Attempting to relocate from/to non-existent locations.
- Concurrent access to locations (though this problem focuses on the core logic, assume single-threaded access for now unless specified otherwise).
Examples
Example 1:
Input:
locations = ["A", "B"]
items_at_A = ["item1", "item2"]
items_at_B = []
// Initialize service and add locations
service := NewRelocationService()
service.AddLocation("A")
service.AddLocation("B")
// Add initial items
service.AddItem("A", "item1")
service.AddItem("A", "item2")
// Relocate "item1" from "A" to "B"
err := service.RelocateItem("A", "B", "item1")
Output:
err == nil
Items at "A": ["item2"]
Items at "B": ["item1"]
Explanation: The service successfully moved "item1" from location "A" to location "B".
Example 2:
Input:
locations = ["X", "Y"]
items_at_X = ["widget"]
items_at_Y = []
// Initialize service and add locations
service := NewRelocationService()
service.AddLocation("X")
service.AddLocation("Y")
// Add initial items
service.AddItem("X", "widget")
// Attempt to relocate "gadget" (which doesn't exist) from "X" to "Y"
err := service.RelocateItem("X", "Y", "gadget")
Output:
err: "item 'gadget' not found at location 'X'" (or similar)
Items at "X": ["widget"]
Items at "Y": []
Explanation: The relocation failed because "gadget" was not found at the source location "X". The state of locations remains unchanged.
Example 3:
Input:
locations = ["alpha"]
items_at_alpha = ["data1"]
// Initialize service and add locations
service := NewRelocationService()
service.AddLocation("alpha")
// Add initial items
service.AddItem("alpha", "data1")
// Attempt to relocate "data1" from "alpha" to a non-existent location "beta"
err := service.RelocateItem("alpha", "beta", "data1")
Output:
err: "destination location 'beta' does not exist" (or similar)
Items at "alpha": ["data1"]
Explanation: The relocation failed because the destination location "beta" was not registered with the service.
Constraints
- Location IDs and Item IDs are strings.
- Location IDs must be unique.
- A location can store multiple items, but each item ID within a single location must be unique.
- The underlying storage for locations and items can be implemented using Go's built-in map types.
- The implementation should be thread-safe if concurrent access is considered, but for this basic challenge, focus on correct logic under single-threaded access. (Assume single-threaded for the core problem unless you want to add concurrency later).
Notes
- Consider how you will store the items within each location. A map where keys are item IDs and values are empty structs or booleans could be efficient.
- When implementing
RelocateItem, ensure atomicity of the operation: either the item is fully moved, or it's not moved at all. - Think about how to represent the locations themselves and the items they contain. A map where keys are
locationIDand values are the data structures holdingitemIDs would be a good start.