|
20 | 20 |
|
21 | 21 | package com.arangodb;
|
22 | 22 |
|
| 23 | +import com.arangodb.config.ArangoConfigProperties; |
| 24 | +import com.arangodb.config.HostDescription; |
23 | 25 | import com.arangodb.entity.*;
|
24 | 26 | import com.arangodb.internal.ArangoDBImpl;
|
25 | 27 | import com.arangodb.internal.ArangoExecutorSync;
|
26 |
| -import com.arangodb.internal.InternalArangoDBBuilder; |
| 28 | +import com.arangodb.internal.config.ArangoConfig; |
27 | 29 | import com.arangodb.internal.net.*;
|
| 30 | +import com.arangodb.internal.util.HostUtils; |
28 | 31 | import com.arangodb.model.*;
|
| 32 | +import com.arangodb.serde.ArangoSerde; |
| 33 | +import org.slf4j.Logger; |
| 34 | +import org.slf4j.LoggerFactory; |
29 | 35 |
|
30 | 36 | import javax.annotation.concurrent.ThreadSafe;
|
| 37 | +import javax.net.ssl.SSLContext; |
| 38 | +import java.util.ArrayList; |
31 | 39 | import java.util.Collection;
|
| 40 | +import java.util.ServiceLoader; |
| 41 | +import java.util.concurrent.Executor; |
32 | 42 |
|
33 | 43 | /**
|
34 | 44 | * Central access point for applications to communicate with an ArangoDB server.
|
@@ -338,7 +348,9 @@ public interface ArangoDB extends ArangoSerdeAccessor {
|
338 | 348 | *
|
339 | 349 | * @author Mark Vollmary
|
340 | 350 | */
|
341 |
| - class Builder extends InternalArangoDBBuilder<Builder> { |
| 351 | + class Builder { |
| 352 | + private static final Logger LOG = LoggerFactory.getLogger(Builder.class); |
| 353 | + private final ArangoConfig config = new ArangoConfig(); |
342 | 354 |
|
343 | 355 | /**
|
344 | 356 | * Returns an instance of {@link ArangoDB}.
|
@@ -370,6 +382,304 @@ public ArangoDB build() {
|
370 | 382 | );
|
371 | 383 | }
|
372 | 384 |
|
| 385 | + public Builder loadProperties(final ArangoConfigProperties properties) { |
| 386 | + config.loadProperties(properties); |
| 387 | + return this; |
| 388 | + } |
| 389 | + |
| 390 | + public Builder protocol(final Protocol protocol) { |
| 391 | + config.setProtocol(protocol); |
| 392 | + return this; |
| 393 | + } |
| 394 | + |
| 395 | + /** |
| 396 | + * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. |
| 397 | + * |
| 398 | + * @param host address of the host |
| 399 | + * @param port port of the host |
| 400 | + * @return {@link ArangoDB.Builder} |
| 401 | + */ |
| 402 | + public Builder host(final String host, final int port) { |
| 403 | + config.addHost(new HostDescription(host, port)); |
| 404 | + return this; |
| 405 | + } |
| 406 | + |
| 407 | + /** |
| 408 | + * Sets the connection and request timeout in milliseconds. |
| 409 | + * |
| 410 | + * @param timeout timeout in milliseconds |
| 411 | + * @return {@link ArangoDB.Builder} |
| 412 | + */ |
| 413 | + public Builder timeout(final Integer timeout) { |
| 414 | + config.setTimeout(timeout); |
| 415 | + return this; |
| 416 | + } |
| 417 | + |
| 418 | + /** |
| 419 | + * Sets the username to use for authentication. |
| 420 | + * |
| 421 | + * @param user the user in the database (default: {@code root}) |
| 422 | + * @return {@link ArangoDB.Builder} |
| 423 | + */ |
| 424 | + public Builder user(final String user) { |
| 425 | + config.setUser(user); |
| 426 | + return this; |
| 427 | + } |
| 428 | + |
| 429 | + /** |
| 430 | + * Sets the password for the user for authentication. |
| 431 | + * |
| 432 | + * @param password the password of the user in the database (default: {@code null}) |
| 433 | + * @return {@link ArangoDB.Builder} |
| 434 | + */ |
| 435 | + public Builder password(final String password) { |
| 436 | + config.setPassword(password); |
| 437 | + return this; |
| 438 | + } |
| 439 | + |
| 440 | + /** |
| 441 | + * Sets the JWT for the user authentication. |
| 442 | + * |
| 443 | + * @param jwt token to use (default: {@code null}) |
| 444 | + * @return {@link ArangoDB.Builder} |
| 445 | + */ |
| 446 | + public Builder jwt(final String jwt) { |
| 447 | + config.setJwt(jwt); |
| 448 | + return this; |
| 449 | + } |
| 450 | + |
| 451 | + /** |
| 452 | + * If set to {@code true} SSL will be used when connecting to an ArangoDB server. |
| 453 | + * |
| 454 | + * @param useSsl whether or not use SSL (default: {@code false}) |
| 455 | + * @return {@link ArangoDB.Builder} |
| 456 | + */ |
| 457 | + public Builder useSsl(final Boolean useSsl) { |
| 458 | + config.setUseSsl(useSsl); |
| 459 | + return this; |
| 460 | + } |
| 461 | + |
| 462 | + /** |
| 463 | + * Sets the SSL context to be used when {@code true} is passed through {@link #useSsl(Boolean)}. |
| 464 | + * |
| 465 | + * @param sslContext SSL context to be used |
| 466 | + * @return {@link ArangoDB.Builder} |
| 467 | + */ |
| 468 | + public Builder sslContext(final SSLContext sslContext) { |
| 469 | + config.setSslContext(sslContext); |
| 470 | + return this; |
| 471 | + } |
| 472 | + |
| 473 | + /** |
| 474 | + * Set whether hostname verification is enabled |
| 475 | + * |
| 476 | + * @param verifyHost {@code true} if enabled |
| 477 | + * @return {@link ArangoDB.Builder} |
| 478 | + */ |
| 479 | + public Builder verifyHost(final Boolean verifyHost) { |
| 480 | + config.setVerifyHost(verifyHost); |
| 481 | + return this; |
| 482 | + } |
| 483 | + |
| 484 | + /** |
| 485 | + * Sets the chunk size when {@link Protocol#VST} is used. |
| 486 | + * |
| 487 | + * @param chunkSize size of a chunk in bytes |
| 488 | + * @return {@link ArangoDB.Builder} |
| 489 | + */ |
| 490 | + public Builder chunkSize(final Integer chunkSize) { |
| 491 | + config.setChunkSize(chunkSize); |
| 492 | + return this; |
| 493 | + } |
| 494 | + |
| 495 | + /** |
| 496 | + * Sets the maximum number of connections the built in connection pool will open per host. |
| 497 | + * |
| 498 | + * <p> |
| 499 | + * Defaults: |
| 500 | + * </p> |
| 501 | + * |
| 502 | + * <pre> |
| 503 | + * {@link Protocol#VST} == 1 |
| 504 | + * {@link Protocol#HTTP_JSON} == 20 |
| 505 | + * {@link Protocol#HTTP_VPACK} == 20 |
| 506 | + * </pre> |
| 507 | + * |
| 508 | + * @param maxConnections max number of connections |
| 509 | + * @return {@link ArangoDB.Builder} |
| 510 | + */ |
| 511 | + public Builder maxConnections(final Integer maxConnections) { |
| 512 | + config.setMaxConnections(maxConnections); |
| 513 | + return this; |
| 514 | + } |
| 515 | + |
| 516 | + /** |
| 517 | + * Set the maximum time to life of a connection. After this time the connection will be closed automatically. |
| 518 | + * |
| 519 | + * @param connectionTtl the maximum time to life of a connection in milliseconds |
| 520 | + * @return {@link ArangoDB.Builder} |
| 521 | + */ |
| 522 | + public Builder connectionTtl(final Long connectionTtl) { |
| 523 | + config.setConnectionTtl(connectionTtl); |
| 524 | + return this; |
| 525 | + } |
| 526 | + |
| 527 | + /** |
| 528 | + * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request |
| 529 | + * every {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the |
| 530 | + * external environment, eg. firewall, intermediate routers, operating system). |
| 531 | + * |
| 532 | + * @param keepAliveInterval interval in seconds |
| 533 | + * @return {@link ArangoDB.Builder} |
| 534 | + */ |
| 535 | + public Builder keepAliveInterval(final Integer keepAliveInterval) { |
| 536 | + config.setKeepAliveInterval(keepAliveInterval); |
| 537 | + return this; |
| 538 | + } |
| 539 | + |
| 540 | + /** |
| 541 | + * Whether the driver should acquire a list of available coordinators in an ArangoDB cluster or a single |
| 542 | + * server with active failover. In case of Active-Failover deployment set to {@code true} to enable automatic |
| 543 | + * master discovery. |
| 544 | + * |
| 545 | + * <p> |
| 546 | + * The host list will be used for failover and load balancing. |
| 547 | + * </p> |
| 548 | + * |
| 549 | + * @param acquireHostList whether automatically acquire a list of available hosts (default: false) |
| 550 | + * @return {@link ArangoDB.Builder} |
| 551 | + */ |
| 552 | + public Builder acquireHostList(final Boolean acquireHostList) { |
| 553 | + config.setAcquireHostList(acquireHostList); |
| 554 | + return this; |
| 555 | + } |
| 556 | + |
| 557 | + /** |
| 558 | + * Setting the Interval for acquireHostList |
| 559 | + * |
| 560 | + * @param acquireHostListInterval Interval in milliseconds |
| 561 | + * @return {@link ArangoDB.Builder} |
| 562 | + */ |
| 563 | + public Builder acquireHostListInterval(final Integer acquireHostListInterval) { |
| 564 | + config.setAcquireHostListInterval(acquireHostListInterval); |
| 565 | + return this; |
| 566 | + } |
| 567 | + |
| 568 | + /** |
| 569 | + * Sets the load balancing strategy to be used in an ArangoDB cluster setup. In case of Active-Failover |
| 570 | + * deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that would be the default. |
| 571 | + * |
| 572 | + * @param loadBalancingStrategy the load balancing strategy to be used (default: |
| 573 | + * {@link LoadBalancingStrategy#NONE} |
| 574 | + * @return {@link ArangoDB.Builder} |
| 575 | + */ |
| 576 | + public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { |
| 577 | + config.setLoadBalancingStrategy(loadBalancingStrategy); |
| 578 | + return this; |
| 579 | + } |
| 580 | + |
| 581 | + /** |
| 582 | + * Setting the amount of samples kept for queue time metrics |
| 583 | + * |
| 584 | + * @param responseQueueTimeSamples amount of samples to keep |
| 585 | + * @return {@link ArangoDB.Builder} |
| 586 | + */ |
| 587 | + public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) { |
| 588 | + config.setResponseQueueTimeSamples(responseQueueTimeSamples); |
| 589 | + return this; |
| 590 | + } |
| 591 | + |
| 592 | + /** |
| 593 | + * Sets the serde for the user data. |
| 594 | + * This is used to serialize and deserialize all the data payload such as: |
| 595 | + * - documents, vertexes, edges |
| 596 | + * - AQL bind vars |
| 597 | + * - body payload of requests and responses in {@link ArangoDB#execute(Request, Class)} |
| 598 | + * <p> |
| 599 | + * However, note that the following types will always be serialized and deserialized using the internal serde: |
| 600 | + * - {@link com.fasterxml.jackson.databind.JsonNode} |
| 601 | + * - {@link com.arangodb.util.RawJson} |
| 602 | + * - {@link com.arangodb.util.RawBytes} |
| 603 | + * - {@link com.arangodb.entity.BaseDocument} |
| 604 | + * - {@link com.arangodb.entity.BaseEdgeDocument} |
| 605 | + * |
| 606 | + * @param serde custom serde for the user data |
| 607 | + * @return {@link ArangoDB.Builder} |
| 608 | + */ |
| 609 | + public Builder serde(final ArangoSerde serde) { |
| 610 | + config.setUserDataSerde(serde); |
| 611 | + return this; |
| 612 | + } |
| 613 | + |
| 614 | + /** |
| 615 | + * Sets the downstream async executor that will be used to consume the responses of the async API, that are returned |
| 616 | + * as {@link java.util.concurrent.CompletableFuture} |
| 617 | + * |
| 618 | + * @param executor async downstream executor |
| 619 | + * @return {@link ArangoDB.Builder} |
| 620 | + */ |
| 621 | + public Builder asyncExecutor(final Executor executor) { |
| 622 | + config.setAsyncExecutor(executor); |
| 623 | + return this; |
| 624 | + } |
| 625 | + |
| 626 | + protected ProtocolProvider protocolProvider(Protocol protocol) { |
| 627 | + ServiceLoader<ProtocolProvider> loader = ServiceLoader.load(ProtocolProvider.class); |
| 628 | + for (ProtocolProvider p : loader) { |
| 629 | + if (p.supportsProtocol(protocol)) { |
| 630 | + return p; |
| 631 | + } |
| 632 | + LOG.debug("Required protocol ({}) not supported by ProtocolProvider: {}", protocol, p.getClass().getName()); |
| 633 | + } |
| 634 | + throw new ArangoDBException("No ProtocolProvider found for protocol: " + protocol); |
| 635 | + } |
| 636 | + |
| 637 | + protected HostHandler createHostHandler(final HostResolver hostResolver) { |
| 638 | + |
| 639 | + final HostHandler hostHandler; |
| 640 | + |
| 641 | + LoadBalancingStrategy loadBalancingStrategy = config.getLoadBalancingStrategy(); |
| 642 | + if (loadBalancingStrategy != null) { |
| 643 | + switch (loadBalancingStrategy) { |
| 644 | + case ONE_RANDOM: |
| 645 | + hostHandler = new RandomHostHandler(hostResolver, new FallbackHostHandler(hostResolver)); |
| 646 | + break; |
| 647 | + case ROUND_ROBIN: |
| 648 | + hostHandler = new RoundRobinHostHandler(hostResolver); |
| 649 | + break; |
| 650 | + case NONE: |
| 651 | + default: |
| 652 | + hostHandler = new FallbackHostHandler(hostResolver); |
| 653 | + break; |
| 654 | + } |
| 655 | + } else { |
| 656 | + hostHandler = new FallbackHostHandler(hostResolver); |
| 657 | + } |
| 658 | + |
| 659 | + LOG.debug("HostHandler is {}", hostHandler.getClass().getSimpleName()); |
| 660 | + |
| 661 | + return new DirtyReadHostHandler(hostHandler, new RoundRobinHostHandler(hostResolver)); |
| 662 | + } |
| 663 | + |
| 664 | + protected HostResolver createHostResolver(final Collection<Host> hosts, final ConnectionFactory connectionFactory) { |
| 665 | + Boolean acquireHostList = config.getAcquireHostList(); |
| 666 | + if (acquireHostList != null && acquireHostList) { |
| 667 | + LOG.debug("acquireHostList -> Use ExtendedHostResolver"); |
| 668 | + return new ExtendedHostResolver(new ArrayList<>(hosts), config, connectionFactory, |
| 669 | + config.getAcquireHostListInterval()); |
| 670 | + } else { |
| 671 | + LOG.debug("Use SimpleHostResolver"); |
| 672 | + return new SimpleHostResolver(new ArrayList<>(hosts)); |
| 673 | + } |
| 674 | + } |
| 675 | + |
| 676 | + protected Collection<Host> createHostList(final ConnectionFactory connectionFactory) { |
| 677 | + final Collection<Host> hostList = new ArrayList<>(); |
| 678 | + for (final HostDescription host : config.getHosts()) { |
| 679 | + hostList.add(HostUtils.createHost(host, config, connectionFactory)); |
| 680 | + } |
| 681 | + return hostList; |
| 682 | + } |
373 | 683 | }
|
374 | 684 |
|
375 | 685 | }
|
0 commit comments