Feature Implementation Plan: Improve Shipping Country Resolution¶
📋 Todo Checklist¶
- [ ] Create
RoasterShippingentity - [ ] Add relationship to
Roasterentity - [ ] Create data migration command
- [ ] Update
RoasterRepository - [ ] Update
EntityToDtoMapper - [ ] Remove old properties from
RoasterCrawlConfig - [ ] Final Review and Testing
🔍 Analysis & Investigation¶
Codebase Structure¶
The relevant files are:
- src/Entity/Roaster.php: The main entity for roasters.
- src/Entity/RoasterCrawlConfig.php: Currently holds the shipping information.
- src/Repository/RoasterRepository.php: Contains the inefficient query that fetches roasters and their shipping information.
- src/Service/Api/Mapper/EntityToDtoMapper.php: Contains the logic for resolving and mapping the shipping information.
Current Architecture¶
The current architecture has a tight coupling between the RoasterCrawlConfig and the shipping information for a Roaster. This leads to a complex and inefficient query in the RoasterRepository that joins multiple tables and fetches a large amount of data. The EntityToDtoMapper then has to process this data to resolve the final list of shipping countries. This is a classic N+1 problem manifesting in a single, complex query.
Dependencies & Integration Points¶
The main dependencies are Doctrine ORM and the Symfony Serializer component. The integration points are the API endpoints that return roaster information.
Considerations & Challenges¶
The main challenge will be migrating the existing data from the RoasterCrawlConfig entity to the new RoasterShipping entity without any downtime. A command-line tool will be created to handle this migration.
📝 Implementation Plan¶
Prerequisites¶
- Ensure that the local development environment is set up and the database is running.
Step-by-Step Implementation¶
- Step 1: Create the
RoasterShippingentity - Files to modify:
src/Entity/RoasterShipping.php(new file) -
Changes needed:
- Create a new entity
RoasterShippingwith the following properties: id(UUID)roaster(ManyToOne relationship toRoaster)type(string enum: 'region' or 'country_list')name(string)countries(ManyToMany relationship toCountry)exceptionCountries(ManyToMany relationship toCountry)
- Create a new entity
-
Step 2: Add the relationship to the
Roasterentity - Files to modify:
src/Entity/Roaster.php -
Changes needed:
- Add a
OneToManyrelationship fromRoastertoRoasterShipping.
- Add a
-
Step 3: Create a data migration command
- Files to modify:
src/Command/MigrateShippingDataCommand.php(new file) -
Changes needed:
- Create a new Symfony command that:
- Fetches all
RoasterCrawlConfigentities. - For each
crawlConfig, creates a newRoasterShippingentity. - Copies the
shippingRegion,shipsTo, andexceptionCountriesdata to the newRoasterShippingentity. - Persists the new
RoasterShippingentities to the database.
-
Step 4: Update
RoasterRepository - Files to modify:
src/Repository/RoasterRepository.php -
Changes needed:
- Simplify the
executeRoasterQueryandfindDtoByIdmethods to remove the joins related toRoasterCrawlConfig. - Instead, join the new
RoasterShippingentity. ```php $qb = $this->createQueryBuilder('r') ->leftJoin('r.country', 'c') ->leftJoin('r.shippingInfo', 'rs') -leftJoin('rs.countries', 'rsc') ->leftJoin('rs.exceptionCountries', 'rsec') ->addSelect('c', 'rs', 'rsc', 'rsec') ->orderBy('r.name', 'ASC'); ```
- Simplify the
-
Step 5: Update
EntityToDtoMapper - Files to modify:
src/Service/Api/Mapper/EntityToDtoMapper.php -
Changes needed:
- Update the
mapRoasterShippingToDtomethod to use the newRoasterShippingentity. - The logic will be similar, but it will iterate over the
shippingInfocollection of theRoasterentity instead of thecrawlConfigs.
- Update the
-
Step 6: Remove old properties from
RoasterCrawlConfig - Files to modify:
src/Entity/RoasterCrawlConfig.php - Changes needed:
- After the data migration is complete and the code is updated, remove the
shipsTo,shippingRegion, andexceptionCountriesproperties from theRoasterCrawlConfigentity. - Create a new database migration to remove the corresponding columns and tables.
- After the data migration is complete and the code is updated, remove the
Testing Strategy¶
- Run the existing test suite to ensure that no functionality is broken.
- Create a new integration test that verifies that the roaster API endpoint returns the correct shipping information.
- Manually test the API endpoint to confirm that the performance has improved.
🎯 Success Criteria¶
- The API endpoints that return roaster information are significantly faster and no longer time out.
- The shipping information for roasters is correctly resolved and returned by the API.
- The codebase is simplified and easier to maintain.