S226 local dev fix#97
Conversation
S219 : prep next version
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
Once credits are available, reopen this pull request to trigger a review.
There was a problem hiding this comment.
Pull request overview
This PR aims to restore correct local-development behavior when using the Datastore emulator after a Google Cloud Java BOM update, by avoiding DatastoreOptions.toBuilder() (which can drop the emulator host) and instead rebuilding options via DatastoreOptions.newBuilder() while explicitly preserving host.
Changes:
- Replaced
DatastoreOptions.toBuilder()/getDefaultInstance().toBuilder()usage with explicitnewBuilder()copies that retainhost. - Removed a couple of “round-trip rebuilds” of
DatastoreOptionsand passed options/services through directly. - Bumped the fork version and documented the change (plus added internal agent docs).
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| java/src/main/java/com/google/appengine/tools/mapreduce/ShardedJobAbstractSettings.java | Rebuilds DatastoreOptions from default instance via newBuilder() while preserving host. |
| java/src/main/java/com/google/appengine/tools/mapreduce/MapReduceJob.java | Updates multiple stage-specific Datastore construction sites to avoid toBuilder() and preserve host. |
| java/src/main/java/com/google/appengine/tools/mapreduce/impl/util/RequestUtils.java | Rebuilds request-derived DatastoreOptions without toBuilder() to retain emulator host. |
| java/src/main/java/com/google/appengine/tools/mapreduce/impl/shardedjob/pipeline/FinalizeShardsInfos.java | Stops rebuilding options via toBuilder() and uses datastoreOptions.getService(). |
| java/src/main/java/com/google/appengine/tools/mapreduce/impl/shardedjob/pipeline/DeleteShardedJob.java | Stops passing a toBuilder().build() copy of DatastoreOptions. |
| java/pom.xml | Version bump to 0.3+worklytics.14. |
| java/changes.md | Adds changelog entry describing the toBuilder() emulator-host issue and affected files. |
| .agents/plans/FIX-DATASTORE-TOBUILDER.md | Internal plan documenting root cause and the intended replacement pattern. |
| .agents/CLAUDE.md | Internal repository guidance for Claude Code usage and project architecture/testing notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| DatastoreOptions defaultInstance = DatastoreOptions.getDefaultInstance(); | ||
| DatastoreOptions.Builder b = DatastoreOptions.newBuilder() | ||
| .setProjectId(defaultInstance.getProjectId()) | ||
| .setCredentials(defaultInstance.getCredentials()) | ||
| .setTransportOptions(defaultInstance.getTransportOptions()); | ||
| java.util.Optional.ofNullable(defaultInstance.getHost()).ifPresent(b::setHost); | ||
| java.util.Optional.ofNullable(settings.getNamespace()).ifPresent(b::setNamespace); | ||
| datastore = b.build().getService(); |
| DatastoreOptions defaultInstance = DatastoreOptions.getDefaultInstance(); | ||
| DatastoreOptions.Builder b = DatastoreOptions.newBuilder() | ||
| .setProjectId(defaultInstance.getProjectId()) | ||
| .setCredentials(defaultInstance.getCredentials()) | ||
| .setTransportOptions(defaultInstance.getTransportOptions()); | ||
| java.util.Optional.ofNullable(defaultInstance.getHost()).ifPresent(b::setHost); |
| DatastoreOptions defaultInstance = DatastoreOptions.getDefaultInstance(); | ||
| DatastoreOptions.Builder b = DatastoreOptions.newBuilder() | ||
| .setProjectId(defaultInstance.getProjectId()) | ||
| .setCredentials(defaultInstance.getCredentials()) | ||
| .setTransportOptions(defaultInstance.getTransportOptions()); | ||
| java.util.Optional.ofNullable(defaultInstance.getHost()).ifPresent(b::setHost); |
| protected Job<?> createShardsJob(int start, int end) { | ||
| return new DeleteShardsInfos(datastoreOptions.toBuilder().build(), getJobId(), start, end); | ||
| return new DeleteShardsInfos(datastoreOptions, getJobId(), start, end); | ||
| } |
| public Value<Void> run() { | ||
| Datastore datastore = datastoreOptions.toBuilder().build().getService(); | ||
| Datastore datastore = datastoreOptions.getService(); | ||
|
|
| (Google Cloud Java BOM ≥ 26.83.0). Replaced all `toBuilder()` / `getDefaultInstance().toBuilder()` | ||
| calls with explicit `DatastoreOptions.newBuilder()` copies that preserve the `host` field. |
| DatastoreOptions defaultInstance = DatastoreOptions.getDefaultInstance(); | ||
|
|
||
| DatastoreOptions.Builder builder = defaultInstance.toBuilder(); | ||
| DatastoreOptions.Builder builder = DatastoreOptions.newBuilder() | ||
| .setProjectId(defaultInstance.getProjectId()) | ||
| .setCredentials(defaultInstance.getCredentials()) | ||
| .setTransportOptions(defaultInstance.getTransportOptions()); | ||
| Optional.ofNullable(defaultInstance.getHost()).ifPresent(builder::setHost); |
| @Override | ||
| public Value<Void> run() { | ||
| Datastore datastore = datastoreOptions.toBuilder().build().getService(); | ||
| Datastore datastore = EnvironmentUtils.datastoreBuilderFromDatastoreOptions(datastoreOptions).build().getService(); |
| public Value<Void> run() { | ||
| Datastore datastore = datastoreOptions.toBuilder().build().getService(); | ||
| // if coming from deserialization may lose transient properties that cause NPE | ||
| Datastore datastore = EnvironmentUtils.datastoreBuilderFromDatastoreOptions(datastoreOptions).build().getService(); |
…t order Test was written for old order (enqueue tasks then commit Datastore). Current implementation commits Datastore first, so when Datastore fails tasks are never enqueued and nothing needs to be deleted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
# Conflicts: # java/pom.xml
finalize() is deprecated and marked for removal in modern Java. The override only logged a warning for unclosed transactions — no actual resource cleanup. Callers already have rollbackIfActive() for explicit cleanup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…local-dev-fix # Conflicts: # java/pom.xml # java/src/test/java/com/google/appengine/tools/txn/PipelineBackendTransactionImplTest.java
| Set<PipelineTaskQueue.TaskReference> taskReferences = Collections | ||
| .singleton(PipelineTaskQueue.TaskReference.of("queue1", "task-ref")); |
| // Only used in tests | ||
| public AppEngineBackEnd(Options options, PipelineTaskQueue taskQueue, AppEngineServicesService appEngineServicesService) { | ||
| this(options.getDatastoreOptions().toBuilder().build().getService(), taskQueue, appEngineServicesService); | ||
| this(EnvironmentUtils.datastoreBuilderFromDatastoreOptions(options.getDatastoreOptions()).build().getService(), taskQueue, appEngineServicesService); |
5c39231 to
f6d8049
Compare
f6d8049 to
27dd669
Compare
Fixes
Attempt to fix local dev datastore after Google bom update to 26.83.0 that introduced some changes to the datastore that broken local dev (that get's injected from worklyytics' main project)
Change implications