1. A Store pod is replaced in Kubernetes and comes back on a new IP behind the
same stable DNS name.
2. HugeGraph Server runs with `HugeSecurityManager` installed by default.
3. With a `SecurityManager` present and no explicit policy, Java 11 falls back to
`networkaddress.cache.ttl = -1`, so `InetAddressCachePolicy` is `FOREVER`.
4. The Server therefore keeps resolving the Store name to the old pod IP, and
HStore writes keep going to an address that no longer exists.
5. Nothing recovers this until the Server process is restarted.
The setting is only honoured as a **security** property. The ordinary
`-Dnetworkaddress.cache.ttl` system property has no effect here, which is why
that form is deliberately not used.
---------
Co-authored-by: imbajin <jin@apache.org>
Fix a startup hang in kind/Kubernetes environments — the case that surfaced while bringing up the Helm chart. In a pod where `ulimit -n` is very large, `lsof -i :PORT` walks an enormous file descriptor table and `start-hugegraph.sh` stalls before the server ever binds.
The fix replaces that `lsof` call in the server's `check_port`, and removes the dead `check_port` copies from PD/Store.
- retain a bounded real-clock startup smoke test
---------
Co-authored-by: imbajin <jin@apache.org>
- cap each PD connection attempt at 2 seconds
- cap each PD request at 3 seconds
- cover failover after a hanging first peer
---------
Co-authored-by: imbajin <jin@apache.org>
AbstractGrpcClient opens concurrency (32) ManagedChannels per target, but
both stub-pool initializers used one precomputed channel index inside their
loops. Every pool entry therefore pointed at the same channel while the other
31 channels remained idle.
- use channels[i] in the blocking and async pool initializers
- add self-contained tests that verify every pool channel is bound
- add ClientSuiteTest so the store-client-test profile runs the tests
Fixes#3125
Remove the backend implementations that have been unsupported since 1.7.0, and
clean up their related build, distribution, test, release, and documentation
artifacts.
- retain the server and backend component boxes in the ASCII diagram
- show HugeGraph-PD and HStore as separate distributed components
- keep removed legacy backends out of the current topology
---------
Co-authored-by: imbajin <jin@apache.org>
- Address the HugeGraph Server + RocksDB `linux/riscv64` build and minimum runtime
support tracked by #3099.
- Keep the change isolated from the existing Docker image design and from the JDK,
build, and test paths used by other architectures.
---------
Co-authored-by: Sean <sean@SeandeMacBook-Pro.local>
- bind Maven build stages to BUILDPLATFORM
- keep all runtime stages target-platform specific
- avoid emulated Maven builds for ARM images
- cover PD, Store, standalone, and HStore images
This PR soft-disables the pre-PD master-worker task scheduling path while keeping old configs and task data upgrade-safe. Scheduler selection is now backend-driven: `hstore` uses `DistributedTaskScheduler`, and other backends use the local `StandardTaskScheduler`.
---------
Co-authored-by: Himanshu Verma <himnshuverma10152006@gmail.com>
Co-authored-by: imbajin <jin@apache.org>
EtcdMetaDriver.listen/listenPrefix handed jetcd a bare Consumer<WatchResponse>,
so a terminal watch error (e.g. after a transport reconnect) was swallowed and
the JVM-global schema-cache-clear listener died silently: a node stopped
receiving cross-node cache-clear events with no error or warning.
Switch to the Watch.Listener overload and re-subscribe on onError/onCompleted
via a daemon-backed backoff, mirroring the self-heal PdMetaDriver already gets
from KvClient. The driver watch now stays live across reconnects, so
CachedSchemaTransactionV2's register-once flag staying true is correct; the
unused resetMetaListenerForReconnect stopgap and its TODO are removed.
storeEventListenStatus had the same owner-first-close bug #3017 fixed for
graph cache listeners: non-owner close() dropped the entry and skipped
unlisten() as a no-op, leaking the owner's listener.
Apply CacheListenerHolder ref-count pattern: StoreListenerHolder +
STORE_EVENT_LISTENERS in CachedGraphTransaction, acquire/release via
compute() with provider-identity guard for close/reopen.
Removes storeEventListenStatus from GraphTransaction and
restoreStoreListenerStatusForKnownTeardownBug workaround from tests.
CachedSchemaTransaction* unaffected (per-instance, balanced 1:1).
Move BytesBuffer.initMaxBufferCapacity() and other process-wide static
config initializations before LockUtil.init() so that validation failures
(e.g. invalid or conflicting serializer.buffer_max_capacity) cannot leave
orphaned lock groups in LockManager, which would block subsequent graph
load attempts without a process restart.
🤖 Generated with [Qoder][https://qoder.com]
- Add -d true|false option to PD and Store startup options sections
(default: true = daemon; false = foreground for Docker/supervisors)
- Add section to docker/README.md explaining HEALTHCHECK endpoints
and the Java process supervision model (replaces old cron monitor)
Chunk 10 of #3043.
All three startup test scripts previously exited 0 when required tools
(lsof, curl, java) were not found. This is indistinguishable from a
passing test run — CI shows green even though no tests ran.
Change skip exits to 77 (conventional skip code) and update the CI
workflow steps to treat exit 77 as a visible skip notice rather than
a failure.
Flagged as non-blocking follow-up in reviews of #3044 and #3047.
Related to: #3043
* fix [Bug]: gremlin-console.sh fails on Mac M4 (Apple Silicon)#3031
Added org.fusesource.jansi:jansi:2.4.0 as a runtime dependency in
`hugegraph-server/hugegraph-dist/pom.xml` to prevent
NoClassDefFoundError: org/fusesource/jansi/AnsiConsole when launching gremlin-console.
Without HEALTHCHECK, docker ps always shows 'Up' even when Java has
crashed inside the container. Add HEALTHCHECK to all three Dockerfiles:
- Server: curl http://localhost:8080/versions
- PD: curl http://localhost:8620/v1/health
- Store: curl http://localhost:8520/v1/health
Fallback: if HTTP is not yet up but Java is alive (kill -0 on pid file),
report healthy. Avoids false unhealthy during startup.
Remove cron: Docker containers use foreground mode (-d false) after the
entrypoint fix. The cron-based monitor is for VM/bare-metal only and is
never started in Docker — removing it shrinks the image and reduces
attack surface.
Endpoints match what is already used in docker/docker-compose.yml.
Related to: #3043
Problem: all three docker-entrypoint.sh files used tail -f /dev/null to
keep the container alive. When Java crashed, tail kept running and the
container stayed up with no Java inside — Docker restart policy never fired.
Verified locally: kill -9 Java inside running container -> container
exits -> Docker restarts it automatically (tested 3 times for server,
PD restart loop confirmed for pd).
* optimize: Optimize RocksDB batch query performance
* Refactor getByIds to queryByIds in RocksDBTable
* Modify queryByIds to use super method temporarily
Temporarily use super.queryByIds() instead of getByIds() for batch version support.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
In foreground mode (-d false), start-hugegraph-pd.sh had no foreground
branch — the script always backgrounded Java with exec ... &, wrote $!
to the pid file, and exited 0, losing Java's exit code entirely.
Fix: add DAEMON="true" default and -d flag to getopts. In the daemon
branch, keep the existing exec ... & pattern. In the foreground branch,
write $$ to the pid file before exec (exec replaces the shell with Java,
so $$ == Java's PID after exec), then exec java without & so the process
blocks and Java's exit code propagates out directly.
No trap needed in the foreground branch — exec replaces the shell
process with Java, so signals from Docker/systemd go directly to Java
without a wrapper to forward through.
Add test-start-hugegraph-pd.sh with 4 tests (daemon regression,
foreground blocking, exit code propagation on SIGKILL, SIGTERM
forwarding via exec) — 12 assertions, all pass after the fix.
Baseline on unmodified code: 3 passed, 9 failed.
After fix: 12 passed, 0 failed.
Wire test into pd-store-ci.yml for the RocksDB backend.
Related to: #3043
The previous implementation captured $! after the daemon/foreground
if/else block. The script blocked at hugegraph-server.sh until Java
exited, then $! was empty, the pid file got an empty string, and the
script exited 0, losing Java's exit code entirely.
Normalizes PropertyKey default values to their declared data type upon retrieval. Previously, values stored in userdata could lose their original type during serialization and deserialization (e.g., Date becoming String), leading to type mismatches.
The `defaultValue()` method now converts deserialized string representations back to their expected runtime types. This change is verified with extensive tests covering schema parsing, vertex property assignment, and both binary and text serializers.
- Replace exploratory README steps with the actual packaged archive path
- Use the version placeholder instead of hard-coded 1.7.0
- Keep the PR focused on the source-build documentation fix
---------
Co-authored-by: imbajin <jin@apache.org>
Normalize server-side schema ~create_time userdata in SchemaElement so serializer reloads and fromMap paths keep the Date contract.
Add SchemaElement, TextSerializer, and BinarySerializer coverage.
The builder accumulates userdata via Userdata.put() before eliminate()
runs, so `.userdata(CREATE_TIME, "").eliminate()` parsed "" as a date
and threw before the key-only removal path. Pass a blank ~create_time
through unchanged; non-empty malformed values still throw on the add
path, so the existing contract is unchanged.
## Main Changes
Change `ServerInfoManager.selfNodeId()` which returns "server-1" previously to "{graphname}/server-1"
## Upgrade impact
This change namespaces the server id by graph name, so old unfinished tasks in the non-PD local scheduler may still reference the previous bare server id, for example `server-1`.
Those historical tasks can remain visible, but they may not be restored or cancelled by the new namespaced server id after upgrade. The impact is limited to unfinished local-scheduler tasks that already existed before upgrading; newly scheduled tasks use the new namespaced id. To avoid this compatibility edge case, finish or cancel pending local tasks before upgrading.
- Align legacy cache invalidation producers and listeners on ACTION_INVALID and
ACTION_CLEAR, removing the obsolete ACTION_INVALIDED/ACTION_CLEARED constants.
- Add EventHub.notifyExcept(...) so cache transactions and the cache notifier
bridge can avoid re-processing their own local listener while still delivering
events to other listeners.
- Track registered graph/schema cache listeners per graph so notifyExcept(...)
uses the listener instance actually registered on the EventHub, including
multi-transaction cases where later transactions reuse the first listener.
- Update cache notifier forwarding to prevent local RPC bridge loops after action
names are unified.
- Add regression coverage for notifyExcept semantics, graph/schema action names,
listener teardown/re-registration, and notifier no-loop behavior.
- The holder keeps the EventHub listener registered while any transaction for the
graph is alive, and unregisters/removes it only when the last transaction
releases it. The registry update, ref-count decrement, and hub unlisten now run
inside ConcurrentMap.compute() to avoid owner-closes-first invalidation gaps.
Also add graph/schema regression coverage for owner-first close and last-close
cleanup, including graph close/reopen handling for stale EventHub holders.
- Resolve Travis helper directory to an absolute path
- Use the script directory directly for JaCoCo agent lookup
- Avoid nesting absolute paths under the repository root
---------
Co-authored-by: imbajin <jin@apache.org>
- Refresh all 8 memories to reflect current code (v1.7.0)
- Remove all PR number references (derivable from git history)
- Remove "Key Recent Changes" changelog section
- Remove CI implementation details (rerun delay/count)
- Describe current behavior as facts, not change events
- Mark legacy backends as excluded from Serena context
- Add GraphSpace, Swagger UI, TTL update, bridge networking info
Register a JVM-wide MetaManager listener on CachedSchemaTransactionV2 so
remote nodes clear their V2 schema-id/schema-name caches and the array
attachment on schema add/remove. Events carry a per-JVM source id to skip
self-echo;
legacy plain-string payloads still accepted for safe rolling
upgrades. Status transitions no longer broadcast to avoid notify storms
from background rebuild/remove jobs.
- Reset driver session after each transient failure in executeWithRetry()
so retries reopen cleanly via lazy open()
- Remove redundant finally block in reconnectIfNeeded(); null session
directly on DriverException
- Store retryBaseDelay as field, reuse in open() (removes double-read)
- One-time LOG.warn via AtomicBoolean for commitAsync() retry gap
- Tighten defaults: max_delay 60s→10s, max_retries 10→3, interval 5s→1s
- Wire retry config via HugeConfig in tests; add cross-validator tests
* fix(pd): complete GET / stats fix and add test coverage
- Use pdService.getMembers() for memberSize (consistent with cluster())
instead of RaftEngine directly, as suggested in issue #3002 discussion
- Add dataState field to BriefStatistics: exposes worst partition health
state across all graphs, the most useful missing operational indicator
- Align graphSize to count only user-facing graphs (endsWith("/g")),
matching the semantics of cluster() to avoid silent count discrepancy
- Add testQueryIndexInfo() to both RestApiTest classes to assert state,
leader, memberSize > 0, and storeSize > 0 — catches this class of bug
* fix(pd): relax storeSize assertion in PD-only test environment
---------
Co-authored-by: imbajin <jin@apache.org>
* fix(docker): skip partition wait for standalone rocksdb mode (#2999)
The `wait-partition.sh` script was called unconditionally in
`docker-entrypoint.sh`, causing standalone containers (rocksdb backend)
to hang for 120s printing "Waiting for partition assignment..." since
there is no Store service to respond.
Now reads the actual backend from `hugegraph.properties` and only runs
the partition wait when `backend=hstore`.