├── .circleci ├── clojars │ └── profiles.clj ├── config.yml └── scripts │ ├── update-tocs.sh │ ├── verify-dockerfile.sh │ ├── verify-docs.sh │ └── verify-license-headers.sh ├── .clj-kondo └── config.edn ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── LICENSE ├── LICENSE-3RD-PARTY.txt ├── Makefile ├── NOTICE ├── README.md ├── aviary.yaml ├── core ├── java-src │ └── eva │ │ ├── Alpha.java │ │ ├── Attribute.java │ │ ├── ByteString.java │ │ ├── ByteStringInputStream.java │ │ ├── ByteStringOutputStream.java │ │ ├── Connection.java │ │ ├── Database.java │ │ ├── Datom.java │ │ ├── Entity.java │ │ ├── Id.java │ │ ├── Log.java │ │ ├── Peer.java │ │ ├── Util.java │ │ ├── error │ │ └── v1 │ │ │ ├── EvaErrorCode.java │ │ │ ├── EvaException.java │ │ │ ├── ICodedExceptionInfo.java │ │ │ ├── IErrorCode.java │ │ │ └── SanitizedEvaException.java │ │ └── storage │ │ └── ChunkCallbackOutputStream.java ├── resources │ ├── data_readers.clj │ ├── eva │ │ ├── error │ │ │ └── error_codes.edn │ │ └── storage │ │ │ └── sql │ │ │ ├── h2 │ │ │ └── h2-table.sql │ │ │ ├── mariadb │ │ │ ├── mariadb-db.sql │ │ │ └── mariadb-table.sql │ │ │ └── postgres │ │ │ ├── postgres-db.sql │ │ │ └── postgres-table.sql │ └── logback.xml ├── src │ └── eva │ │ ├── admin │ │ ├── alpha │ │ │ ├── api.clj │ │ │ ├── cli.clj │ │ │ └── traversal.clj │ │ └── graph │ │ │ └── alpha.clj │ │ ├── alpha.clj │ │ ├── api.clj │ │ ├── api │ │ └── java │ │ │ └── util.clj │ │ ├── attribute.clj │ │ ├── builtin.clj │ │ ├── bytes.clj │ │ ├── comparators.clj │ │ ├── concurrent │ │ └── background_resource_map.clj │ │ ├── config.clj │ │ ├── contextual │ │ ├── README.md │ │ ├── config.clj │ │ ├── context.clj │ │ ├── core.clj │ │ ├── logging.clj │ │ ├── metrics.clj │ │ ├── tags.clj │ │ ├── tracing.clj │ │ └── utils.clj │ │ ├── core.clj │ │ ├── datastructures │ │ ├── error.clj │ │ ├── protocols.clj │ │ ├── utils │ │ │ ├── comparators.clj │ │ │ ├── core.clj │ │ │ ├── fressian.clj │ │ │ └── interval.clj │ │ └── versioning.clj │ │ ├── datom.clj │ │ ├── db_update.clj │ │ ├── defaults.clj │ │ ├── entity.clj │ │ ├── entity_id.clj │ │ ├── error.clj │ │ ├── functions.clj │ │ ├── logging.clj │ │ ├── print_ext.clj │ │ ├── query │ │ ├── README.md │ │ ├── core.clj │ │ ├── datalog │ │ │ ├── edb.clj │ │ │ ├── error.clj │ │ │ ├── evaluable.clj │ │ │ ├── predicate.clj │ │ │ ├── program.clj │ │ │ ├── protocols.clj │ │ │ ├── qsqr │ │ │ │ ├── core.clj │ │ │ │ ├── protocols.clj │ │ │ │ └── state.clj │ │ │ └── rule.clj │ │ ├── dialect │ │ │ ├── aggregates.clj │ │ │ ├── functions.clj │ │ │ ├── pull │ │ │ │ ├── ast.clj │ │ │ │ ├── core.clj │ │ │ │ ├── error.clj │ │ │ │ └── parser.clj │ │ │ ├── pull_helpers.clj │ │ │ ├── sandbox.clj │ │ │ ├── spec.clj │ │ │ ├── translation │ │ │ │ ├── compile.clj │ │ │ │ ├── compile │ │ │ │ │ ├── pass1.clj │ │ │ │ │ └── pass2.clj │ │ │ │ ├── core.clj │ │ │ │ ├── edb.clj │ │ │ │ └── error.clj │ │ │ └── util.clj │ │ ├── error.clj │ │ ├── trace.clj │ │ └── util.clj │ │ ├── readers.clj │ │ ├── sizing_api.clj │ │ ├── utils.clj │ │ ├── utils │ │ ├── delay_queue.clj │ │ ├── guava_cache.clj │ │ ├── logging.clj │ │ ├── testing.clj │ │ ├── tracing.clj │ │ └── unify.clj │ │ ├── v2 │ │ ├── database │ │ │ ├── core.clj │ │ │ ├── history_snapshot.clj │ │ │ ├── index.clj │ │ │ ├── index_manager.clj │ │ │ ├── log.clj │ │ │ ├── lookup_refs.clj │ │ │ └── overlay.clj │ │ ├── datastructures │ │ │ ├── README.md │ │ │ ├── atom.clj │ │ │ ├── bbtree.clj │ │ │ ├── bbtree │ │ │ │ ├── README.md │ │ │ │ ├── api.clj │ │ │ │ ├── error.clj │ │ │ │ ├── fressian.clj │ │ │ │ ├── fressian │ │ │ │ │ └── v0.clj │ │ │ │ ├── logic │ │ │ │ │ └── v0 │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ ├── balance.clj │ │ │ │ │ │ ├── buffer.clj │ │ │ │ │ │ ├── core.clj │ │ │ │ │ │ ├── docs │ │ │ │ │ │ ├── balance.md │ │ │ │ │ │ └── images │ │ │ │ │ │ │ ├── balance-illustration-1.png │ │ │ │ │ │ │ ├── balance-illustration-2.png │ │ │ │ │ │ │ └── balance-illustration-3.png │ │ │ │ │ │ ├── error.clj │ │ │ │ │ │ ├── message.clj │ │ │ │ │ │ ├── nodes.clj │ │ │ │ │ │ ├── operations.clj │ │ │ │ │ │ ├── protocols.clj │ │ │ │ │ │ ├── query.clj │ │ │ │ │ │ ├── state.clj │ │ │ │ │ │ ├── storage.clj │ │ │ │ │ │ ├── tree.clj │ │ │ │ │ │ └── types.clj │ │ │ │ └── storage.clj │ │ │ ├── var.clj │ │ │ └── vector.clj │ │ ├── fressian.clj │ │ ├── messaging │ │ │ ├── address.clj │ │ │ ├── jms │ │ │ │ ├── alpha │ │ │ │ │ ├── core.clj │ │ │ │ │ └── message.clj │ │ │ │ └── beta │ │ │ │ │ ├── connection_factory.clj │ │ │ │ │ ├── core.clj │ │ │ │ │ └── patterns.clj │ │ │ └── node │ │ │ │ ├── alpha.clj │ │ │ │ ├── beta.clj │ │ │ │ ├── local.clj │ │ │ │ ├── local_simulation.clj │ │ │ │ └── manager │ │ │ │ ├── alpha.clj │ │ │ │ └── types.clj │ │ ├── storage │ │ │ ├── block_store.clj │ │ │ ├── block_store │ │ │ │ ├── impl │ │ │ │ │ ├── ddb.clj │ │ │ │ │ ├── memory.clj │ │ │ │ │ └── sql.clj │ │ │ │ └── types.clj │ │ │ ├── core.clj │ │ │ ├── ddb.clj │ │ │ ├── error.clj │ │ │ ├── local.clj │ │ │ ├── system.clj │ │ │ ├── value_store.clj │ │ │ └── value_store │ │ │ │ ├── README.md │ │ │ │ ├── concurrent.clj │ │ │ │ ├── core.clj │ │ │ │ ├── docs │ │ │ │ ├── reader.png │ │ │ │ ├── simplified-reader.png │ │ │ │ └── writer.png │ │ │ │ ├── functions.clj │ │ │ │ ├── gcached.clj │ │ │ │ ├── handlers.clj │ │ │ │ ├── manager.clj │ │ │ │ └── protocols.clj │ │ ├── system │ │ │ ├── database_catalogue │ │ │ │ └── core.clj │ │ │ ├── database_connection │ │ │ │ └── core.clj │ │ │ ├── indexing │ │ │ │ ├── core.clj │ │ │ │ └── indexer_agent.clj │ │ │ ├── message.clj │ │ │ ├── peer_connection │ │ │ │ ├── autogenetic.clj │ │ │ │ ├── core.clj │ │ │ │ └── error.clj │ │ │ ├── protocols.clj │ │ │ └── transactor │ │ │ │ └── core.clj │ │ ├── transaction_pipeline │ │ │ ├── core.clj │ │ │ ├── error.clj │ │ │ ├── protocols.clj │ │ │ ├── resolve │ │ │ │ ├── ids.clj │ │ │ │ ├── maps.clj │ │ │ │ ├── maps │ │ │ │ │ └── flatten.clj │ │ │ │ └── tx_fns.clj │ │ │ ├── type │ │ │ │ ├── basic.clj │ │ │ │ ├── map.clj │ │ │ │ └── tx_fn.clj │ │ │ └── validation.clj │ │ └── utils │ │ │ ├── completable_future.clj │ │ │ └── spec.clj │ │ └── value_types.clj └── test │ └── eva │ ├── admin │ └── alpha │ │ ├── api_test.clj │ │ └── cli_test.clj │ ├── api_test.clj │ ├── byte_string_test.clj │ ├── contextual │ ├── aspects_test.clj │ ├── config_test.clj │ └── usage_examples.clj │ ├── datastructures │ └── versioning_test.clj │ ├── datom_test.clj │ ├── entity_id_test.clj │ ├── entity_test.clj │ ├── error_test.clj │ ├── functions_test.clj │ ├── gen_test_scaffold.clj │ ├── gen_tests.clj │ ├── load_tests.clj │ ├── metrics_test.clj │ ├── quartermaster_patches.clj │ ├── query │ ├── datalog │ │ ├── predicate_tests.clj │ │ ├── program_tests.clj │ │ ├── qsqr │ │ │ ├── core_tests.clj │ │ │ └── state_tests.clj │ │ └── rule_tests.clj │ ├── exceptions_test.clj │ ├── pull_test.clj │ └── query_test.clj │ ├── test │ ├── chaos_utils.clj │ ├── chaos_utils_test.clj │ └── clojure_test_ext.clj │ ├── transaction │ └── map_expansion_test.clj │ ├── transaction_pipeline │ ├── errors_test.clj │ ├── lookup_refs_test.clj │ ├── resolve_ids_test.clj │ └── tx_inst_test.clj │ ├── transaction_test.clj │ ├── utils │ └── delay_queue_test.clj │ └── v2 │ ├── api_test.clj │ ├── datastructures │ ├── atom_test.clj │ ├── bbtree_test.clj │ ├── var_test.clj │ └── vector_test.clj │ ├── messaging │ ├── jms │ │ ├── activemq_and_artemis_interop.clj │ │ ├── alpha │ │ │ ├── local_broker.clj │ │ │ └── message_test.clj │ │ └── beta │ │ │ ├── core_test.clj │ │ │ └── patterns_test.clj │ └── node │ │ └── alpha_beta_interop_test.clj │ ├── server │ └── transactor_test_utils.clj │ ├── storage │ ├── chunk_callback_outstream_test.clj │ ├── core_test.clj │ ├── ddb_test.clj │ ├── testing_utils.clj │ └── value_store_test.clj │ └── system │ ├── integration_test.clj │ └── peer_connection_test.clj ├── dev ├── integration-testing │ └── mariadb │ │ └── start-test-database.sh ├── java-src │ └── eva │ │ └── dev │ │ └── logback │ │ └── PrintAppender.java ├── resources │ └── logback.xml ├── src │ └── eva │ │ ├── datastructures │ │ └── test_version │ │ │ ├── api.clj │ │ │ ├── fressian.clj │ │ │ └── logic │ │ │ ├── balance.clj │ │ │ ├── buffer.clj │ │ │ ├── core.clj │ │ │ ├── error.clj │ │ │ ├── message.clj │ │ │ ├── missing_versioning.clj │ │ │ ├── nodes.clj │ │ │ ├── operations.clj │ │ │ ├── protocols.clj │ │ │ ├── query.clj │ │ │ ├── state.clj │ │ │ ├── storage.clj │ │ │ ├── tree.clj │ │ │ ├── types.clj │ │ │ └── versioning.clj │ │ └── dev │ │ ├── logback │ │ ├── init_sqlite.clj │ │ └── print_appender.clj │ │ ├── repl.clj │ │ └── tasks │ │ ├── errorcode_generation.clj │ │ └── release_trigger.clj └── test │ └── eva │ └── dev │ └── errorcode_generation_test.clj ├── docker ├── catalog_config.edn ├── docker-compose.override.yml ├── docker-compose.repl.yml ├── docker-compose.skynet.override.yml ├── docker-compose.transactor.yml ├── docker-compose.yml └── eva-db │ ├── Dockerfile │ └── init.sql ├── docs ├── api │ ├── clojure │ │ ├── css │ │ │ └── default.css │ │ ├── eva.api.html │ │ ├── highlight │ │ │ ├── highlight.min.js │ │ │ └── solarized-light.css │ │ ├── index.html │ │ └── js │ │ │ ├── jquery.min.js │ │ │ └── page_effects.js │ ├── eva_config_properties.md │ └── java │ │ ├── allclasses-frame.html │ │ ├── allclasses-noframe.html │ │ ├── constant-values.html │ │ ├── deprecated-list.html │ │ ├── eva │ │ ├── Attribute.html │ │ ├── Connection.html │ │ ├── Database.html │ │ ├── Datom.html │ │ ├── Entity.html │ │ ├── Id.html │ │ ├── Log.html │ │ ├── Peer.html │ │ ├── Util.html │ │ ├── error │ │ │ └── v1 │ │ │ │ ├── EvaErrorCode.html │ │ │ │ ├── EvaException.html │ │ │ │ ├── ICodedExceptionInfo.html │ │ │ │ ├── IErrorCode.html │ │ │ │ ├── package-frame.html │ │ │ │ ├── package-summary.html │ │ │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── help-doc.html │ │ ├── index-all.html │ │ ├── index.html │ │ ├── overview-frame.html │ │ ├── overview-summary.html │ │ ├── overview-tree.html │ │ ├── package-list │ │ ├── script.js │ │ ├── serialized-form.html │ │ └── stylesheet.css ├── attr-based-modelling │ ├── design.md │ └── plantuml-src │ │ ├── classes-simple.png │ │ ├── classes-simple.puml │ │ ├── classes.png │ │ └── classes.puml ├── clause-order-matters-pt2.md ├── database-state-and-time.md ├── differences.md ├── eva-exception.md ├── eva_101.md ├── eva_102.md ├── images │ └── logo │ │ ├── EVA-Logo-InkScape.svg │ │ └── EVA-Logo.svg ├── last-modified-in-eva.md ├── local-v2-h2.md ├── query-order-matters.md ├── query-rules.md └── technical-faq.md ├── package.json ├── project.clj ├── scripts ├── ci │ ├── pull_composes.sh │ └── workiva-build.sh └── image │ ├── run_service.sh │ └── set_mem_constraints.sh ├── server ├── java-src │ └── eva │ │ └── Server.java ├── src │ ├── eva │ │ └── server │ │ │ ├── v1 │ │ │ └── http_status_endpoint.clj │ │ │ ├── v2.clj │ │ │ └── v2 │ │ │ ├── config.clj │ │ │ └── config_monitor │ │ │ └── alpha.clj │ └── resources │ │ └── logback.xml ├── test-resources │ └── eva │ │ └── server │ │ └── v2 │ │ ├── catalog_config.edn │ │ ├── local.xml │ │ └── local_transactors_test_config.clj └── tests │ └── v2 │ └── startup_test.clj ├── skynet.yaml ├── third-party └── fabric8io-images.java.LICENSE ├── transactor.Dockerfile └── workivabuild.Dockerfile /.circleci/clojars/profiles.clj: -------------------------------------------------------------------------------- 1 | {:auth 2 | {:repository-auth 3 | {#"clojars" 4 | {:username #=(eval (System/getenv "CLOJARS_USER")) 5 | :password #=(eval (System/getenv "CLOJARS_PASS"))}}}} 6 | -------------------------------------------------------------------------------- /.circleci/scripts/update-tocs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Updates table of contents in all relevant readmes 3 | # Requires markdown-toc 4 | MAX_DEPTH=4 5 | 6 | # Parent README 7 | npx markdown-toc -i README.md --maxdepth $MAX_DEPTH 8 | -------------------------------------------------------------------------------- /.circleci/scripts/verify-dockerfile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Checks if either the `docker build ...` command exited with '0' or 4 | # if the dockerfile ends with FROM scratch, no image will be generated which 5 | # causes exit code '1', however this is a valid condition from our perspective. 6 | 7 | COLOR_NC='\e[0m' 8 | COLOR_GREEN='\e[0;32m' 9 | COLOR_RED='\e[0;31m' 10 | 11 | docker build -f workivabuild.Dockerfile . 2>&1 | tee workivabuild.Dockerfile.output 12 | 13 | finalLine=$(awk '/./{line=$0} END{print line}' workivabuild.Dockerfile.output) 14 | 15 | regex="Successfully built*" 16 | if [[ "$finalLine" == $regex ]]; then 17 | printf "${COLOR_GREEN}Dockerfile built successfully${COLOR_NC}" 18 | rm workivabuild.Dockerfile.output 19 | exit 0 20 | fi 21 | 22 | if [[ "$finalLine" == "No image was generated. Is your Dockerfile empty?" ]]; then 23 | printf "${COLOR_GREEN}Dockerfile built successfully${COLOR_NC}" 24 | rm workivabuild.Dockerfile.output 25 | exit 0 26 | fi 27 | 28 | printf "${COLOR_RED}Dockerfile built successfully${COLOR_NC}" 29 | rm workivabuild.Dockerfile.output 30 | exit 1 31 | -------------------------------------------------------------------------------- /.circleci/scripts/verify-docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Verifies that docs have been generated and updated 3 | GREEN='\e[0;32m' 4 | RED='\033[0;31m' 5 | NC='\033[0m' # No Color 6 | 7 | md5Command=md5sum 8 | if [ $(uname -s) == "Darwin" ]; then 9 | md5Command=(md5 -q) 10 | fi 11 | 12 | # Store MD5 of Committed Documentation 13 | MD5_ROOT_README_BEFORE=$(find README.md -type f -exec $md5Command {} \; | sort -k 2 | $md5Command) 14 | MD5_CLOJURE_DOCS_BEFORE=$(find ./docs/api/clojure -type f -exec $md5Command {} \; | sort -k 2 | $md5Command) 15 | MD5_JAVA_DOCS_BEFORE=$(find ./docs/api/java -type f -exec $md5Command {} \; | sort -k 2 | $md5Command) 16 | 17 | # Update Table of Contents 18 | ./.circleci/scripts/update-tocs.sh 19 | # Update Codox documentation 20 | lein docs 21 | 22 | # Calculate Later 23 | MD5_ROOT_README_AFTER=$(find README.md -type f -exec $md5Command {} \; | sort -k 2 | $md5Command) 24 | MD5_CLOJURE_DOCS_AFTER=$(find ./docs/api/clojure -type f -exec $md5Command {} \; | sort -k 2 | $md5Command) 25 | MD5_JAVA_DOCS_AFTER=$(find ./docs/api/java -type f -exec $md5Command {} \; | sort -k 2 | $md5Command) 26 | 27 | # Verify root README.md 28 | if [ "$MD5_ROOT_README_BEFORE" != "$MD5_ROOT_README_AFTER" ]; then 29 | printf "${RED}Aborting, parent README file TOC was not updated${NC}\n" 30 | printf "${RED}Run make update-tocs${NC}\n" 31 | exit 1 32 | fi 33 | 34 | # Verify ./docs/api content 35 | if [ "$MD5_CLOJURE_DOCS_BEFORE" != "$MD5_CLOJURE_DOCS_AFTER" ] || [ "$MD5_JAVA_DOCS_BEFORE" != "$MD5_JAVA_DOCS_AFTER" ]; then 36 | printf "${RED}Aborting, ./docs/api was not updated${NC}\n" 37 | printf "${RED}Run lein docs${NC}\n" 38 | exit 1 39 | fi 40 | 41 | printf "${GREEN}Documentation verified successfully${NC}\n" 42 | -------------------------------------------------------------------------------- /.circleci/scripts/verify-license-headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Verifies if the license headers are present in source-code files identified by extension 4 | # Grabs the first line of every discovered file and checks it against the provided regex 5 | 6 | # Parameter Listing: 7 | # extension to search for 8 | # regex 9 | # file-names to exclude 10 | 11 | COLOR_NC='\e[0m' 12 | COLOR_GREEN='\e[0;32m' 13 | COLOR_CYAN='\e[0;36m' 14 | COLOR_RED='\e[0;31m' 15 | COLOR_YELLOW='\e[1;33m' 16 | 17 | EXTENSION=$1 18 | REGEX=$2 19 | EXCLUDE_LIST=( "$@" ) 20 | # Remove First Two Arguments 21 | EXCLUDE_LIST=( ${EXCLUDE_LIST[@]:2} ) 22 | 23 | printf $COLOR_CYAN 24 | printf "Extension - $EXTENSION\n" 25 | printf "REGEX - $REGEX\n" 26 | printf "EXCLUDE LIST - ${EXCLUDE_LIST[*]}\n\n" 27 | printf "$COLOR_NC\n" 28 | 29 | missingHeader=false 30 | for file in $(find . -name "*.$EXTENSION"); do 31 | # Check to see if we should exclude this file 32 | skipFile=false 33 | for excludeFile in "${EXCLUDE_LIST[@]}"; do 34 | if [[ $file == *"$excludeFile"* ]]; then 35 | printf "${COLOR_YELLOW}Skipping - ${file}${COLOR_NC}\n" 36 | skipFile=true 37 | fi 38 | done 39 | # Check the file headers 40 | if [[ "$skipFile" == false ]]; then 41 | headLine=$(head -n 1 $file) 42 | if ! [[ "$headLine" =~ $REGEX ]]; then 43 | printf "${COLOR_RED}\"${file}\" does not contain the proper licensing header!${COLOR_NC}\n" 44 | missingHeader=true 45 | fi 46 | fi 47 | done 48 | 49 | if [[ $missingHeader == false ]]; then 50 | printf "\n${COLOR_GREEN}All non-excluded *.${EXTENSION} files contained the licensing header.${COLOR_NC}\n" 51 | exit 0 52 | else 53 | exit 1 54 | fi 55 | -------------------------------------------------------------------------------- /.clj-kondo/config.edn: -------------------------------------------------------------------------------- 1 | {:lint-as {morphe.core/defn clojure.core/defn 2 | quartermaster.core/defmanager clojure.core/def 3 | potemkin/def-map-type clojure.core/deftype 4 | plumbing.core/for-map clojure.core/for}} 5 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | 1. Branch and PR to master 4 | 2. Maintiners / Previous Contributors will Review 5 | 6 | # Guidelines 7 | 8 | - Good style - https://github.com/bbatsov/clojure-style-guide 9 | - Descriptive commit messages - https://chris.beams.io/posts/git-commit/ 10 | - Tests where appropriate 11 | 12 | # Active Maintainers 13 | 14 | - Erik Petersen 15 | 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Expected Behavior 2 | 3 | 4 | ## Actual Behavior 5 | 6 | 7 | ## Steps to Reproduce the Problem 8 | 9 | 1. 10 | 2. 11 | 3. 12 | 13 | ## Specifications 14 | 15 | - Version: 16 | - Platform: 17 | - Subsystem: 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description of Changes 2 | 3 | - 4 | 5 | ## Proposed Testing Steps (If Applicable) 6 | 7 | - 8 | 9 | ## Relevant Issues (If Applicable) 10 | 11 | - 12 | 13 | ## Maintainer Notifications 14 | 15 | - @erikpetersen-wf 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | 4 | # Created by .ignore support plugin (hsz.mobi) 5 | 6 | /target 7 | /classes 8 | /checkouts 9 | pom.xml 10 | pom.xml.asc 11 | *.class 12 | /.lein-* 13 | /.nrepl-port 14 | .hgignore 15 | .hg/ 16 | .classpath 17 | .project 18 | .eastwood 19 | **/target/* 20 | *.iml 21 | .idea 22 | /data 23 | /logs 24 | /api-docs 25 | /internal-api-docs 26 | compose_remote* 27 | .release-trigger 28 | *.lock 29 | .clj-kondo/.cache -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | --------------------------------------------------- 2 | 3 | eva 4 | Copyright (c) 2015-2019 Workiva Inc. All rights reserved. 5 | 6 | The use and distribution terms for this software are covered 7 | by the Eclipse Public License 1.0 (https://www.eclipse.org/legal/epl-v10.html). 8 | By using this software in any fashion, you are agreeing to 9 | be bound by the terms of this license. 10 | 11 | ----------------------------------------------------------------------------- 12 | 13 | This program uses implementation from Clojure which is distributed under the 14 | Eclipse Public License (EPLv1.0) at https://github.com/clojure/clojure with the 15 | following notice: 16 | 17 | Copyright (c) Rich Hickey. All rights reserved. 18 | The use and distribution terms for this software are covered by the 19 | Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 20 | which can be found in the file epl-v10.html in the 'third-party' folder of 21 | this distribution. 22 | By using this software in any fashion, you are agreeing to be bound by 23 | the terms of this license. 24 | You must not remove this notice, or any other, from this software. 25 | 26 | ----------------------------------------------------------------------------- 27 | 28 | This program uses implementation from Datascript which is distributed under the 29 | Eclipse Public License (EPLv1.0) at https://github.com/tonsky/datascript with 30 | the following notice: 31 | 32 | Copyright © 2014–2018 Nikita Prokopov 33 | 34 | Licensed under Eclipse Public License 35 | 36 | ----------------------------------------------------------------------------- 37 | 38 | This program uses implementation from again which is distributed under the 39 | Eclipse Public License (EPLv1.0) at https://github.com/liwp/again with the 40 | following notice: 41 | 42 | Copyright © 2014–2017 Listora, Lauri Pesonen 43 | 44 | Distributed under the Eclipse Public License either version 1.0 or(at your 45 | option) any later version. 46 | 47 | ----------------------------------------------------------------------------- 48 | 49 | This program uses scripts from fabric8io-images/java which is 50 | distributed under the Apache 2.0 license. 51 | 52 | fabric8io-images/java 53 | Copyright 2009-2010 Roland Huss 54 | 55 | The included license can be found here: 56 | https://github.com/fabric8io-images/java/blob/master/LICENSE 57 | 58 | ----------------------------------------------------------------------------- 59 | -------------------------------------------------------------------------------- /LICENSE-3RD-PARTY.txt: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | This program uses implementation from Clojure which is distributed under the 3 | Eclipse Public License (EPLv1.0) at https://github.com/clojure/clojure with the 4 | following notice: 5 | 6 | Copyright (c) Rich Hickey. All rights reserved. 7 | The use and distribution terms for this software are covered by the 8 | Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 9 | which can be found in the file epl-v10.html in the 'third-party' folder of 10 | this distribution. 11 | By using this software in any fashion, you are agreeing to be bound by 12 | the terms of this license. 13 | You must not remove this notice, or any other, from this software. 14 | 15 | ----------------------------------------------------------------------------- 16 | This program uses implementation from Datascript which is distributed under the 17 | Eclipse Public License (EPLv1.0) at https://github.com/tonsky/datascript with 18 | the following notice: 19 | 20 | Copyright © 2014–2018 Nikita Prokopov 21 | 22 | Licensed under Eclipse Public License 23 | 24 | ----------------------------------------------------------------------------- 25 | This program uses implementation from again which is distributed under the 26 | Eclipse Public License (EPLv1.0) at https://github.com/liwp/again with the 27 | following notice: 28 | 29 | Copyright © 2014–2017 Listora, Lauri Pesonen 30 | 31 | Distributed under the Eclipse Public License either version 1.0 or(at your 32 | option) any later version. 33 | 34 | ----------------------------------------------------------------------------- 35 | This program uses scripts from fabric8io-images/java which is 36 | distributed under the Apache 2.0 license. 37 | 38 | fabric8io-images/java 39 | Copyright 2009-2010 Roland Huss 40 | 41 | The included license can be found here: 42 | https://github.com/fabric8io-images/java/blob/master/LICENSE 43 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | gen-docker: 2 | docker build \ 3 | -f workivabuild.Dockerfile \ 4 | -t workivadocker/eva . 5 | 6 | gen-docker-no-tests: 7 | docker build \ 8 | --build-arg SKIP_TESTS=true \ 9 | -f workivabuild.Dockerfile \ 10 | -t workivadocker/eva . 11 | 12 | run-docker: 13 | ./scripts/ci/pull_composes.sh 14 | docker-compose -f docker/docker-compose.yml \ 15 | -f compose_remote/local-compose-eva-catalog.yml \ 16 | -f docker/docker-compose.override.yml up -d 17 | 18 | stop-docker: 19 | docker-compose -f docker/docker-compose.yml \ 20 | -f compose_remote/local-compose-eva-catalog.yml \ 21 | -f docker/docker-compose.override.yml down 22 | 23 | docker-logs: 24 | docker-compose -f docker-compose.yml \ 25 | -f compose_remote/local-compose-eva-catalog.yml \ 26 | -f docker/docker-compose.override.yml logs 27 | 28 | repl: run-docker ## Starts a Clojure REPL in the docker network 29 | docker-compose -f docker/docker-compose.repl.yml run --rm lein with-profile +dev repl 30 | 31 | transactor-docker: 32 | docker-compose -f docker/docker-compose.transactor.yml run --rm lein with-profile +dev repl 33 | 34 | update-tocs: 35 | ./.circleci/scripts/update-tocs.sh 36 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | eva 2 | Copyright 2015-2019 Workiva Inc. 3 | 4 | Licensed under the Eclipse Public License 1.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://opensource.org/licenses/eclipse-1.0.php 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /aviary.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | exclude: 4 | - tests?/ 5 | - testing/ 6 | - test-resources/ 7 | 8 | raven_monitored_classes: 9 | 10 | raven_monitored_files: 11 | 12 | raven_monitored_functions: 13 | 14 | raven_monitored_keywords: 15 | -------------------------------------------------------------------------------- /core/java-src/eva/Alpha.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | import clojure.java.api.Clojure; 18 | import clojure.lang.IFn; 19 | import com.codahale.metrics.MetricRegistry; 20 | 21 | import java.util.concurrent.ExecutionException; 22 | import java.util.Map; 23 | 24 | // We make no promises about the contract, stability, or lifetime of functions 25 | // provided in this namespace 26 | 27 | public final class Alpha { 28 | 29 | private static IFn require = Clojure.var("clojure.core", "require"); 30 | 31 | static { 32 | require.invoke(Clojure.read("eva.alpha")); 33 | } 34 | 35 | public static Map getTransactionExceptionData(ExecutionException e){ 36 | IFn getData = Clojure.var("eva.alpha", "to-ex-data"); 37 | return (Map) getData.invoke(e); 38 | } 39 | 40 | public static String getTransactionExceptionCause(ExecutionException e){ 41 | IFn getCause = Clojure.var("eva.alpha", "to-ex-cause"); 42 | return (String) getCause.invoke(e); 43 | } 44 | 45 | public static MetricRegistry internalMetricRegistry() { 46 | require.invoke(Clojure.read("eva.api")); 47 | require.invoke(Clojure.read("barometer.core")); 48 | IFn defaultRegistry = Clojure.var("barometer.core", "default-registry"); 49 | return (MetricRegistry) defaultRegistry.invoke(); 50 | } 51 | 52 | @SuppressWarnings("unchecked") 53 | public static Map txResultToEntityIDTempIDMap (Map txResult){ 54 | require.invoke(Clojure.read("eva.api")); 55 | IFn entityObjects = Clojure.var("eva.alpha", "tx-result->EntityID-tempids"); 56 | return (Map) entityObjects.invoke(txResult); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /core/java-src/eva/ByteStringInputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.nio.ByteBuffer; 21 | 22 | /** 23 | * InputStream implementation that reads bytes from an immutable ByteString 24 | */ 25 | public final class ByteStringInputStream extends InputStream { 26 | ByteBuffer buf; 27 | 28 | public ByteStringInputStream(ByteString b) { 29 | this.buf = b.toByteBuffer(); 30 | } 31 | 32 | @Override 33 | public int read() throws IOException { 34 | if(!buf.hasRemaining()) { 35 | return -1; 36 | } 37 | return buf.get() & 0xFF; 38 | } 39 | 40 | @Override 41 | public int read(byte[] bytes, int off, int len) throws IOException { 42 | if(!buf.hasRemaining()) { 43 | return -1; 44 | } 45 | len = Math.min(len, buf.remaining()); 46 | buf.get(bytes, off, len); 47 | return len; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /core/java-src/eva/ByteStringOutputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | 18 | import java.io.ByteArrayOutputStream; 19 | import java.io.IOException; 20 | import java.io.OutputStream; 21 | 22 | /** 23 | * OutputStream implementation that collects written bytes into an immutable ByteString 24 | */ 25 | public final class ByteStringOutputStream extends OutputStream { 26 | ByteArrayOutputStream bout; 27 | 28 | public ByteStringOutputStream() { 29 | this.bout = new ByteArrayOutputStream(2048); 30 | } 31 | 32 | @Override 33 | public void write(int b) throws IOException { 34 | bout.write(b); 35 | } 36 | 37 | @Override 38 | public void write(byte[] bytes, int off, int len) throws IOException { 39 | bout.write(bytes, off, len); 40 | } 41 | 42 | /** 43 | * @return an immutable ByteString containing the bytes written 44 | */ 45 | public ByteString toByteString() { 46 | return ByteString.wrapping(this.bout.toByteArray()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/java-src/eva/Datom.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | public interface Datom { 18 | /** 19 | * Datom's entity-id. 20 | */ 21 | Object e(); 22 | 23 | /** 24 | * Datom's attribute-id. 25 | */ 26 | Object a(); 27 | 28 | /** 29 | * Datom's value. 30 | */ 31 | Object v(); 32 | 33 | /** 34 | * Datom's transaction number. 35 | */ 36 | Object tx(); 37 | 38 | /** 39 | * Indicates if the datom was added or retracted. 40 | * 41 | * @return boolean indicating the datom was added or retracted 42 | */ 43 | Object added(); 44 | 45 | /** 46 | * Positional getter; treats the datom as a tuple of: [e a v tx added]. 47 | * 48 | * @param index numeric index of [0, 1 ,2 ,3, 4] 49 | * @return value at the position in the datom 50 | */ 51 | Object getIndex(int index); 52 | 53 | /** 54 | * Associative getter; treats datom as a map with keys: [:e, :a, :v, :tx, :added]. 55 | * 56 | * @param key key of the field to access 57 | * @return value at the field mapped to the key 58 | */ 59 | Object getKey(Object key); 60 | } 61 | -------------------------------------------------------------------------------- /core/java-src/eva/Entity.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | import java.util.Set; 18 | 19 | /** 20 | * Provides Entity/Object-oriented access to database-entities. 21 | * Entities are lazy: value of attributes are retrieved on-demand when 22 | * {@link #get(Object)} or {@link #touch()} are called. 23 | * After retrieval attribute-values are cached inside the entity. 24 | * 25 | *

Entities are equal if they have the same entity-id and equivalent databases. 26 | */ 27 | public interface Entity { 28 | 29 | /** 30 | * Return the database value that backs this entity. 31 | */ 32 | Database db(); 33 | 34 | /** 35 | * Get the value of the attribute named by k. 36 | * 37 | * @param k keyword or colon-prefixed string (ie. ":person/name") 38 | * @return value(s) of that attribute, or null if none 39 | */ 40 | Object get(Object k); 41 | 42 | /** 43 | * Return the key names of the attributes. 44 | */ 45 | Set keySet(); 46 | 47 | /** 48 | * Loads all attributes of the entity, recursively touching any component entities. 49 | * 50 | * @return the {@link Entity} 51 | */ 52 | Entity touch(); 53 | } 54 | -------------------------------------------------------------------------------- /core/java-src/eva/Id.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | /** 18 | * Marker Interface for Ids. 19 | */ 20 | public interface Id {} 21 | -------------------------------------------------------------------------------- /core/java-src/eva/Log.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | import java.util.Map; 18 | 19 | /** 20 | * Interface to the transaction log. 21 | */ 22 | public interface Log { 23 | /** 24 | * Given a {@link Log} object and a start and end 'transaction number' or 'id', return all 25 | * applicable datoms that were asserted or retracted in the database. 26 | * 27 | * @param startT Start transaction number 28 | * @param endT Ending transaction number 29 | * @return All datoms that were asserted or retracted between startT and endT 30 | */ 31 | Iterable txRange(Object startT, Object endT); 32 | } 33 | -------------------------------------------------------------------------------- /core/java-src/eva/error/v1/ICodedExceptionInfo.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva.error.v1; 16 | 17 | import clojure.lang.IExceptionInfo; 18 | 19 | public interface ICodedExceptionInfo extends IExceptionInfo { 20 | E getErrorCode(); 21 | default boolean hasErrorCode(E code) { 22 | return (getErrorCode().is(code)); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /core/java-src/eva/error/v1/IErrorCode.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva.error.v1; 16 | 17 | import clojure.lang.Keyword; 18 | 19 | public interface IErrorCode { 20 | /** 21 | * Is this an unknown (unspecified) error code? 22 | */ 23 | default boolean isUnspecified() { 24 | return false; 25 | } 26 | 27 | /** 28 | * Returns a long uniquely representing this ErrorCode. 29 | */ 30 | long getCode(); 31 | 32 | /** 33 | * Return an HTTP error code as a long appropriate to this ErrorCode 34 | */ 35 | long getHttpErrorCode(); 36 | String getScope(); 37 | 38 | /** 39 | * Return the name of this ErrorCode as a String 40 | */ 41 | String getName(); 42 | 43 | /** 44 | * Return a description of this error code as a Clojure keyword. 45 | */ 46 | Keyword getKey(); 47 | 48 | /** 49 | * Get an explanation (the message) of the error. 50 | */ 51 | String getExplanation(); 52 | 53 | /** 54 | * Use to compare two error codes. 55 | * 56 | * @param e Another error code for comparison 57 | * @return True if the error codes are the same, or if the parent of this error code is {@code e}. 58 | */ 59 | boolean is(IErrorCode e); 60 | } 61 | -------------------------------------------------------------------------------- /core/java-src/eva/error/v1/SanitizedEvaException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva.error.v1; 16 | 17 | import recide.sanex.ISanitized; 18 | import java.lang.Throwable; 19 | import java.lang.StackTraceElement; 20 | import clojure.lang.IPersistentMap; 21 | 22 | public class SanitizedEvaException extends EvaException implements ISanitized { 23 | private final EvaException unsuppressed; 24 | private final IPersistentMap suppressedData; 25 | private final Throwable suppressedCause; 26 | private final StackTraceElement[] suppressedStack; 27 | private final String suppressedMessage; 28 | 29 | public SanitizedEvaException(EvaException original, 30 | IPersistentMap data, 31 | Throwable cause, 32 | StackTraceElement[] stack, 33 | String message) { 34 | super(original.getErrorCode(), message, data, cause); 35 | this.unsuppressed = original; 36 | this.suppressedData = data; 37 | this.suppressedCause = cause; 38 | this.suppressedStack = stack; 39 | this.suppressedMessage = message; 40 | } 41 | 42 | public ISanitized getSanitized(IPersistentMap suppression) { 43 | return unsuppressed.getSanitized(suppression); 44 | } 45 | 46 | @Override 47 | public Throwable getUnsanitized() { 48 | return unsuppressed; 49 | } 50 | 51 | @Override 52 | public Throwable getCause() { 53 | return suppressedCause; 54 | } 55 | 56 | @Override 57 | public StackTraceElement[] getStackTrace() { 58 | return suppressedStack; 59 | } 60 | 61 | @Override 62 | public String getMessage() { 63 | return suppressedMessage; 64 | } 65 | 66 | @Override 67 | public IPersistentMap getData() { 68 | return suppressedData; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "eva.error.v2.SuppressedEvaException: " 74 | + this.getMessage() 75 | + " " 76 | + this.getData(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /core/java-src/eva/storage/ChunkCallbackOutputStream.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva.storage; 16 | 17 | import clojure.lang.IFn; 18 | 19 | import java.io.IOException; 20 | import java.io.OutputStream; 21 | import java.nio.ByteBuffer; 22 | 23 | public class ChunkCallbackOutputStream extends OutputStream { 24 | 25 | private final ByteBuffer buffer; 26 | private final IFn chunkCallback; 27 | private final IFn closedCallback; 28 | private boolean closed; 29 | 30 | public ChunkCallbackOutputStream(int chunkSize, IFn chunkCallback, IFn closedCallback) { 31 | this.buffer = ByteBuffer.allocate(chunkSize); 32 | this.chunkCallback = chunkCallback; 33 | this.closedCallback = closedCallback; 34 | this.closed = false; 35 | } 36 | 37 | @Override 38 | public synchronized void write(int b) throws IOException { 39 | if(closed) { 40 | throw new IllegalStateException(String.format("output stream is closed: %s", this)); 41 | } 42 | if(!buffer.hasRemaining()) { 43 | flush(); 44 | } 45 | buffer.put((byte) b); 46 | } 47 | 48 | private void _flush() { 49 | if(!closed && buffer.position() > 0) { 50 | buffer.flip(); 51 | byte[] ba = new byte[buffer.limit()]; 52 | buffer.get(ba); 53 | this.chunkCallback.invoke(ba); 54 | } 55 | buffer.clear(); 56 | } 57 | 58 | @Override 59 | public synchronized void flush() { 60 | _flush(); 61 | } 62 | 63 | @Override 64 | public synchronized void close() { 65 | flush(); 66 | this.closedCallback.invoke(); 67 | closed = true; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /core/resources/data_readers.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | {db/id eva.readers/read-db-id 16 | db/fn eva.readers/read-db-fn} 17 | -------------------------------------------------------------------------------- /core/resources/eva/storage/sql/h2/h2-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS 2 | eva_kv( 3 | namespace varchar(128), 4 | id varchar(128), 5 | attrs varchar(600), 6 | val blob, 7 | primary key (namespace, id) 8 | ); 9 | -------------------------------------------------------------------------------- /core/resources/eva/storage/sql/mariadb/mariadb-db.sql: -------------------------------------------------------------------------------- 1 | -- Database: eva 2 | 3 | -- DROP DATABASE eva; 4 | 5 | CREATE DATABASE eva; 6 | -------------------------------------------------------------------------------- /core/resources/eva/storage/sql/mariadb/mariadb-table.sql: -------------------------------------------------------------------------------- 1 | -- Table: eva_kv; 2 | 3 | -- DROP TABLE eva_kv; 4 | 5 | CREATE TABLE eva_kv ( 6 | namespace varchar(640) NOT NULL, 7 | id varchar(640) NOT NULL, 8 | attrs text, 9 | val longblob, 10 | CONSTRAINT pk_ns_id PRIMARY KEY (namespace, id) 11 | ) 12 | ENGINE=INNODB 13 | -------------------------------------------------------------------------------- /core/resources/eva/storage/sql/postgres/postgres-db.sql: -------------------------------------------------------------------------------- 1 | -- Database: eva 2 | 3 | -- DROP DATABASE eva; 4 | 5 | CREATE DATABASE eva 6 | WITH OWNER = postgres 7 | ENCODING = 'UTF8' 8 | TABLESPACE = pg_default 9 | LC_COLLATE = 'en_US.utf8' 10 | LC_CTYPE = 'en_US.utf8' 11 | CONNECTION LIMIT = -1; 12 | 13 | -------------------------------------------------------------------------------- /core/resources/eva/storage/sql/postgres/postgres-table.sql: -------------------------------------------------------------------------------- 1 | -- Table: eva_kv 2 | 3 | -- DROP TABLE eva_kv; 4 | 5 | CREATE TABLE eva_kv 6 | ( 7 | namespace TEXT NOT NULL, 8 | id TEXT NOT NULL, 9 | attrs TEXT, 10 | val BYTEA, 11 | CONSTRAINT pk_ns_id PRIMARY KEY (namespace, id) 12 | ) 13 | WITH ( 14 | OIDS=FALSE 15 | ); 16 | -------------------------------------------------------------------------------- /core/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /core/src/eva/admin/alpha/cli.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.admin.alpha.cli 16 | "Entry point for Eva Administrative CLI tooling" 17 | (:require [eva.admin.alpha.api :as admin-api] 18 | [clojure.edn :as edn]) 19 | (:import [java.util UUID])) 20 | 21 | (defmulti run-command (fn [cmd-str & params] cmd-str)) 22 | 23 | (defn parse-config [config] 24 | (-> config edn/read-string)) 25 | 26 | (defmethod run-command "simple-migration" 27 | [_ [source destination database-id]] 28 | (let [id (UUID/fromString database-id) 29 | src (parse-config source) 30 | dst (parse-config destination)] 31 | (admin-api/stateful-migration! src dst id))) 32 | 33 | (defn -main [& args] 34 | ;; TODO: Integrate with clojure.tools.cli for parsing. 35 | (let [[cmd & params] args] 36 | (run-command cmd params))) 37 | -------------------------------------------------------------------------------- /core/src/eva/alpha.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.alpha 16 | (:require [eva.entity-id :as e] 17 | [utiliva.core :as uc] 18 | [map-experiments.smart-maps.protocol :as smart-maps])) 19 | 20 | (defn to-ex-data 21 | "(alpha) 22 | 23 | Given a j.u.c.ExecutionException thrown in transact as the result of 24 | a thrown IExceptionInfo inside a transaction function, extract the ex-data included 25 | within the user-defined IExceptionInfo." 26 | [juce] 27 | (-> juce .getCause .getData :exception eva.Util/read :data)) 28 | 29 | (defn to-ex-cause 30 | "(alpha) 31 | 32 | Given a j.u.c.ExecutionException thrown in transact as the result of 33 | a thrown IExceptionInfo inside a transaction function, extract the cause message 34 | included within the user-defined IExceptionInfo." 35 | [juce] 36 | (-> juce .getCause .getData :exception eva.Util/read :cause)) 37 | 38 | (defn integer->tempid [db tempid] 39 | (let [n (e/n tempid) 40 | part-id->part-key (-> db :parts smart-maps/inverse) 41 | part (-> (e/partition tempid) part-id->part-key)] 42 | (e/tempid part (- n)))) 43 | 44 | (defn tx-result->EntityID-tempids [{:as tx-result :keys [tempids db-after]}] 45 | (into {} (uc/map-keys (partial integer->tempid db-after)) tempids)) 46 | -------------------------------------------------------------------------------- /core/src/eva/api/java/util.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.api.java.util 16 | "Supporting implementation of functions 17 | in eva.Util class" 18 | (:refer-clojure :exclude [read]) 19 | (:require [clojure.edn :as edn] 20 | [eva.entity-id] 21 | [eva.datom] 22 | [clojure.java.io :as io] 23 | [utiliva.core :as uc] 24 | [eva.readers :refer [reader-functions]]) 25 | (:import (java.io Closeable PushbackReader BufferedReader) 26 | (java.util.function Function))) 27 | 28 | (defn Function->IFn [^Function function] 29 | (reify clojure.lang.IFn 30 | (invoke [_ x] (.apply function x)))) 31 | 32 | (defn read 33 | ([s] 34 | (read {} s)) 35 | ([readers s] 36 | (let [symboled-map (into {} (comp (uc/map-keys symbol) 37 | (uc/map-vals Function->IFn)) 38 | readers)] 39 | (edn/read-string {:readers (merge symboled-map reader-functions)} s)))) 40 | 41 | (defn read-seq 42 | "Loads an EDN stream as a lazy sequence. 43 | No operations occur on the Reader until an item of the sequence is accessed." 44 | ([rdr] (read-seq {} rdr)) 45 | ([opts rdr] 46 | (lazy-seq (let [opts (cond-> opts (not (contains? opts :eof)) (assoc :eof ::eof)) 47 | val (edn/read opts rdr)] 48 | (when (not= val (:eof opts)) 49 | (cons val (read-seq opts rdr))))))) 50 | 51 | (defn read-all [source] 52 | (with-open [^Closeable pb-rdr (cond 53 | (instance? PushbackReader source) source 54 | (instance? BufferedReader source) (PushbackReader. source) 55 | :else (PushbackReader. (io/reader source)))] 56 | (doall (read-seq {:readers reader-functions} pb-rdr)))) 57 | -------------------------------------------------------------------------------- /core/src/eva/contextual/config.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.contextual.config 16 | (:require [clojure.spec.alpha :as s]) 17 | (:refer-clojure :exclude [reset!])) 18 | 19 | (s/def ::config-options #{::as-per-config ::override}) 20 | 21 | (def ^:private config (atom {})) 22 | 23 | (defn keep? 24 | [tag option] 25 | (cond 26 | (= ::override option) true ;; do not ignore tag 27 | (= ::as-per-config option) (get @config tag true) ;; not ignored if not configured 28 | :else (throw (IllegalArgumentException. (format "Invalid config option: %s" option))))) 29 | 30 | (s/fdef keep? :args (s/cat :tag keyword? :option ::config-options)) 31 | 32 | (defn set-tag! [tag yes-no] 33 | (swap! config assoc tag yes-no)) 34 | 35 | (defn enable! [tag] 36 | (set-tag! tag true)) 37 | 38 | (defn disable! [tag] 39 | (set-tag! tag false)) 40 | 41 | (defn reset! [] 42 | (clojure.core/reset! config {})) 43 | -------------------------------------------------------------------------------- /core/src/eva/contextual/context.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.contextual.context) 16 | 17 | (defrecord Context [runtime lexical]) 18 | -------------------------------------------------------------------------------- /core/src/eva/contextual/logging.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.contextual.logging 16 | (:require [eva.contextual.utils :as utils])) 17 | 18 | (defn- sorted 19 | [tags] 20 | (into (sorted-map) tags)) 21 | 22 | (defn runtime->str 23 | ([context left-bracket right-bracket] 24 | (let [runtime (:runtime context)] 25 | (if (not-empty runtime) 26 | (str 27 | left-bracket 28 | (utils/params->query-string (sorted runtime)) ;; for now 29 | right-bracket)))) 30 | ([context] 31 | (runtime->str context "" ""))) 32 | 33 | (defn lexical->str 34 | ([context] 35 | (lexical->str context {})) 36 | ([context options] 37 | (let [fn-form (:lexical context) 38 | str (format "%s/%s"(:namespace fn-form) (:fn-name fn-form))] 39 | (if (:params options) 40 | (format "%s%s" str (apply list (:params fn-form))) 41 | str)))) 42 | 43 | (comment 44 | (runtime->str {:runtime {:b "b" :a "a"}}) 45 | (runtime->str {:runtime {:b "b" :a "a"}} "[" "]") 46 | (runtime->str {} "[" "]")) 47 | -------------------------------------------------------------------------------- /core/src/eva/contextual/tags.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.contextual.tags 16 | (:require [clojure.spec.alpha :as s] 17 | [eva.contextual.config :as contextual-config] 18 | [eva.config :as config] 19 | [eva.v2.database.core :as database])) 20 | 21 | (s/def ::database-id string?) 22 | 23 | (defn config->tags [config] 24 | {::database-id (::database/id config)}) 25 | 26 | (defn conn->tags [conn] 27 | (config->tags (:config conn))) 28 | 29 | (defn db->tags [db] 30 | {::database-id (:database-id (:database-info db))}) 31 | 32 | (defn log->tags [log] 33 | (config->tags (-> log :pv .store deref :config))) 34 | 35 | 36 | ;; syncing contextual config 37 | (contextual-config/set-tag! ::database-id (config/config-strict :eva.telemetry.enable-per-db-metrics)) 38 | -------------------------------------------------------------------------------- /core/src/eva/contextual/tracing.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.contextual.tracing) 16 | 17 | (defn ->prefix 18 | [context] 19 | (let [lexical (:lexical context)] 20 | (format "%s/%s" (ns-name (:namespace lexical)) (:fn-name lexical)))) 21 | -------------------------------------------------------------------------------- /core/src/eva/contextual/utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.contextual.utils 16 | (:require [clojure.string :refer [join replace]]) 17 | (:import [java.util.regex Pattern]) 18 | (:refer-clojure :exclude [replace])) 19 | 20 | ;; helpers to sanitize names a bit, so code parsing them could use standard URI parsing tools 21 | (def ^:private replacements 22 | {"?" "_QMARK_" 23 | "!" "_BANG_" 24 | "&" "_AND_" 25 | "=" "_EQ_"}) 26 | 27 | (def ^:private replacement-pattern 28 | (->> (keys replacements) 29 | (map #(Pattern/quote %)) 30 | (interpose "|") 31 | (apply str) 32 | (re-pattern))) 33 | 34 | (defn- clean-name 35 | [name] 36 | (replace name replacement-pattern replacements)) 37 | 38 | ;; Until tags could be submitted to metrics library as hash, they are being 39 | ;; encoded into metric name. Some third-party tool could be used to parse it 40 | ;; and process properly. 41 | (defn params->query-string [m] 42 | (if (not-empty m) 43 | (join "&" (for [[k v] m] (str (clean-name (name k)) "=" (clean-name (str v))))) 44 | nil)) 45 | 46 | (comment 47 | (params->query-string {::a "a" ::b "b"}) 48 | (params->query-string {})) 49 | -------------------------------------------------------------------------------- /core/src/eva/datastructures/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datastructures.error 16 | (:require [eva.error :refer [deferror]])) 17 | 18 | (deferror io-failure 19 | :datastructures/io-failure 20 | "I/O failure occurred in datastructures") 21 | 22 | (deferror concurrent 23 | :datastructures/concurrent-modification 24 | "Probable concurrent modification of datastructure") 25 | 26 | (deferror stale 27 | :datastructures/stale 28 | "Attempt to modify a locally stale datastructure") 29 | 30 | (deferror non-monotonicity 31 | :datastructures/probable-non-montonicity 32 | "Probable non-monotonic modification to datastructure") 33 | -------------------------------------------------------------------------------- /core/src/eva/datastructures/utils/core.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datastructures.utils.core 16 | (:import (java.util Comparator))) 17 | 18 | (defn overlaps? 19 | "Given a comparator and two tuples representing ranges, returns true if the ranges overlap." 20 | [^Comparator cmp [x1 x2] [y1 y2]] 21 | (and (<= (.compare cmp x1 y2) 0) 22 | (<= (.compare cmp y1 x2) 0))) 23 | 24 | (defn arg-cmp 25 | "arg-foo in the spirit of argmin or argmax." 26 | ([cmp f coll] 27 | (arg-cmp cmp f (first coll) (f (first coll)) (next coll))) 28 | ([cmp f x fx coll] 29 | (if coll 30 | (let [fy (f (first coll))] 31 | (if (= -1 (. ^Comparator cmp (compare fy fx))) 32 | (recur cmp f (first coll) fy (next coll)) 33 | (recur cmp f x fx (next coll)))) 34 | x))) 35 | 36 | (defn fast-last [coll] 37 | (let [my-count (count coll)] 38 | (when-not (zero? my-count) 39 | (nth coll (dec my-count))))) 40 | -------------------------------------------------------------------------------- /core/src/eva/datastructures/versioning.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datastructures.versioning 16 | (:require [eva.datastructures.protocols :as dsp] 17 | [recide.sanex :as sanex] 18 | [eva.error :refer [raise insist]])) 19 | 20 | (defmulti version-conversion 21 | "Takes the version to ensure, a node-or-pointer, whatever extra arguments are 22 | necessary to facilitate the conversion in whatever context it is being converted. 23 | It is *unnecessary* to define a method to 'convert' a version to itself. 24 | (defmethod ensure-version 25 | [to-version from-version] 26 | conversion:to-version->from-version ;; name it! 27 | [_ from-version-node-or-pointer & {:as contextual-args}] 28 | (conversion-code-here))" 29 | (fn [version datastructure _] [version (dsp/get-version datastructure)])) 30 | 31 | (defmethod version-conversion 32 | :default 33 | version-conversion:error 34 | [v o _] 35 | (raise :eva.datastructures.versioning/impossible-conversion 36 | (format "Undefined conversion: %s to %s." (dsp/get-version o) v) 37 | {::sanex/sanitary? true})) 38 | 39 | (defn ensure-version 40 | "Takes the version to ensure, a node-or-pointer, 41 | and whatever extra arguments are necessary to facilitate 42 | the conversion. It is unnecessary to define a method to 43 | convert a version to itself. 44 | (defmethod version-conversion 45 | [to-version from-version] 46 | conversion:to-version->from-version ;; name it please! 47 | [_ from-version-node-or-pointer & {:as contextual-args}] 48 | (conversion-code-here))" 49 | [version datastructure & {:as args}] 50 | (insist (satisfies? dsp/Versioned datastructure) 51 | "ensure-version must be called on Versioned objects.") 52 | (let [existing (dsp/get-version datastructure)] 53 | (if (= version existing) 54 | datastructure 55 | (version-conversion version datastructure args)))) 56 | -------------------------------------------------------------------------------- /core/src/eva/db_update.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.db-update 16 | "Higher level api functions for working with databases") 17 | 18 | (defprotocol UpdatableDB 19 | (safe-advance-db [db entry] 20 | "Given a transaction log entry, advances the database to a state where the (already validated) tx has been applied. Requires non-speculative log entries. If the log-entry indicates that the indexes have flushed, will (re)load the database state with the new indexes from the backing store.") 21 | (speculatively-advance-db [db speculative-log-entry] 22 | "Create a new fully-local database snapshot based on a speculative log entry.") 23 | (advance-db* [db entry] 24 | "Update the database state based on the entry. Agnostic to whether or not the log entry is speculative.") 25 | (advance-db-to-tx [db tx-log target-tx-num] 26 | "Given the log and a transaction number advance the database to the target tx.") 27 | (flush-overlay [db tx-num] 28 | "Returns a new db instance with all datoms <= tx-num removed from the overlay.")) 29 | -------------------------------------------------------------------------------- /core/src/eva/defaults.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.defaults 16 | (:require [again.core :as again])) 17 | 18 | (defn default-strategy [retries] 19 | (cons 0 20 | (again/max-retries retries 21 | (again/randomize-strategy 0.5 22 | (again/multiplicative-strategy 10 2))))) 23 | 24 | (def read-index-retry-strategy #(default-strategy 3)) 25 | 26 | (def read-log-range-retry-strategy #(default-strategy 3)) 27 | 28 | (def open-index-retry-strategy #(default-strategy 3)) 29 | 30 | (def init-fill-index-retry-strategy #(default-strategy 3)) 31 | 32 | (def write-tx-log-retry-strategy #(default-strategy 3)) 33 | 34 | (def create-index-retry-strategy #(default-strategy 3)) 35 | -------------------------------------------------------------------------------- /core/src/eva/logging.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.logging 16 | (:import [org.slf4j MDC])) 17 | 18 | (defn with-context* [context f] 19 | (let [context (if (map? context) context (into {} context)) 20 | curr (not-empty (MDC/getCopyOfContextMap))] 21 | (try (doseq [[k v] context 22 | :let [k (if (keyword? k) (name k) (str k))]] 23 | (MDC/put k (str v))) 24 | (f) 25 | (finally 26 | (if curr 27 | (MDC/setContextMap curr) 28 | (MDC/clear)))))) 29 | (defmacro with-context [context & body] `(with-context* ~context (fn [] ~@body))) 30 | -------------------------------------------------------------------------------- /core/src/eva/query/core.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.core 16 | (:require [eva.query.dialect.translation.core :refer [compile]] 17 | [eva.query.trace :as special] 18 | [morphe.core :as d] 19 | [ichnaie.core :refer [traced]]) 20 | (:refer-clojure :exclude [compile])) 21 | 22 | (d/defn ^{::d/aspects [traced]} q 23 | "This executes a query, given a matching set of inputs." 24 | [query & inputs] 25 | (special/trace "QUAESTIO: eva.query/q called.") 26 | (let [query (apply compile query inputs) 27 | _ (special/trace "QUAESTIO: Inspecting query: " ((:inspect query) inputs)) 28 | r (query inputs)] 29 | (special/trace "QUAESTIO: eva/query/q returning.") 30 | r)) 31 | 32 | (defn inspect 33 | "This compiles a query with a matching set of inputs, and returns 34 | a map with :program (the compiled datalog program), :sym->edb 35 | (the map of source symbols to extensional objects), and :init-bindings 36 | (the set of initial bindings seeding the initial datalog query)." 37 | [query & inputs] 38 | ((:inspect (apply compile query inputs)) 39 | inputs)) 40 | -------------------------------------------------------------------------------- /core/src/eva/query/datalog/edb.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.datalog.edb 16 | (:require [eva.query.datalog.protocols :as p] 17 | [eva.query.util :refer [unifies?]] 18 | [clojure.core.unify :as u])) 19 | 20 | (defn coll-of-tuples->EDB 21 | "This is basically just a utility function used to cast regular Clojure data structures 22 | as extensional databases." 23 | [tuples] 24 | (reify p/EDB 25 | (extensions [_ terms] 26 | (for [tuple tuples 27 | :when (some #(unifies? tuple %) terms)] 28 | tuple)))) 29 | -------------------------------------------------------------------------------- /core/src/eva/query/datalog/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.datalog.error 16 | (:require [eva.error :refer :all])) 17 | 18 | (deferror bindings 19 | :query.bindings/insufficient 20 | "Insufficient bindings") 21 | 22 | (deferror evaluable-error 23 | :query.evaluation/function-error 24 | "Error thrown in function during query evaluation") 25 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/aggregates.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.aggregates 16 | "Aggregates usable in the :find specification of queries." 17 | (:require [utiliva.comparator :as cmp] 18 | [eva.query.error :refer [raise-builtin]] 19 | [recide.sanex :as sanex]) 20 | (:refer-clojure :exclude [eval min max rand])) 21 | 22 | (defn min 23 | ([xs] (when-not (empty? xs) (apply (partial cmp/min compare) xs))) 24 | ([n xs] (when-not (empty? xs) (take n (sort xs))))) 25 | 26 | (defn max 27 | ([xs] (when-not (empty? xs) (apply (partial cmp/max compare) xs))) 28 | ([n xs] (when-not (empty? xs) (take n (sort (comp - compare) xs))))) 29 | 30 | (defn rand [n c] (repeatedly n (partial rand-nth (vec c)))) 31 | (defn sample [n c] (->> c distinct shuffle (take n))) 32 | (def count-distinct (comp count distinct)) 33 | (defn sum [c] (when-not (empty? c) 34 | (try (reduce + c) 35 | (catch Throwable t 36 | (raise-builtin :aggregate "sum failed (possibly operating on non-numbers?)" 37 | {:sample-elems (take 4 c), 38 | ::sanex/sanitary? false} 39 | t))))) 40 | (defn avg [c] (when-not (empty? c) 41 | (double (/ (sum c) (count c))))) 42 | 43 | (defn median ;; naive 44 | [c] 45 | (let [c (sort c)] 46 | (if (odd? (count c)) 47 | (nth c (Math/floor (/ (count c) 2.0))) 48 | (avg (take 2 (drop (dec (/ (count c) 2.0)) c)))))) 49 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/pull/ast.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.pull.ast 16 | (:require [eva.query.dialect.util :refer [ASTNode expression]])) 17 | 18 | (defrecord Wildcard [] 19 | ASTNode 20 | (expression [_] '*) 21 | (children [_] nil)) 22 | 23 | (def wildcard-value (->Wildcard)) 24 | 25 | (defrecord Attribute [name] 26 | ASTNode 27 | (expression [_] name) 28 | (children [_] nil)) 29 | 30 | (defrecord LimitExpr [attribute limit] 31 | ASTNode 32 | (expression [_] (list 'limit (expression attribute) limit)) 33 | (children [_] [attribute])) 34 | 35 | (defrecord DefaultExpr [attribute default] 36 | ASTNode 37 | (expression [_] (list 'default (expression attribute) default)) 38 | (children [_] [attribute])) 39 | 40 | (defrecord RecursionLimit [value] 41 | ASTNode 42 | (expression [_] (if (some? value) value '...)) 43 | (children [_] nil)) 44 | 45 | (defrecord MapSpec [entries] 46 | ASTNode 47 | (expression [_] (into {} (map expression) entries)) 48 | (children [_] (seq entries))) 49 | 50 | (defrecord MapSpecEntry [attribute value] 51 | ASTNode 52 | (expression [_] [(expression attribute) (expression value)]) 53 | (children [_] [attribute value])) 54 | 55 | (defrecord Pattern [args] 56 | ASTNode 57 | (expression [_] (mapv expression args)) 58 | (children [_] (seq args))) 59 | 60 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/pull/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.pull.error 16 | (:require [eva.error :as err])) 17 | 18 | (err/deferror syntax-error 19 | :pull/syntax-error 20 | "Invalid pull syntax" 21 | [:expression]) 22 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/sandbox.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.sandbox 16 | (:require [eva.query.dialect.aggregates] 17 | [eva.query.dialect.functions]) 18 | (:import (clojure.lang Var))) 19 | 20 | (defn create-eval-ns [] 21 | (let [ns-sym (symbol (str *ns* "." (gensym "evalns"))) 22 | ns (create-ns ns-sym)] 23 | (binding [*ns* ns] 24 | (refer-clojure :exclude '[eval min max rand]) 25 | (refer 'eva.query.dialect.aggregates) 26 | (refer 'eva.query.dialect.functions)) 27 | (.setDynamic ^Var (intern ns 'sym->edb)) 28 | (.setDynamic ^Var (intern ns 'pattern-vars)) 29 | ns)) 30 | 31 | ;; ^^^^^ sym->edb ^^^^^^ 32 | ;; Data sources are passed around as symbols in the datalog engine. sym->edb is used 33 | ;; to resolve the symbol to a specific Extensional database. 34 | ;; 35 | ;; When the query is compiled to Datalog, it wraps all the Extensional 36 | ;; sources with a single Extensional object with an extra ?src-var term; this object 37 | ;; then dispatches based on the value of that ?src-var. 38 | ;; 39 | ;; But if a data source is passed to a function, the function expects to see an actual 40 | ;; data source, not symbol. Because data sources are not actually available until 41 | ;; the inputs are passed into the query, and because we support arbitrary functions, 42 | ;; and because of *details*, it is easier to have the sym->edb map available at query 43 | ;; runtime than it is to wrap the functions correctly at compile time. 44 | 45 | (def ^:dynamic *sandbox-ns* (create-eval-ns)) 46 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/translation/compile.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.translation.compile 16 | (:require [eva.query.dialect.translation.compile.pass1 :as p1] 17 | [eva.query.dialect.translation.compile.pass2 :as p2]) 18 | (:refer-clojure :exclude [compile])) 19 | 20 | (defn compile [query] 21 | (-> (p1/preprocess-where-with-rules query) 22 | (p1/process-query) 23 | (p2/compile-processed-form))) 24 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/translation/core.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.translation.core 16 | (:require [eva.query.dialect.translation.compile :as compile] 17 | [eva.config :refer [config]] 18 | [eva.query.trace :as special] 19 | [eva.query.dialect.spec :as qs] 20 | [clojure.spec.alpha :as spec] 21 | [clojure.core.memoize :as mem]) 22 | (:refer-clojure :exclude [compile])) 23 | 24 | (def compile-query-and-rules 25 | ;; TODO: Measure and switch around the caching of compilation if spec conformation is expensive 26 | (mem/lru compile/compile 27 | :lru/threshold (config :eva.query.memoization-cache))) 28 | 29 | (defn compile 30 | [query & inputs] 31 | (let [query (if (map? query) 32 | (mapcat (partial apply (partial apply list)) query) 33 | query) 34 | _ (special/trace "QUAESTIO: query looks like: \n" query) 35 | 36 | conformed-datalog (qs/conform! ::qs/datalog query) 37 | rules-idx (qs/rules-idx conformed-datalog) 38 | conformed-query (qs/conform! ::qs/query 39 | (cond-> [query] 40 | rules-idx (conj (nth inputs rules-idx))))] 41 | (compile-query-and-rules conformed-query))) 42 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/translation/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.translation.error 16 | (:require [eva.error :refer :all])) 17 | 18 | (deferror-group translation-error 19 | :query.translation 20 | (invalid-form "Invalid query form") 21 | (unrecognized-clause "Unrecognized clause type") 22 | (unknown-predicate "Unknown predicate symbol" [:symbol]) 23 | (unresolved-sym "Unable to resolve symbol" [:fn-sym])) 24 | 25 | (deferror edb-error 26 | :query.inputs/invalid-data-source 27 | "Invalid data source" 28 | [:src-var]) 29 | -------------------------------------------------------------------------------- /core/src/eva/query/dialect/util.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.dialect.util) 16 | 17 | (defprotocol ASTNode 18 | (expression [ast] "returns the original expression that produced the ASTNode") 19 | (children [ast] "returns child ASTNodes")) 20 | 21 | (def default-ast-node-impl {:expression identity 22 | :children (constantly nil)}) 23 | (def default-ast-types [String 24 | Boolean 25 | Number 26 | clojure.lang.Keyword 27 | java.util.Date 28 | java.util.UUID 29 | java.net.URI 30 | (type (byte-array 0)) 31 | eva.ByteString]) 32 | 33 | (doseq [t default-ast-types] 34 | (extend t ASTNode default-ast-node-impl)) 35 | -------------------------------------------------------------------------------- /core/src/eva/query/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.error 16 | (:require [eva.error :refer :all])) 17 | 18 | (deferror-group parse-err 19 | (:query.invalid [:expression]) 20 | (find-spec "Invalid find spec") 21 | (inputs "Invalid inputs" [:invalid]) 22 | (with "Invalid with-clause" [:invalid]) 23 | (clause "Invalid clause") 24 | (or-clause "Invalid or-clause" [:invalid]) 25 | (or-join "Invalid or-join-clause" [:invalid]) 26 | (where "Invalid where-clause" [:invalid]) 27 | (query "Invalid query form")) 28 | 29 | (deferror-group builtin 30 | :query.builtins 31 | (function "An error occurred during the execution of a built-in function") 32 | (aggregate "An error occurred during the execution of a built-in aggregate function")) 33 | -------------------------------------------------------------------------------- /core/src/eva/query/trace.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.trace 16 | "Tracing utilities to add toggleable tracing to the query engine. 17 | 18 | Enable via setting the config option :eva.query.trace-logging or 19 | the environment variable EVA_QUERY_TRACE_LOGGING to true." 20 | (:require [eva.config :refer [config-strict]] 21 | [recide.sanex.logging :as log])) 22 | 23 | (defmacro trace 24 | [& stuff] 25 | `(when (config-strict :eva.query.trace-logging) 26 | (log/trace ~@stuff))) 27 | 28 | (defmacro trace-spy 29 | ([form] 30 | `(let [r# ~form] 31 | (trace r#) 32 | r#)) 33 | ([msg f form] 34 | `(let [r# ~form] 35 | (trace ~msg (~f r#)) 36 | r#))) 37 | -------------------------------------------------------------------------------- /core/src/eva/readers.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | ;; IMPORTANT: Take care when making changes to this file! 16 | ;; The following metadata MUST be present on the namespace declaration: 17 | ;; {:clojure.tools.namespace.repl/unload false 18 | ;; :clojure.tools.namespace.repl/load false} 19 | ;; This metadata excludes this namespace from reloading by clojure.tools.namespace. 20 | ;; 21 | ;; If this file is reloaded by clojure.tools.namespace, the clojure reader functions 22 | ;; referenced in clojure.core/*data-reader* WILL BREAK. 23 | ;; 24 | ;; This is because clojure.tools.namespace completely removes/unloads the 25 | ;; namespace-instance, causing the vars in clojure.core/*data-readers* to point to 26 | ;; a namespace-instance that no longer corresponds with this file. 27 | ;; 28 | ;; If you make changes to this file, or any function referenced here, you must 29 | ;; restart your repl. 30 | (ns ^{:clojure.tools.namespace.repl/unload false 31 | :clojure.tools.namespace.repl/load false} 32 | eva.readers 33 | (:require [clojure.edn :as edn] 34 | [eva.functions] 35 | [eva.entity-id] 36 | [eva.datom])) 37 | 38 | (defn read-db-fn [db-fn-form] (eva.functions/build-db-fn db-fn-form)) 39 | (defn read-db-id [vec-form] (apply eva.entity-id/tempid vec-form)) 40 | 41 | (def reader-functions {'db/fn #'read-db-fn 42 | 'db/id #'read-db-id}) 43 | 44 | (defn ensure-parsed 45 | "For functions that take EDN data structures, this function will attempt to parse 46 | any passed strings, and will otherwise return non-string values unchanged." 47 | [x] 48 | (if (string? x) 49 | (edn/read-string {:readers reader-functions} x) 50 | x)) 51 | -------------------------------------------------------------------------------- /core/src/eva/sizing_api.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.sizing-api) 16 | 17 | (defprotocol SizeEstimable 18 | (ram-size [o] "Estimate the size in ram of the object")) 19 | -------------------------------------------------------------------------------- /core/src/eva/utils/delay_queue.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.utils.delay-queue 16 | (:refer-clojure :exclude [memoize])) 17 | 18 | (defprotocol DelayedQueue 19 | (enqueue-f [dq f args]) 20 | (viz [dq])) 21 | (defn enqueue-update [dq f & args] (enqueue-f dq f args)) 22 | 23 | (defn- realize-step 24 | [v [p op]] 25 | (if (realized? p) 26 | @p 27 | (locking p 28 | (if (realized? p) 29 | @p 30 | @(deliver p (apply (:fn op) v (:args op))))))) 31 | 32 | ;; A type of queue in which elements can only be dequeued once it has 33 | ;; remained in the queue for a certain length of time. It goes without saying: 34 | ;; the head of the queue has always been in the queue the longest. 35 | (deftype DelayQueue 36 | [^clojure.lang.IDeref prom 37 | ^:volatile-mutable ^clojure.lang.PersistentVector ops 38 | ^:volatile-mutable ^Boolean pending?] 39 | clojure.lang.IDeref 40 | (deref [this] 41 | (if-not pending? 42 | @prom 43 | (locking this 44 | (if-not pending? 45 | @prom 46 | (let [ret (if (realized? prom) @prom (reduce realize-step ops))] 47 | (deliver prom ret) 48 | (set! ops []) 49 | (set! pending? false) 50 | ret))))) 51 | clojure.lang.IPending 52 | (isRealized [this] (or (not pending?) (realized? prom))) 53 | DelayedQueue 54 | (enqueue-f [this f args] 55 | (locking this 56 | (let [p (promise)] 57 | (if pending? 58 | (DelayQueue. p (conj ops [p {:fn f :args args}]) true) 59 | (DelayQueue. p [@prom [p {:fn f :args args}]] true))))) 60 | (viz [this] {:prom prom :ops ops :pending? pending?})) 61 | 62 | (defn delay-queue? [x] (instance? DelayQueue x)) 63 | (defn delay-queue 64 | ([x] 65 | (cond (delay-queue? x) x 66 | (instance? clojure.lang.IDeref x) (DelayQueue. (promise) [x {:fn deref :args ()}] true) 67 | :else (DelayQueue. (deliver (promise) x) [] false))) 68 | ([x f & args] (apply enqueue-update (delay-queue x) f args))) 69 | -------------------------------------------------------------------------------- /core/src/eva/utils/logging.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.utils.logging 16 | (:require [morphe.core :as d] 17 | [recide.sanex.logging :refer [log]])) 18 | 19 | (defn logged 20 | "Inserts a log/trace call as the first item in the fn body." 21 | ([] (logged :trace)) 22 | ([level] 23 | (fn [fn-form] 24 | (d/prefix-bodies fn-form 25 | `(log ~level ~(format "calling function: %s/%s:%s" 26 | (ns-name &ns) 27 | &name 28 | ¶ms)))))) 29 | -------------------------------------------------------------------------------- /core/src/eva/utils/testing.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.utils.testing 16 | (:require [clojure.test :refer :all])) 17 | 18 | (defmacro every-test 19 | [& syms] 20 | (letfn [(wrap [sym] `(comp #(or % (with-test-out (prn (str '~sym " failed.")))) 21 | ~sym))] 22 | `(every-pred ~@(map wrap syms)))) 23 | -------------------------------------------------------------------------------- /core/src/eva/utils/unify.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.utils.unify) 16 | 17 | (defn walk* 18 | "Walks a substitution-map s, resolving all intermediate lvars 19 | (as identified by pred lvar?), until a terminal value is found." 20 | [s u lvar?] 21 | (if-let [pr (s u)] 22 | (if (lvar? pr) 23 | (recur s pr lvar?) 24 | pr) 25 | u)) 26 | 27 | (defn unify* [u v s lvar?] 28 | (let [u (walk* s u lvar?) 29 | v (walk* s v lvar?)] 30 | (cond (and (lvar? u) 31 | (lvar? v) 32 | (= u v)) s 33 | (lvar? u) (assoc s u v) 34 | (lvar? v) (assoc s v u) 35 | :else (or (and (= u v) s) 36 | nil)))) 37 | 38 | (defprotocol Unifications 39 | (unifications [x source subst lvar?] 40 | "given source, previous substitition, and pred to detect lvars, returns sequence of possible unifications")) 41 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/README.md: -------------------------------------------------------------------------------- 1 | # A note on upgrading datastructures 2 | 3 | Our datastructures are an important part of EVA, and we would like continually to be making improvements to the underlying datastructure. To that end, this package allows for seamless, lazy datastructure upgrades to existing EVA instances. The design is generic, allowing implementations to pursue whatever kind of upgrade strategy implementers prefer. 4 | 5 | There are only two high-level pieces of this: 6 | 7 | * A [single protocol, `Versioned`](/core/src/eva/datastructures/protocols.clj#L34), containing a single method, `get-version`. Each datastructure is responsible for implementing its own versioning path. Currently, only our B-ε tree provides a full implementation. 8 | * An [`ensure-version` function](/core/src/eva/datastructures/versioning.clj#L25), implemented through the [multimethod `version-conversion`](/core/src/eva/datastructures/versioning.clj#L5), which is the entrypoint to converting between versions of a datastructure. 9 | 10 | Currently only the Bε-tree code has been restructured for ease of using this functionality. An example of how versioning might be implemented can be seen in these test files: 11 | 12 | * [Redirecting api.clj implementations to the new datastructure version](/dev/src/eva/datastructures/test_version/api.clj) 13 | * [Ensuring that fressian readers and writers use distinct tags](/dev/src/eva/datastructures/test_version/fressian.clj) 14 | * [Providing implementations of multimethod `version-conversion`](/dev/src/eva/datastructures/test_version/logic/versioning.clj#L89) 15 | * [A missing piece of the last file, separated for testing purposes](/dev/src/eva/datastructures/test_version/logic/missing_versioning.clj) 16 | * [Actually calling `ensure-version` after reading from storage](/dev/src/eva/datastructures/test_version/logic/nodes.clj#L196) 17 | 18 | An alternate method of implementation would be to re-use our message buffers to insert upgrade messages, relying on current propagation patterns for the upgrade messages to work their way through the tree. However, while we may use this in the future, it would put a number of limitations on the types and extent of changes we could make, forcing the conversion of each node to work without any context derived from hierarchical context existing above that node in the Bε-tree. 19 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/atom.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.atom 16 | (:require [eva.v2.storage.value-store :as vs] 17 | [eva.datastructures.protocols :refer [BackedStructure]]) 18 | (:import [eva.v2.storage.value_store.protocols IValueStorage])) 19 | 20 | ;; Wraps a store and a particular key to create a 21 | ;; 'persisted atom'. The atom should behave the same with 22 | ;; compare-and-set!, reset!, and deref, with the caveat 23 | ;; there may be io delays in performing the operations. 24 | ;; these operations *are* blocking. (this could be 25 | ;; abstracted away through a clone of the IAtom interface 26 | ;; in the future, if desired.) 27 | (defrecord PersistedAtom [^IValueStorage store ^String k] 28 | clojure.lang.IAtom 29 | (compareAndSet [_ oldv newv] @(vs/replace-value @store k oldv newv)) 30 | (reset [_ newval] @(vs/put-value @store k newval)) 31 | clojure.lang.IDeref 32 | (deref [_] (deref (vs/get-value @store k))) 33 | BackedStructure 34 | (storage-id [_] k) 35 | (store [_] store) 36 | (persisted? [_] true)) 37 | 38 | (defn persisted-atom [store k] 39 | (->PersistedAtom store k)) 40 | 41 | (defn create-persisted-atom 42 | ([store v] 43 | (let [k (str (random-uuid))] 44 | @(vs/put-value @store k v) 45 | (->PersistedAtom store k)))) 46 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.bbtree 16 | "Convenience namespace to refer to protocol methods and certain internal btree methods 17 | all in one place. See eva.v2.datastructures.bbtree.api for implementation details and docs." 18 | (:require [potemkin :as p] 19 | [eva.v2.datastructures.bbtree.api] 20 | [eva.datastructures.protocols]) 21 | (:refer-clojure :exclude [sorted-map sorted-set sorted-map-by sorted-set-by filter])) 22 | 23 | (p/import-vars 24 | [eva.v2.datastructures.bbtree.api 25 | sorted-map 26 | sorted-map-by 27 | sorted-set 28 | sorted-set-by 29 | backed-sorted-map 30 | backed-sorted-map-by 31 | backed-sorted-set 32 | backed-sorted-set-by 33 | open 34 | open-writable 35 | open-set 36 | open-writable-set 37 | open-map 38 | open-writable-map 39 | between 40 | subrange 41 | subranges] 42 | [eva.datastructures.protocols 43 | persist! 44 | make-editable! 45 | root-node 46 | storage-id 47 | store 48 | filter 49 | remove-interval 50 | keep-interval 51 | filter! 52 | remove-interval! 53 | keep-interval! 54 | in-mem-nodes]) 55 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.bbtree.error 16 | (:require [eva.error :refer [deferror-group]]) 17 | (:import (eva.error.v1 EvaErrorCode))) 18 | 19 | (deferror-group storage 20 | [:bbtree.storage [:method]] 21 | (failure "A storage failure occurred in the btree") 22 | (timeout "A storage timeout occurred in the btree" [:timeout-ms])) 23 | 24 | (deferror-group fressian-read-err 25 | [:fressian.unreadable [:handler-chain]] 26 | (vector "Unable to deserialize vector") 27 | (list "Unable to deserialize list") 28 | (set "Unable to deserialize set") 29 | (var "Unable to resolve var") 30 | (byte-string "Unable to deserialize ByteString")) 31 | 32 | (def overrides 33 | {:flowgraph/timeout EvaErrorCode/STORAGE_TIMEOUT}) 34 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/logic/v0/README.md: -------------------------------------------------------------------------------- 1 | # Version 0 of Bε-Trees 2 | 3 | This version makes heavy use of [persistence](https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf) and [laziness](https://www.cc.gatech.edu/~bader/COURSES/GATECH/CSE-Algs-Fall2013/papers/Arg03.pdf) and [batching](http://brics.dk/RS/96/28/BRICS-RS-96-28.pdf). 4 | 5 | ## Deletions 6 | Our deletion algorithm is derived from [this paper](http://ilpubs.stanford.edu:8090/85/1/1995-19.pdf). 7 | 8 | ## Balancing the tree 9 | See [here](./docs/balance.md). 10 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/logic/v0/docs/images/balance-illustration-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/core/src/eva/v2/datastructures/bbtree/logic/v0/docs/images/balance-illustration-1.png -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/logic/v0/docs/images/balance-illustration-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/core/src/eva/v2/datastructures/bbtree/logic/v0/docs/images/balance-illustration-2.png -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/logic/v0/docs/images/balance-illustration-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/core/src/eva/v2/datastructures/bbtree/logic/v0/docs/images/balance-illustration-3.png -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/logic/v0/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.bbtree.logic.v0.error 16 | (:require [eva.error :refer [deferror-group]])) 17 | 18 | (deferror-group persist 19 | [:bbtree.faulty-persist] 20 | (local-only "This copy cannot be persisted")) 21 | 22 | (deferror-group safety 23 | [:bbtree.safety] 24 | (not-found "A pre-existing buffered btree was expected but not found") 25 | (no-overwrite "Attempting to overwrite newer version of buffered btree") 26 | (unpersisted-changes "This operation cannot be called on a tree with unpersisted changes")) 27 | 28 | (deferror-group fressian-read-err 29 | [:fressian.unreadable [:handler-chain]] 30 | (bbtree-node "Unable to deserialize tree node") 31 | (bbtree-pointer "Unable to deserialize tree pointer") 32 | (bbtree-buffer "Unable to deserialize node buffer") 33 | (bbtree-message "Unable to deserialize bbtree message")) 34 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/logic/v0/state.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.bbtree.logic.v0.state) 16 | 17 | (def ^:dynamic *store* nil) 18 | (def ^:dynamic *node-id-counter* nil) 19 | (def ^:dynamic *transaction-id* nil) 20 | (def ^:dynamic *comparator* nil) 21 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/bbtree/logic/v0/storage.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.bbtree.logic.v0.storage 16 | (:require [eva.v2.datastructures.bbtree.logic.v0.state :as state] 17 | [eva.v2.datastructures.bbtree.logic.v0.nodes :as nodes] 18 | [eva.v2.datastructures.bbtree.logic.v0.protocols :as protocols] 19 | [eva.v2.datastructures.bbtree.error :refer [raise-storage]] 20 | [recide.sanex :as sanex] 21 | [eva.v2.datastructures.bbtree.storage :refer [get-nodes put-nodes get-node uuid]] 22 | [barometer.core :as em])) 23 | 24 | (def persist-tree-counter 25 | (em/get-or-register em/DEFAULT 'eva.v2.datastructures.bbtree.logic.v0.storage:persist-tree.counter 26 | (em/counter "Counts the number of times that 'persist-tree' is called."))) 27 | 28 | (def persist-tree-node-hist 29 | (em/get-or-register em/DEFAULT 'eva.v2.datastructures.bbtree.logic.v0.storage:persist-tree-node.histogram 30 | (em/histogram (em/reservoir) "Records the number of nodes persisted at each 'persist-tree' call."))) 31 | 32 | (defn persist-tree 33 | "Takes the IBBTreeSTorageBackend implementation and all new pointer-node pairs. Persists!" 34 | [store all-pairs] 35 | (em/increment persist-tree-counter) 36 | (em/update persist-tree-node-hist (count all-pairs)) 37 | (try (put-nodes @store all-pairs) 38 | (catch Exception e 39 | (raise-storage :failure 40 | "failed to persist the new tree." 41 | {:method 'persist-tree 42 | ::sanex/sanitary? false} 43 | e)))) 44 | 45 | (defn init-persist 46 | "When a new map or set is created, this persists a pointer to the empty initial root. 47 | Returns the persisted node with its new UUID." 48 | [store node] 49 | (binding [state/*store* store] 50 | (let [node-pointer (nodes/node->pointer node) 51 | node (uuid node (uuid node-pointer))] 52 | (put-nodes @store {node-pointer node}) 53 | node))) 54 | -------------------------------------------------------------------------------- /core/src/eva/v2/datastructures/var.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.var 16 | (:require [eva.v2.datastructures.atom :refer [->PersistedAtom]] 17 | [eva.v2.storage.value-store :as vs] 18 | [eva.datastructures.protocols :refer [EditableBackedStructure]])) 19 | 20 | ;; A persisted var is the 'simplest' base construct 21 | ;; in the backing store. It is essentially just a 22 | ;; tuple of key and backing store that can be 23 | ;; derefed to realize its value 24 | ;; 25 | ;; No interfaces are provided for mutation 26 | (defrecord PersistedVar [store ^String k] 27 | clojure.lang.IDeref 28 | (deref [_] (deref (vs/get-value @store k))) 29 | EditableBackedStructure 30 | (make-editable! [_] (->PersistedAtom store k))) 31 | 32 | (prefer-method print-method clojure.lang.IPersistentMap clojure.lang.IDeref) 33 | (prefer-method print-method clojure.lang.IRecord clojure.lang.IDeref) 34 | (prefer-method clojure.pprint/simple-dispatch clojure.lang.IPersistentMap clojure.lang.IDeref) 35 | 36 | (defn persisted-var [store k] (->PersistedVar store k)) 37 | -------------------------------------------------------------------------------- /core/src/eva/v2/messaging/address.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.messaging.address 16 | (:require [clojure.spec.alpha :as s])) 17 | 18 | ;;;;;;;;;; 19 | ;; SPEC ;; 20 | ;;;;;;;;;; 21 | 22 | (s/def ::address string?) 23 | 24 | (s/def ::transaction-submission ::address) 25 | (s/def ::index-updates ::address) 26 | (s/def ::transaction-publication ::address) 27 | 28 | ;;;;;;;;;;;;;; 29 | ;; END SPEC ;; 30 | ;;;;;;;;;;;;;; 31 | -------------------------------------------------------------------------------- /core/src/eva/v2/messaging/jms/beta/connection_factory.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.messaging.jms.beta.connection-factory 16 | (:import (java.lang.reflect Constructor) 17 | (javax.jms ConnectionFactory))) 18 | 19 | (defn ^:private load-class [cls] 20 | (cond (class? cls) cls 21 | (string? cls) (Class/forName (str cls)) 22 | (symbol? cls) (recur (name cls)) 23 | :else (throw (IllegalArgumentException. "expected class, or class-name as string or symbol")))) 24 | 25 | (defn ^:private constructor [cls sig] (.getConstructor (load-class cls) (into-array Class sig))) 26 | (defn ^:private new-instance [^Constructor ctor args] 27 | (.newInstance ctor (into-array Object args))) 28 | 29 | (defn ^:private construct 30 | ([cls args] (construct cls (map class args) args)) 31 | ([cls sig args] (-> cls (constructor sig) (new-instance args)))) 32 | 33 | (defn ^ConnectionFactory new-connection-factory 34 | "Creates an instance of a javax.jms.ConnectionFactory 35 | given the class-name and the constructor arguments." 36 | [class-name & args] 37 | (let [cls (load-class class-name)] 38 | (if (isa? cls ConnectionFactory) 39 | (construct cls args) 40 | (throw (IllegalArgumentException. (str cls " does not implement " ConnectionFactory)))))) 41 | 42 | (def connection-factory-name 43 | "Provides a map of alias to ConnectionFactory class-name. 44 | May be used in conjunction with `new-connection-factory` for easier 45 | lookup of class-names." 46 | {:artemis "org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory" 47 | :activemq "org.apache.activemq.ActiveMQConnectionFactory"}) 48 | -------------------------------------------------------------------------------- /core/src/eva/v2/messaging/node/manager/alpha.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.messaging.node.manager.alpha 16 | (:require [eva.v2.messaging.node.manager.types :as types] 17 | [eva.v2.messaging.node.beta :as beta] 18 | [eva.v2.messaging.node.local :as local] 19 | [quartermaster.core :as qu] 20 | [eva.v2.storage.value-store.core :as vs] 21 | [eva.v2.database.core :as db] 22 | [clojure.spec.alpha :as s])) 23 | 24 | (defmethod types/messenger-node-discriminator :broker-uri [user-id config] 25 | (beta/extract-broker-config config)) 26 | (defmethod types/messenger-node-constructor :broker-uri [description config] 27 | (beta/create-messenger description)) 28 | 29 | (defmethod types/messenger-node-discriminator :local-messenger-node [user-id config] 30 | (assert (::db/id config)) 31 | (assert (::vs/partition-id config)) 32 | [(::db/id config) (::vs/partition-id config)]) 33 | 34 | (defmethod types/messenger-node-constructor :local-messenger-node [description config] 35 | (local/local-messenger)) 36 | 37 | ;; END CONSTRUCTORS & IDENT ;; 38 | 39 | (qu/defmanager messenger-nodes 40 | :discriminator 41 | (fn [user-id config] (types/messenger-node-discriminator user-id config)) 42 | :constructor 43 | (fn [description config] (types/messenger-node-constructor description config))) 44 | -------------------------------------------------------------------------------- /core/src/eva/v2/messaging/node/manager/types.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.messaging.node.manager.types 16 | (:require [clojure.spec.alpha :as s])) 17 | 18 | ;;;;;;;;;; 19 | ;; SPEC ;; 20 | ;;;;;;;;;; 21 | 22 | ;; TODO: multispec 23 | (s/def ::config map?) 24 | 25 | ;;;;;;;;;;;;;; 26 | ;; END SPEC ;; 27 | ;;;;;;;;;;;;;; 28 | 29 | (defmulti messenger-node-discriminator 30 | "Returns a unique 'identity' for a messenger node for use 31 | in a resource manager." 32 | (fn [_ config] (:messenger-node-config/type config))) 33 | 34 | (defmulti messenger-node-constructor 35 | "Constructs and returns a SharedResource messenger node that satisfies 36 | the various messaging protocols" 37 | (fn [_ config] (:messenger-node-config/type config))) 38 | -------------------------------------------------------------------------------- /core/src/eva/v2/storage/block_store.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.block-store 16 | (:require [quartermaster.core :as qu] 17 | [eva.v2.storage.block-store.types :as types] 18 | [eva.v2.storage.block-store.impl.ddb :as ddb] 19 | [eva.v2.storage.block-store.impl.memory :as memory] 20 | [eva.v2.storage.block-store.impl.sql :as sql])) 21 | 22 | ;; CONSTRUCTORS & IDENT ;; 23 | 24 | (defmethod types/config-by-type ::types/ddb [_] ::ddb/config) 25 | (defmethod types/build-block-store ::types/ddb [config] (ddb/build-ddb-store config)) 26 | (defmethod types/block-store-ident ::types/ddb [config] (ddb/ddb-store-ident config)) 27 | 28 | (defmethod types/config-by-type ::types/ddb-local [_] ::ddb/local-config) 29 | (defmethod types/build-block-store ::types/ddb-local [config] (ddb/build-ddb-local-store config)) 30 | (defmethod types/block-store-ident ::types/ddb-local [config] (ddb/ddb-local-store-ident config)) 31 | 32 | (defmethod types/config-by-type ::types/memory [_] ::memory/config) 33 | (defmethod types/build-block-store ::types/memory [config] (memory/build-memory-store config)) 34 | (defmethod types/block-store-ident ::types/memory [config] (memory/memory-store-ident config)) 35 | 36 | (defmethod types/config-by-type ::types/sql [_] ::sql/config) 37 | (defmethod types/build-block-store ::types/sql [config] (sql/build-sql-store config)) 38 | (defmethod types/block-store-ident ::types/sql [config] (sql/sql-store-ident config)) 39 | 40 | ;; END CONSTRUCTORS & IDENT ;; 41 | 42 | (qu/defmanager block-store-manager 43 | :discriminator 44 | (fn [_ config] (types/block-store-ident config)) 45 | :constructor 46 | (fn [_ config] (types/build-block-store config))) 47 | -------------------------------------------------------------------------------- /core/src/eva/v2/storage/block_store/types.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.block-store.types 16 | (:require [clojure.spec.alpha :as s] 17 | [eva.v2.utils.spec :refer [conform-spec]])) 18 | 19 | (defmulti config-by-type ::storage-type) 20 | (s/def ::config (s/multi-spec config-by-type ::storage-type)) 21 | 22 | (defn config-type [config] 23 | {:pre [(conform-spec ::config config)]} 24 | (::storage-type config)) 25 | 26 | (defmulti build-block-store 27 | "Constructs an object satisfying the blockstore contract given a configuration 28 | which must be multispec'd via ::config. The returned block store must also 29 | implement the component protocol for starting and stopping to control resource 30 | allocation." 31 | config-type) 32 | 33 | (defmulti block-store-ident 34 | "Returns a 'ident' for the provided block store configuration, which will be 35 | used to determine uniqueness of the block store object. Since scopes for 36 | allocating connections / resources for the block stores are specific to each 37 | block store, this must be provided by the individual configurations." 38 | config-type) 39 | -------------------------------------------------------------------------------- /core/src/eva/v2/storage/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.error 16 | (:require [eva.error :refer [deferror deferror-group]])) 17 | 18 | (deferror data-err 19 | :storage.error/data 20 | "Invalid data" [:invalid]) 21 | 22 | (deferror-group sql-err 23 | :storage.sql 24 | (unknown "Unknown exception logged in SQL Storage error") 25 | (non-extant "SQL Storage not started") 26 | (cas-failure "SQL Storage CAS failed") 27 | (unexpected-cas-update-result "SQL Storage CAS update error")) 28 | 29 | (deferror request-cardinality 30 | :storage.error/request-cardinality-exceeded 31 | "Max request cardinality exceeded") 32 | 33 | (deferror-group ddb-err 34 | :storage.dynamo 35 | (credentials "Invalid AWSCredentials") 36 | (unprocessed "Error processing items")) 37 | 38 | (deferror-group conc-err 39 | :value-store.concurrent 40 | (state "Value store in illegal state") 41 | (unknown "Value store encountered unknown exception" [:method])) 42 | 43 | (deferror npe 44 | :value-store/NPE 45 | "Null pointer error in storage" [:method]) 46 | -------------------------------------------------------------------------------- /core/src/eva/v2/storage/system.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.system 16 | (:require [clojure.spec.alpha :as s] 17 | [eva.v2.storage.block-store.types :as blocks] 18 | [eva.v2.storage.value-store.core :as values])) 19 | 20 | (s/def ::config (s/merge ::blocks/config ::values/config)) 21 | -------------------------------------------------------------------------------- /core/src/eva/v2/storage/value_store/core.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.value-store.core 16 | (:require [clojure.spec.alpha :as s])) 17 | 18 | ;;;;;;;;;; 19 | ;; SPEC ;; 20 | ;;;;;;;;;; 21 | 22 | (s/def ::partition-id uuid?) 23 | 24 | (s/def ::config 25 | (s/keys :req [::partition-id] 26 | :opt [::uncached-keys])) 27 | -------------------------------------------------------------------------------- /core/src/eva/v2/storage/value_store/docs/reader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/core/src/eva/v2/storage/value_store/docs/reader.png -------------------------------------------------------------------------------- /core/src/eva/v2/storage/value_store/docs/simplified-reader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/core/src/eva/v2/storage/value_store/docs/simplified-reader.png -------------------------------------------------------------------------------- /core/src/eva/v2/storage/value_store/docs/writer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/core/src/eva/v2/storage/value_store/docs/writer.png -------------------------------------------------------------------------------- /core/src/eva/v2/storage/value_store/handlers.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.value-store.handlers 16 | (:require [eva.v2.storage.error :refer [raise-data-err]] 17 | [recide.sanex :as sanex] 18 | [clojure.data.fressian :as fressian]) 19 | (:import (org.fressian.handlers ILookup))) 20 | 21 | (defn ilookup? [x] (instance? ILookup x)) 22 | 23 | (def read-handlers 24 | (-> fressian/clojure-read-handlers 25 | fressian/associative-lookup)) 26 | 27 | (defn merge-read-handlers 28 | [handlers] 29 | (-> (merge handlers fressian/clojure-read-handlers) 30 | fressian/associative-lookup)) 31 | 32 | (def write-handlers 33 | (-> fressian/clojure-write-handlers 34 | fressian/associative-lookup 35 | fressian/inheritance-lookup)) 36 | 37 | (defn merge-write-handlers 38 | [handlers] 39 | (-> (merge handlers fressian/clojure-write-handlers) 40 | fressian/associative-lookup 41 | fressian/inheritance-lookup)) 42 | 43 | (defn normalize-read-handlers 44 | ([x] (normalize-read-handlers x false)) 45 | ([x strict?] 46 | (cond (ilookup? x) x 47 | (map? x) (merge-read-handlers x) 48 | :else (when (#{true :strict} strict?) 49 | (raise-data-err (str "normalize-read-handlers passed unknown value: " (pr-str x)) 50 | {:invalid x, 51 | ::sanex/sanitary? true}))))) 52 | 53 | (defn normalize-write-handlers 54 | ([x] (normalize-write-handlers false x)) 55 | ([x strict?] 56 | (cond (ilookup? x) x 57 | (map? x) (merge-write-handlers x) 58 | :else (when (#{true :strict} strict?) 59 | (raise-data-err (str "normalize-write-handlers passed unknown value: " (pr-str x)) 60 | {:invalid x, 61 | ::sanex/sanitary? true}))))) 62 | -------------------------------------------------------------------------------- /core/src/eva/v2/storage/value_store/manager.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.value-store.manager 16 | (:require [quartermaster.core :as qu] 17 | [eva.v2.storage.value-store.concurrent :as concurrent-value-store] 18 | [eva.v2.storage.value-store.gcached :as caching-value-store])) 19 | 20 | ;; TODO: for consistency, this file should probably be in storage/value-store/core.clj, 21 | ;; but the presence of specs in that file would force a cyclic dependency. 22 | ;; Once we have an external contract that allows us to perturb the config 23 | ;; parameters more easily, this manager should probably be relocated to core. 24 | 25 | ;; TODO: right now, we're calling down to the definitions for these functions 26 | ;; from their resource managers, but they should probably be 27 | ;; consolidated: I don't think we *really* have a case for lots of 28 | ;; polymorphism wrt value stores. The different managers should 29 | ;; probably just be one. 30 | 31 | (qu/defmanager value-store-manager 32 | :discriminator 33 | (fn [user config] 34 | (if (true? (::disable-caching? config)) 35 | [:no-caching (concurrent-value-store/discriminator user config)] 36 | [:caching (caching-value-store/discriminator user config)])) 37 | :constructor 38 | (fn [[caching-opt sub-ident] config] 39 | (case caching-opt 40 | :no-caching (concurrent-value-store/constructor sub-ident config) 41 | :caching (caching-value-store/constructor sub-ident config)))) 42 | -------------------------------------------------------------------------------- /core/src/eva/v2/system/message.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.system.message 16 | (:require [eva.v2.system.indexing.core :as indexing] 17 | [eva.v2.database.log :as log] 18 | [eva.v2.system.transactor.core :as tx] 19 | [eva.v2.database.core :as database] 20 | [eva.v2.storage.value-store.core :as values] 21 | [clojure.spec.alpha :as s])) 22 | 23 | (s/def ::scope 24 | (s/keys :req [::values/partition-id 25 | ::database/id])) 26 | 27 | (defn system-scoped-spec [s] 28 | (s/merge s ::scope)) 29 | 30 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 31 | ;; SYSTEM-SUPPORTED MESSAGES ;; 32 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 33 | 34 | ;; TODO: This may not be the correct place for these. 35 | 36 | (s/def ::transaction-submission 37 | (system-scoped-spec (s/keys :req-un [::tx/transaction-data]))) 38 | 39 | (s/def ::transaction-accepted 40 | (system-scoped-spec (s/keys :req-un [::log/entry]))) ;; TODO: This currently has undocumented issues 41 | 42 | ;; the transactor has written a new log entry vs ... 43 | (s/def ::log-advanced 44 | (system-scoped-spec (s/keys :req-un [::log/head]))) ;; TODO: This currently has undocumented issues 45 | 46 | (s/def ::indexes-updated 47 | (system-scoped-spec (s/keys :req-un [::indexing/index-updates]))) ;; TODO: This currently has undocumented issues 48 | -------------------------------------------------------------------------------- /core/src/eva/v2/system/peer_connection/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.system.peer-connection.error 16 | (:require [eva.error :refer [deferror-group]])) 17 | 18 | (deferror-group timeout 19 | (:peer-timeout [:timeout-ms]) 20 | (transact "Peer timed out" [:tx-data-size])) 21 | 22 | (deferror-group connect-failure 23 | (:peer-connect [:peer-id :database-id]) 24 | (message-queue "Unable to connect to message queue") 25 | (resource-manager "Unable to acquire a resource") 26 | (unrecognized-cause "Unable to acquire a peer connection")) 27 | -------------------------------------------------------------------------------- /core/src/eva/v2/transaction_pipeline/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.transaction-pipeline.error 16 | "Transaction pipeline related errors and error codes." 17 | (:require [eva.error :as ee]) 18 | (:import [eva.error.v1 EvaErrorCode])) 19 | 20 | (ee/deferror-group tx-fn-error 21 | (:transaction-pipeline [:fn]) 22 | (tx-fn-threw "A tx-fn threw an exception") 23 | (tx-fn-illegal-return "A tx-fn return value indecipherable.")) 24 | 25 | (ee/deferror unrecognized-command 26 | :transaction-pipeline/unrecognized-command 27 | "Cannot interpret object as a transaction command" 28 | [:unrecognized-command]) 29 | 30 | (ee/deferror invalid-tx-inst 31 | :transact-exception/invalid-tx-inst 32 | "invalid :db/txInstant") 33 | 34 | (ee/deferror clock-skew 35 | :transact-exception/clock-skew 36 | "excessive transactor clock skew detected") 37 | 38 | ;; The following map is 39 | (def error-codes 40 | "For adding overrides to the types of exceptions thrown from the 41 | transactor. 42 | 43 | There aren't any as of yet, but it's probably pretty likely 44 | we'll find *some* case of exception that we want to be a bit more 45 | obvious from the context of a transaction." 46 | {:attribute-resolution/unresolvable-attribute EvaErrorCode/MODEL_CONSTRAINT_VIOLATION 47 | :attribute-resolution/irresolvable-attribute EvaErrorCode/MODEL_CONSTRAINT_VIOLATION}) 48 | -------------------------------------------------------------------------------- /core/src/eva/v2/transaction_pipeline/protocols.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.transaction-pipeline.protocols 16 | "Protocols used in transaction pipeline.") 17 | 18 | (defprotocol TxReportProcessing 19 | (note-ref-attr [report ref-attr-eid]) 20 | (note-tx-inst [report inst]) 21 | (note-validated [report]) 22 | (note-now [report now]) 23 | (resolve-tx-fns [report] "Resolve all transaction functions to MapEntities, Adds, or Retracts") 24 | (flatten-maps [report] "Flatten all MapEntities to Adds") 25 | (resolve-ids [report] "Resolve the datoms contained in the report") 26 | (eliminate-redundancy [report]) 27 | (validate [report] "Validate the fully-resolved transaction report, producing a db-after") 28 | (check-commands-value-types! [report] "Checks if value matches the type Adds/Retracts commands") 29 | (generate-tx-log-entry [report]) 30 | (generate-old-signature-results [report])) 31 | 32 | (defprotocol CoerceToCommand 33 | (coerce-to-command [o db] "Reifies explicit types for commands to add, retract, resolve map-entity, run a tx-fn")) 34 | -------------------------------------------------------------------------------- /core/src/eva/v2/transaction_pipeline/resolve/maps.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.transaction-pipeline.resolve.maps 16 | (:require [eva.v2.transaction-pipeline.resolve.maps.flatten :refer [flatten-map-entities]] 17 | [eva.v2.transaction-pipeline.type.map :refer [map-entity? map->adds]] 18 | [morphe.core :as d] 19 | [ichnaie.core :refer [traced]])) 20 | 21 | (d/defn ^{::d/aspects [traced]} resolve-map-entities 22 | "Given a report comprised of Add, Retract, and MapEntity objects, return an 23 | updated report where the MapEntity objects have been resolved to Adds." 24 | [report] 25 | (let [flattened-report (flatten-map-entities report) 26 | grpd (group-by map-entity? (:tx-data flattened-report)) 27 | res (mapcat map->adds (get grpd true))] 28 | (assoc flattened-report 29 | :tx-data (into (get grpd false) res)))) 30 | -------------------------------------------------------------------------------- /core/src/eva/v2/transaction_pipeline/resolve/tx_fns.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.transaction-pipeline.resolve.tx-fns 16 | (:require [eva.v2.transaction-pipeline.type.tx-fn :refer [tx-fn? eval-tx-fn]] 17 | [morphe.core :as d] 18 | [ichnaie.core :refer [traced]])) 19 | 20 | (defn resolve-tx-fns* [tx-data] 21 | (let [grpd (group-by tx-fn? tx-data)] 22 | (into (get grpd false) (mapcat (comp resolve-tx-fns* eval-tx-fn)) (get grpd true)))) 23 | 24 | (d/defn ^{::d/aspects [traced]} resolve-tx-fns 25 | "Given a report comprised of Add, Retract, and MapEntity objects, return an 26 | updated report where the MapEntity objects have been resolved to Adds." 27 | [report] 28 | (update report :tx-data resolve-tx-fns*)) 29 | -------------------------------------------------------------------------------- /core/src/eva/v2/transaction_pipeline/type/tx_fn.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.transaction-pipeline.type.tx-fn 16 | "Defines a concrete type for transaction functions handled in the transaction pipeline." 17 | (:require [eva 18 | [core :refer [select-datoms]]] 19 | [eva.v2.transaction-pipeline.protocols :refer [coerce-to-command]] 20 | [eva.v2.transaction-pipeline.error :as tpe] 21 | [recide.core :refer [try*]] 22 | [eva.core :refer [db-fn? ->fn]]) 23 | (:import (java.util List) 24 | (eva Database))) 25 | 26 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 27 | ;; Transaction Functions 28 | 29 | (defrecord TxFn [^Database db ^List raw f args]) 30 | 31 | (defn- name-of-fn 32 | [tx-fn] 33 | (or (-> tx-fn :f :fn-name) 'name-your-tx-fns-and-this-gets-better)) 34 | 35 | (defn eval-tx-fn 36 | "Evaluate the given transaction function, yielding a new coll of tx-data" 37 | [tx-fn] 38 | (map #(try* (coerce-to-command % (:db tx-fn)) 39 | (catch :transaction-pipeline/unrecognized-command e 40 | (tpe/raise-tx-fn-error :tx-fn-illegal-return 41 | "aborting transaction." 42 | {:fn (name-of-fn tx-fn)} 43 | e))) 44 | (try 45 | (apply (:f tx-fn) (:db tx-fn) (:args tx-fn)) 46 | (catch Throwable t 47 | (tpe/raise-tx-fn-error :tx-fn-threw 48 | "aborting transaction." 49 | {:fn (name-of-fn tx-fn)} 50 | t))))) 51 | 52 | (defn tx-fn? [o] (instance? TxFn o)) 53 | 54 | (defn db-fn-op? [db o] 55 | (db-fn? db o)) 56 | 57 | (defn ->tx-fn [db cmd] 58 | (let [[op & args] (seq cmd)] 59 | (->TxFn db cmd (->fn db op) args))) 60 | -------------------------------------------------------------------------------- /core/src/eva/v2/utils/completable_future.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.utils.completable-future 16 | (:refer-clojure :exclude [promise deliver realized?]) 17 | (:import (java.util.concurrent CompletableFuture))) 18 | 19 | (defn promise [] (CompletableFuture.)) 20 | (defn promise? [x] (instance? CompletableFuture x)) 21 | 22 | (defn complete [^CompletableFuture p v] (.complete p v)) 23 | (defn reject [^CompletableFuture p ex] (.completeExceptionally p ex)) 24 | (defn deliver [p v] (if (instance? Throwable v) 25 | (reject p v) 26 | (complete p v))) 27 | 28 | (defn done? [^CompletableFuture p] (.isDone p)) 29 | (defn pending? [p] (not (done? p))) 30 | (defn rejected? [^CompletableFuture p] (.isCompletedExceptionally p)) 31 | (defn cancelled? [^CompletableFuture p] (.isCancelled p)) 32 | 33 | (defn failed? [p] (or (rejected? p) (cancelled? p))) 34 | (defn resolved? [p] (and (not (failed? p)) 35 | (done? p))) 36 | -------------------------------------------------------------------------------- /core/src/eva/v2/utils/spec.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.utils.spec 16 | (:require [clojure.spec.alpha :as s] 17 | [eva.error :refer [raise]])) 18 | 19 | (defn conform-spec [spec x] 20 | (let [conformed (s/conform spec x)] 21 | (if (s/invalid? conformed) 22 | (raise :invalid-spec 23 | (str "\n" (s/explain-str spec x)) 24 | {:spec spec 25 | :x x 26 | :explain-data (s/explain-data spec x)}) 27 | conformed))) 28 | -------------------------------------------------------------------------------- /core/src/eva/value_types.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.value-types 16 | (:require [eva.entity-id :refer [IEntityID]] 17 | [eva.bytes] 18 | [eva.functions]) 19 | (:import [eva.functions DBFn] 20 | [eva.bytes BBA] 21 | (java.util Date UUID) 22 | (java.net URI) 23 | (clojure.lang BigInt))) 24 | 25 | (defn test-array 26 | [t] 27 | (let [check (type (t []))] 28 | (fn [arg] (instance? check arg)))) 29 | 30 | (def byte-array? 31 | (test-array byte-array)) 32 | 33 | (def type->validator 34 | {:db.type/instant (partial instance? Date) 35 | :db.type/boolean (partial instance? Boolean) 36 | :db.type/bytes (partial instance? BBA) 37 | :db.type/uri (partial instance? URI) 38 | :db.type/uuid (partial instance? UUID) 39 | :db.type/string string? 40 | :db.type/keyword keyword? 41 | :db.type/ref (partial satisfies? IEntityID) 42 | :db.type/bigdec decimal? 43 | :db.type/float (fn [x] (and (float? x) (not (Float/isNaN x)))) 44 | :db.type/bigint (partial instance? BigInt) 45 | :db.type/double (fn [x] (and (double? x) (not (Double/isNaN x)))) 46 | :db.type/long (partial instance? Long) 47 | :db.type/fn (partial instance? DBFn)}) 48 | 49 | (defmulti valid-value-type? (fn [t _] t)) 50 | 51 | (defn register-types [vmap] 52 | (doseq [[t vfn] vmap] 53 | (defmethod valid-value-type? t [_ v] (vfn v)))) 54 | 55 | (register-types type->validator) 56 | -------------------------------------------------------------------------------- /core/test/eva/byte_string_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.byte-string-test 16 | (:require [clojure.test :refer :all]) 17 | (:import (eva ByteString) 18 | (java.util Arrays))) 19 | 20 | (deftest test:byte-string-joining 21 | (let [b1-bytes (repeat (rand-int 100) (byte 65)) 22 | b1 (byte-array b1-bytes) 23 | b2-bytes (repeat (rand-int 100) (byte 66)) 24 | b2 (byte-array b2-bytes) 25 | b3-bytes (repeat (rand-int 100) (byte 67)) 26 | b3 (byte-array b3-bytes) 27 | expected-array (byte-array (concat b1-bytes b2-bytes b3-bytes))] 28 | (is (= (ByteString/copyFrom expected-array) 29 | (ByteString/join (map #(ByteString/copyFrom ^bytes %) [b1 b2 b3])))) 30 | (is (Arrays/equals expected-array 31 | (->> [b1 b2 b3] 32 | (map #(ByteString/copyFrom ^bytes %)) 33 | (ByteString/join) 34 | (.toByteArray)))))) 35 | -------------------------------------------------------------------------------- /core/test/eva/contextual/config_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.contextual.config-test 16 | (:require 17 | [clojure.test :refer :all] 18 | [eva.contextual.config :as config])) 19 | 20 | (defn reset-config! [f] 21 | (config/reset!) 22 | (f)) 23 | 24 | (use-fixtures :each reset-config!) 25 | 26 | (deftest unit:tags-overriding 27 | (testing "overriden tags are not ignored when not configured" 28 | (is (config/keep? :a ::config/override))) 29 | 30 | (testing "overriden tags are not ignored when enabled" 31 | (config/enable! :a) 32 | (is (config/keep? :a ::config/override))) 33 | 34 | (testing "overriden tags are not ignored when disabled" 35 | (config/disable! :a) 36 | (is (config/keep? :a ::config/override)))) 37 | 38 | 39 | (deftest unit:enabling-tags 40 | (testing "tags are not ignored when not configured" 41 | (is (config/keep? :a ::config/as-per-config))) 42 | 43 | (testing "tags are ignored when disabled" 44 | (config/disable! :a) 45 | (is (not (config/keep? :a ::config/as-per-config)))) 46 | 47 | (testing "tags are not ignored when enabled" 48 | (config/enable! :a) 49 | (is (config/keep? :a ::config/as-per-config)))) 50 | -------------------------------------------------------------------------------- /core/test/eva/datom_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datom-test 16 | (:require [clojure.test :refer :all] 17 | [eva.datom :refer [datom]])) 18 | 19 | (deftest test-datom-hash-and-equals 20 | (are [d1 d2] (and (.equals d1 d2) (.equals d2 d1) 21 | (= (.hashCode d1) (.hashCode d2))) 22 | (datom 1 2 3 1 true) (datom 1 2 3 1 true) 23 | (datom 1 5 "foo" 1 true) (datom 1 5 "foo" 1 true) 24 | (datom 1 5 "foo" 1 false) (datom 1 5 "foo" 1 false)) 25 | 26 | (are [d1 d2] (not (and (.equals d1 d2) (.equals d2 d1) 27 | (= (.hashCode d1) (.hashCode d2)))) 28 | (datom 100 2 3 1 true) (datom 1 2 3 1 true) 29 | (datom 1 5 "foo" 1 true) (datom 1 5 "foo" 1 false) 30 | (datom 1 5 "foo" 1 false) (datom 1 5 "bar" 1 false))) 31 | -------------------------------------------------------------------------------- /core/test/eva/quartermaster_patches.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.quartermaster-patches 16 | (:require [quartermaster.core] 17 | [eva.contextual.core] 18 | [clojure.test :refer :all])) 19 | 20 | (defmacro testing-for-resource-leaks 21 | "This macro is for tests only and it is specialization of 22 | quartermaster's `testing-for-resource-leaks` macro - metrics are allowed to leak: 23 | 1. In most cases metrics get created not through resource manager anyway and 24 | therefore they are getting released when application quits 25 | 2. When tagged metrics get created for something which is not shared resource they have 26 | to be released manually (for example, `eva.api/release` must also release metrics and do it 27 | outside of `morphe.core/defn` macro" 28 | [& body] 29 | `(let [leaked# (quartermaster.core/identify-resource-leaks ~@body)] 30 | (is (empty? (remove #(= `eva.contextual.metrics/metrics %) leaked#))))) 31 | 32 | (comment 33 | (testing-for-resource-leaks (prn "example"))) 34 | -------------------------------------------------------------------------------- /core/test/eva/query/exceptions_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.query.exceptions-test 16 | (:require [eva.query.core :refer [q inspect]] 17 | [eva.error :refer [is-thrown?]]) 18 | (:import [eva.error.v1 EvaErrorCode]) 19 | (:use [clojure.test])) 20 | 21 | (deftest better-exception:missing-predicate-expression 22 | (is-thrown? 23 | {:msg-re #".*predicate does not exist\." 24 | :error-codes #{EvaErrorCode/UNKNOWN_QUERY_PREDICATE 25 | EvaErrorCode/DATALOG_INTERPRETER_FAILURE 26 | EvaErrorCode/PROCESSING_FAILURE} 27 | :http-code 422 28 | :error-type :query.translation/unknown-predicate} 29 | (q '[:find ?name 30 | :in $ % 31 | :where 32 | (book-1author "Modeling Business Processes: A Petri-Net Oriented Approach" ?name)] 33 | [] 34 | '[[(book-author ?book ?name) 35 | [?b :book/title ?book] 36 | [?b :book/author ?a] 37 | [?a :author/name ?name]]]))) 38 | -------------------------------------------------------------------------------- /core/test/eva/test/clojure_test_ext.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.test.clojure-test-ext 16 | "Provides extensions to clojure.test" 17 | (:require [clojure.test :refer :all])) 18 | 19 | ;; Allows you to test for an exception along with its cause. 20 | ;; This is particularly useful when dealing with ExecutionExceptions: 21 | ;; 22 | ;; ``` 23 | ;; (is (thrown-with-cause? ExecutionException IllegalArgumentException 24 | ;; @(future (throw (IllegalArgumentException.)) 25 | ;; ``` 26 | (defmethod assert-expr 'thrown-with-cause? [msg form] 27 | (let [outer-klass (nth form 1) 28 | inner-klass (nth form 2) 29 | body (nthnext form 3)] 30 | `(try ~@body 31 | (do-report {:type :fail, :message ~msg 32 | :expected '~form :actual nil}) 33 | (catch ~outer-klass e# 34 | (if (instance? ~inner-klass (.getCause e#)) 35 | (do-report {:type :pass, :message ~msg 36 | :expected '~form, :actual (.getCause e#)}) 37 | (do-report {:type :fail, :message ~msg, 38 | :expected '~form, :actual (.getCause e#)})) 39 | (.getCause e#))))) 40 | -------------------------------------------------------------------------------- /core/test/eva/utils/delay_queue_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.utils.delay-queue-test 16 | (:require [eva.utils.delay-queue :refer :all] 17 | [clojure.test :refer :all])) 18 | 19 | (deftest delay-queue:very-deep 20 | (is (= 500000500000 21 | @(loop [n 1000000 res (delay-queue 0)] 22 | (if (zero? n) 23 | res 24 | (recur (dec n) (enqueue-f res #(+ % n) []))))))) 25 | 26 | (deftest delay-queue:memoizes 27 | (let [test-size 10000 28 | total (atom 0) 29 | update-fn (fn [x] 30 | (enqueue-f x #(do (swap! total inc) 31 | (inc %)) 32 | [])) 33 | dawdles (take test-size (rest (iterate update-fn (delay-queue 0)))) 34 | final (last dawdles) 35 | dawdles (doseq [dawdle (shuffle dawdles)] 36 | (deref dawdle))] 37 | (is (= @total test-size)) 38 | (is (= @final test-size)))) 39 | -------------------------------------------------------------------------------- /core/test/eva/v2/datastructures/atom_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.atom-test 16 | (:require [clojure.test :refer :all] 17 | [eva.v2.datastructures.atom :refer :all] 18 | [eva.datastructures.protocols :refer [make-editable!]] 19 | [eva.v2.storage.value-store.concurrent :as vsc] 20 | [quartermaster.core :as qu] 21 | [eva.quartermaster-patches :as qp] 22 | [eva.v2.storage.block-store.types :as store-type] 23 | [eva.v2.storage.block-store.impl.memory :as memory] 24 | [eva.v2.storage.value-store.core :as value])) 25 | 26 | (defn memory-config 27 | [] 28 | {::store-type/storage-type ::store-type/memory 29 | ::memory/store-id (random-uuid) 30 | ::value/partition-id (random-uuid)}) 31 | 32 | (deftest atom-unit-test 33 | (let [config (memory-config)] 34 | (qp/testing-for-resource-leaks 35 | (try 36 | (let [store (qu/acquire vsc/concurrent-value-store-manager :testing config) 37 | ak "atom-key" 38 | p-atom (persisted-atom store ak)] 39 | (is (reset! p-atom 1)) 40 | (is (= 1 @p-atom)) 41 | (is (compare-and-set! p-atom 1 2)) 42 | (is (= 2 @p-atom))) 43 | (finally 44 | (qu/release* vsc/concurrent-value-store-manager :testing config true)))))) 45 | -------------------------------------------------------------------------------- /core/test/eva/v2/datastructures/var_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.datastructures.var-test 16 | (:require [clojure.test :refer :all] 17 | [eva.v2.datastructures.var :refer :all] 18 | [eva.datastructures.protocols :refer [make-editable!]] 19 | [eva.v2.storage.value-store.concurrent :as vsc] 20 | [quartermaster.core :as qu] 21 | [eva.quartermaster-patches :as qp] 22 | [eva.v2.storage.block-store.types :as store-type] 23 | [eva.v2.storage.block-store.impl.memory :as memory] 24 | [eva.v2.storage.value-store.core :as value] 25 | [eva.v2.storage.value-store :refer [put-value]])) 26 | 27 | (defn memory-config 28 | [] 29 | {::store-type/storage-type ::store-type/memory 30 | ::memory/store-id (random-uuid) 31 | ::value/partition-id (random-uuid)}) 32 | 33 | (deftest var-unit-tests 34 | (let [config (memory-config)] 35 | (qp/testing-for-resource-leaks 36 | (try 37 | (let [store (qu/acquire vsc/concurrent-value-store-manager :testing config) 38 | pk (str ["1"] ["v"]) 39 | p-var (persisted-var store pk) 40 | p-at (make-editable! p-var)] 41 | (is @(put-value @store pk 1)) 42 | (is (= 1 @p-var)) 43 | (is (= 1 @p-at)) 44 | (compare-and-set! p-at 1 2) 45 | (is (= 2 @p-var)) 46 | (is (= 2 @p-at))) 47 | (finally 48 | (qu/release* vsc/concurrent-value-store-manager :testing config true)))))) 49 | -------------------------------------------------------------------------------- /core/test/eva/v2/server/transactor_test_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.server.transactor-test-utils 16 | (:require [eva.api :as api] 17 | [eva.quartermaster-patches :as qp]) 18 | (:import (java.io File))) 19 | 20 | (defmacro with-local-mem-connection [name & body] 21 | `(qp/testing-for-resource-leaks 22 | (let [~name (api/connect {:local true 23 | :eva.v2.database.core/id (random-uuid)})] 24 | (try 25 | ~@body 26 | (finally (api/release ~name)))))) 27 | 28 | (def cntr (atom 1)) 29 | (defn ^File temp-file 30 | [] 31 | (File/createTempFile (str "sql-test-db-" (swap! cntr inc)) "tmpdb")) 32 | 33 | (defn h2-config [path] 34 | {:local true, 35 | :eva.v2.database.core/id (random-uuid), 36 | :eva.v2.storage.value-store.core/partition-id (random-uuid), 37 | :eva.v2.storage.block-store.types/storage-type :eva.v2.storage.block-store.types/sql, 38 | :eva.v2.storage.block-store.impl.sql/db-spec 39 | {:classname "org.h2.Driver", 40 | :subprotocol "h2", 41 | :subname path 42 | :user "sa"}}) 43 | 44 | (defn sqlite-config [path] 45 | {:local true, 46 | :eva.v2.database.core/id (random-uuid), 47 | :eva.v2.storage.value-store.core/partition-id (random-uuid), 48 | :eva.v2.storage.block-store.types/storage-type :eva.v2.storage.block-store.types/sql, 49 | :eva.v2.storage.block-store.impl.sql/db-spec 50 | {:classname "org.sqlite.JDBC", 51 | :subprotocol "sqlite", 52 | :subname path}}) 53 | 54 | (defmacro with-local-sql-connection* [name & body] 55 | `(let [tmp-file# (temp-file) 56 | config# (sqlite-config (.getAbsolutePath tmp-file#)) 57 | ~name (api/connect config#)] 58 | (try 59 | ~@body 60 | (finally (api/release ~name))))) 61 | 62 | (defmacro with-local-sql-connection [name & body] 63 | `(qp/testing-for-resource-leaks 64 | (with-local-sql-connection* ~name ~@body))) 65 | -------------------------------------------------------------------------------- /core/test/eva/v2/storage/chunk_callback_outstream_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.chunk-callback-outstream-test 16 | (:require [clojure.test :refer :all]) 17 | (:import (eva.storage ChunkCallbackOutputStream))) 18 | 19 | (deftest test:ChunkCallbackOutputStream 20 | (let [chunks (atom []) 21 | closed? (atom false)] 22 | (with-open [out (ChunkCallbackOutputStream. 10 23 | (fn on-chunk [ba] (swap! chunks conj ba)) 24 | (fn on-close [] (swap! closed? not)))] 25 | (doseq [i (range 95)] 26 | (is (not @closed?)) 27 | (.write out (int i)))) 28 | 29 | (is (true? @closed?)) 30 | (is (= 10 (count @chunks))))) 31 | -------------------------------------------------------------------------------- /core/test/eva/v2/storage/ddb_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.ddb-test 16 | (:require [clojure.test :refer :all] 17 | [eva.v2.storage.ddb :refer :all] 18 | [eva.v2.storage.core :as blocks] 19 | [clojure.java.io :as io] 20 | [clojure.set :as set])) 21 | (def ^:dynamic *ddb-client* nil) 22 | (defn ddb-client [] (assert *ddb-client* "*ddb-client* not bound") *ddb-client*) 23 | 24 | (defn random-unprocessed [ks] 25 | (let [completed (random-sample 0.75 ks)] 26 | {:completed completed 27 | :unprocessed (set/difference (set ks) (set completed))})) 28 | 29 | (deftest test:retry-until-complete 30 | (let [items (vec (range 1000)) 31 | call-count (atom 0) 32 | strategy (exponential-retry-strategy 100) 33 | final-results (retry-until-complete strategy 34 | :completed 35 | :unprocessed 36 | (fn ([] []) ([acc complete] (into acc complete))) 37 | #(do (swap! call-count inc) (random-unprocessed %)) 38 | items)] 39 | (is (< 0 @call-count (count strategy))) 40 | (is (= (set final-results) 41 | (set items))))) 42 | 43 | -------------------------------------------------------------------------------- /core/test/eva/v2/storage/testing_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.v2.storage.testing-utils 16 | (:require [eva.v2.storage.block-store.types :as store-type] 17 | [eva.v2.storage.block-store.impl.memory :as memory] 18 | [eva.v2.storage.value-store.core :as value] 19 | [eva.v2.storage.block-store :as bs] 20 | [quartermaster.core :as qu] 21 | [eva.quartermaster-patches :as qp] 22 | [eva.v2.storage.value-store.concurrent :as vsc])) 23 | 24 | (defn store-memory-config 25 | [] 26 | {::store-type/storage-type ::store-type/memory 27 | ::memory/store-id (random-uuid) 28 | ::value/partition-id (random-uuid)}) 29 | 30 | (defmacro with-mem-value-store [name & body] 31 | `(qp/testing-for-resource-leaks 32 | (let [~name (qu/acquire vsc/concurrent-value-store-manager :testing (store-memory-config))] 33 | (try 34 | ~@body 35 | (finally (qu/release ~name true)))))) 36 | 37 | (defmacro with-mem-block-store [name & body] 38 | `(qp/testing-for-resource-leaks 39 | (let [~name (qu/acquire bs/block-store-manager :testing (store-memory-config))] 40 | (try 41 | ~@body 42 | (finally (qu/release ~name true)))))) 43 | -------------------------------------------------------------------------------- /dev/java-src/eva/dev/logback/PrintAppender.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva.dev.logback; 16 | 17 | 18 | import ch.qos.logback.classic.spi.ILoggingEvent; 19 | import ch.qos.logback.core.AppenderBase; 20 | import clojure.java.api.Clojure; 21 | import clojure.lang.IFn; 22 | 23 | public class PrintAppender extends AppenderBase { 24 | 25 | private IFn print; 26 | 27 | @Override 28 | public void start() { 29 | IFn require = Clojure.var("clojure.core", "require"); 30 | require.invoke(Clojure.read("eva.dev.logback.print-appender")); 31 | this.print = Clojure.var("eva.dev.logback.print-appender", "print-logging-event"); 32 | super.start(); 33 | } 34 | 35 | @Override 36 | protected void append(E e) { 37 | assert (e instanceof ILoggingEvent); 38 | ILoggingEvent evt = (ILoggingEvent)e; 39 | print.invoke(evt); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /dev/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | logs/${EVA_LOG_NAME:-eva-dev}.log 17 | true 18 | 19 | 20 | logs/${EVA_LOG_NAME:-eva-dev}.%d{yyyy-MM-dd}.log 21 | 22 | 30 23 | 3GB 24 | 25 | 26 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 27 | 28 | 29 | 30 | 31 | 32 | 33 | jdbc:sqlite:logs/${EVA_LOG_NAME:-eva-dev}.sqlite 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /dev/src/eva/datastructures/test_version/logic/error.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datastructures.test-version.logic.error 16 | (:require [eva.error :refer [deferror-group]])) 17 | 18 | (deferror-group persist 19 | [:bbtree.faulty-persist] 20 | (local-only "This copy cannot be persisted")) 21 | 22 | (deferror-group safety 23 | [:bbtree.safety] 24 | (not-found "A pre-existing buffered btree was expected but not found") 25 | (no-overwrite "Attempting to overwrite newer version of buffered btree") 26 | (unpersisted-changes "This operation cannot be called on a tree with unpersisted changes")) 27 | 28 | (deferror-group fresh-read-err 29 | [:fressian.unreadable [:handler-chain]] 30 | (bbtree-node "Unable to deserialize tree node") 31 | (bbtree-pointer "Unable to deserialize tree pointer") 32 | (bbtree-buffer "Unable to deserialize node buffer") 33 | (bbtree-message "Unable to deserialize bbtree message")) 34 | -------------------------------------------------------------------------------- /dev/src/eva/datastructures/test_version/logic/missing_versioning.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datastructures.test-version.logic.missing-versioning 16 | (:require [eva.datastructures.test-version.logic.versioning :refer [convert-from-v0]] 17 | [eva.datastructures.test-version.logic.nodes :as nodes])) 18 | 19 | (defmethod convert-from-v0 20 | eva.v2.datastructures.bbtree.logic.v0.nodes.BufferedBTreePointer 21 | convert-from-v0:pointer 22 | [o] 23 | (nodes/map->BufferedBTreePointer o)) 24 | -------------------------------------------------------------------------------- /dev/src/eva/datastructures/test_version/logic/state.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datastructures.test-version.logic.state) 16 | 17 | (def ^:dynamic *store* nil) 18 | (def ^:dynamic *node-id-counter* nil) 19 | (def ^:dynamic *transaction-id* nil) 20 | (def ^:dynamic *comparator* nil) 21 | -------------------------------------------------------------------------------- /dev/src/eva/datastructures/test_version/logic/storage.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.datastructures.test-version.logic.storage 16 | (:require [eva.datastructures.test-version.logic.state :as state] 17 | [eva.datastructures.test-version.logic.nodes :as nodes] 18 | [eva.datastructures.test-version.logic.protocols :as protocols] 19 | [eva.v2.datastructures.bbtree.error :refer [raise-storage]] 20 | [eva.v2.datastructures.bbtree.storage :refer [get-nodes put-nodes get-node uuid]] 21 | [barometer.core :as em]) 22 | (:import [eva.v2.storage.value_store.protocols IValueStorage])) 23 | 24 | (def persist-tree-counter 25 | (em/get-or-register em/DEFAULT 'eva.datastructures.test-version.logic.storage:persist-tree.counter 26 | (em/counter "Counts the number of times that 'persist-tree' is called."))) 27 | 28 | (def persist-tree-node-hist 29 | (em/get-or-register em/DEFAULT 'eva.datastructures.test-version.logic.storage:persist-tree-node.histogram 30 | (em/histogram (em/reservoir) "Records the number of nodes persisted at each 'persist-tree' call."))) 31 | 32 | (defn persist-tree 33 | "Takes the IBBTreeSTorageBackend implementation and all new pointer-node pairs. Persists!" 34 | [store all-pairs] 35 | (em/increment persist-tree-counter) 36 | (em/update persist-tree-node-hist (count all-pairs)) 37 | (try (put-nodes store all-pairs) 38 | (catch Exception e 39 | (raise-storage :failure "failed to persist the new tree." {:method 'persist-tree} e)))) 40 | 41 | (defn init-persist 42 | "When a new map or set is created, this persists a pointer to the empty initial root. 43 | Returns the persisted node with its new UUID." 44 | [store node] 45 | (binding [state/*store* store] 46 | (let [node-pointer (nodes/node->pointer node) 47 | node (uuid node (uuid node-pointer))] 48 | (put-nodes store {node-pointer node}) 49 | node))) 50 | -------------------------------------------------------------------------------- /dev/src/eva/dev/logback/init_sqlite.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.dev.logback.init-sqlite 16 | (:require [next.jdbc :as jdbc])) 17 | 18 | (def create-table 19 | {:logging-event 20 | ["CREATE TABLE IF NOT EXISTS logging_event 21 | ( 22 | timestmp BIGINT NOT NULL, 23 | formatted_message TEXT NOT NULL, 24 | logger_name VARCHAR(254) NOT NULL, 25 | level_string VARCHAR(254) NOT NULL, 26 | thread_name VARCHAR(254), 27 | reference_flag SMALLINT, 28 | arg0 VARCHAR(254), 29 | arg1 VARCHAR(254), 30 | arg2 VARCHAR(254), 31 | arg3 VARCHAR(254), 32 | caller_filename VARCHAR(254) NOT NULL, 33 | caller_class VARCHAR(254) NOT NULL, 34 | caller_method VARCHAR(254) NOT NULL, 35 | caller_line CHAR(4) NOT NULL, 36 | event_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT 37 | )"] 38 | 39 | :logging-event-property 40 | ["CREATE TABLE IF NOT EXISTS logging_event_property 41 | ( 42 | event_id BIGINT NOT NULL, 43 | mapped_key VARCHAR (254) NOT NULL, 44 | mapped_value TEXT, 45 | PRIMARY KEY (event_id, mapped_key), 46 | FOREIGN KEY (event_id) REFERENCES logging_event (event_id) 47 | )"] 48 | 49 | :logging-event-exception 50 | ["CREATE TABLE IF NOT EXISTS logging_event_exception 51 | ( 52 | event_id BIGINT NOT NULL, 53 | i SMALLINT NOT NULL, 54 | trace_line VARCHAR (254) NOT NULL, 55 | PRIMARY KEY (event_id, i), 56 | FOREIGN KEY (event_id) REFERENCES logging_event (event_id) 57 | )"]}) 58 | 59 | 60 | (def default-file "logs/eva-dev.sqlite") 61 | (defn connection-uri [file] (str "jdbc:sqlite:" file)) 62 | 63 | (defn -main [& [file]] 64 | (let [file (or file default-file)] 65 | (with-open [conn (jdbc/get-connection (connection-uri file))] 66 | (jdbc/execute! conn (create-table :logging-event)) 67 | (jdbc/execute! conn (create-table :logging-event-property)) 68 | (jdbc/execute! conn (create-table :logging-event-exception))))) 69 | -------------------------------------------------------------------------------- /dev/src/eva/dev/logback/print_appender.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.dev.logback.print-appender 16 | (:require [clojure.string :as str] 17 | [clojure.pprint :refer [pprint]]) 18 | (:import (java.util Date) 19 | (ch.qos.logback.classic.spi ILoggingEvent))) 20 | 21 | (defn event->form [^ILoggingEvent evt] 22 | (tagged-literal (symbol "log" (str/lower-case (str (.getLevel evt)))) 23 | [(Date. (.getTimeStamp evt)) 24 | (tagged-literal 'thread 25 | (.getThreadName evt)) 26 | (tagged-literal 'logger 27 | (.getLoggerName evt)) 28 | (tagged-literal 'msg (.getFormattedMessage evt))])) 29 | 30 | (defn prn-event [^ILoggingEvent evt] (prn (event->form evt))) 31 | (defn pprint-event-map [^ILoggingEvent evt] 32 | (pprint (array-map :level (symbol (str/lower-case (str (.getLevel evt)))) 33 | :logger (symbol (.getLoggerName evt)) 34 | :time (Date. (.getTimeStamp evt)) 35 | :thread (symbol (.getThreadName evt)) 36 | :msg (.getFormattedMessage evt)))) 37 | 38 | (defn simple-print-event [^ILoggingEvent evt] 39 | (println (format "[%s/%s] <%s> %s" 40 | (str (.getLevel evt)) 41 | (.getLoggerName evt) 42 | (.getThreadName evt) 43 | (.getFormattedMessage evt)))) 44 | 45 | (def print-logging-event simple-print-event) 46 | 47 | (defn simple-printing! [] (alter-var-root #'print-logging-event (constantly simple-print-event))) 48 | (defn map-printing! [] (alter-var-root #'print-logging-event (constantly pprint-event-map))) 49 | (defn edn-printing! [] (alter-var-root #'print-logging-event (constantly prn-event))) 50 | -------------------------------------------------------------------------------- /dev/src/eva/dev/repl.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.dev.repl 16 | (:require [clojure.tools.namespace.repl :refer [refresh]] 17 | [eva.error] 18 | [recide.sanex] 19 | [eva.api :as eva])) 20 | 21 | (alter-var-root #'eva.error/*capture-flag* (constantly true)) 22 | (alter-var-root #'recide.sanex/*sanitization-level* (constantly recide.sanex/noop-sanitization)) 23 | -------------------------------------------------------------------------------- /dev/src/eva/dev/tasks/release_trigger.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.dev.tasks.release-trigger 16 | (:import (java.util Date))) 17 | 18 | (defn update-release-trigger [] (spit ".release-trigger" (pr-str (Date.)))) 19 | -------------------------------------------------------------------------------- /dev/test/eva/dev/errorcode_generation_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns eva.dev.errorcode-generation-test 16 | (:require [clojure.test :refer :all] 17 | [eva.dev.tasks.errorcode-generation :as erg])) 18 | 19 | (deftest unit:java-file-has-been-generated 20 | (is (erg/check-equivalence) 21 | "Mismatch between expected errorcode file and actual errorcode file?")) 22 | -------------------------------------------------------------------------------- /docker/docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | eva-db: 4 | ports: 5 | - 3306:3306 6 | 7 | eva: 8 | environment: 9 | - EVA_CATALOG_ADDRESS=http://eva-catalog:3000 10 | ports: 11 | - 9999:9999 12 | - 61616:61616 13 | 14 | eva-catalog: 15 | ports: 16 | - 3000:3000 17 | environment: 18 | - EVA_CATALOG_DATA=/catalog-config.edn 19 | volumes: 20 | - ${SKYNET_TESTING_PATH:-..}/server/test-resources/eva/server/v2/catalog_config.edn:/catalog-config.edn 21 | -------------------------------------------------------------------------------- /docker/docker-compose.repl.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | # REPL container for running transactions against eva locally 5 | lein: 6 | container_name: lein 7 | entrypoint: ["lein"] 8 | image: pandeiro/lein 9 | environment: 10 | - JAVA_OPTS=-Dlogback.configurationFile=/code/server/test-resources/eva/server/v2/local.xml 11 | volumes: 12 | - ..:/code 13 | - ~/.lein/:/root/.lein 14 | - ~/.m2/:/root/.m2 15 | working_dir: /code -------------------------------------------------------------------------------- /docker/docker-compose.skynet.override.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | networks: 4 | default: 5 | external: 6 | name: ${SKYNET_NETWORK} 7 | 8 | volumes: 9 | shared: 10 | external: 11 | name: ${SKYNET_VOLUME} 12 | -------------------------------------------------------------------------------- /docker/docker-compose.transactor.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | # REPL container for running transactions against eva locally 5 | lein: 6 | container_name: lein 7 | entrypoint: ["lein"] 8 | image: pandeiro/lein 9 | environment: 10 | - USE_STD_OUT_TELEMETRY=false 11 | - LOGBACK_LOG_LEVEL=DEBUG 12 | - EVA_SERVER_MODE=TRANSACTORS_NODE 13 | - EVA_TRANSACTORS_CONFIG=server/test-resources/eva/server/v2/local_transactors_test_config.clj 14 | - EVA_TRANSACTOR_GROUPS=eva-test 15 | - JAVA_OPTS=-Dlogback.configurationFile=/code/server/test-resources/eva/server/v2/local.xml -XX:MaxJavaStackTraceDepth=1000000 16 | volumes: 17 | - .:/code 18 | - ~/.lein/:/root/.lein 19 | - ~/.m2/:/root/.m2 20 | working_dir: /code 21 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | # use an eva mysql database with prepopulated data supporting data platform services 5 | eva-db: 6 | build: ./eva-db 7 | environment: 8 | - MYSQL_ROOT_PASSWORD=notasecret 9 | - MYSQL_DATABASE=eva 10 | - MYSQL_USER=eva 11 | - MYSQL_PASSWORD=notasecret 12 | 13 | activemq: 14 | image: webcenter/activemq:5.14.3 15 | environment: 16 | - ACTIVEMQ_ACTIVEMQ_USERS_EVA="eva" 17 | 18 | eva-catalog: 19 | image: ${SKYNET_APPLICATION_EVA_CATALOG_LEGACY:-workivadocker/eva-catalog:latest-release} 20 | healthcheck: 21 | test: wget -q -O - http://eva-catalog:3000/status || exit 1 22 | 23 | eva: 24 | depends_on: 25 | - activemq 26 | - eva-db 27 | - eva-catalog 28 | image: ${SKYNET_APPLICATION_EVA:-workivadocker/eva:latest-release} 29 | environment: 30 | - EVA_BROKER_HOST=activemq 31 | - EVA_TRANSACTORS_CONFIG=/local_transactors_test_config.clj 32 | - LOGBACK_LOG_LEVEL=DEBUG 33 | - EVA_SERVER_MODE=TRANSACTORS_NODE 34 | - EVA_DEFAULT_TRANSACTOR=true 35 | - LOGBACK_APPENDER=STDOUT 36 | - JAVA_OPTS=-Dlogback.configurationFile=/local_logback.xml 37 | healthcheck: 38 | test: wget -q -O- http://eva:9999/status || exit 1 39 | restart: on-failure 40 | -------------------------------------------------------------------------------- /docker/eva-db/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mysql:5.7 2 | 3 | COPY ./init.sql /docker-entrypoint-initdb.d/init-eva-db.sql 4 | ENTRYPOINT ["docker-entrypoint.sh"] 5 | EXPOSE 3306 6 | CMD ["mysqld"] 7 | -------------------------------------------------------------------------------- /docker/eva-db/init.sql: -------------------------------------------------------------------------------- 1 | -- DROP TABLE eva_kv; 2 | 3 | CREATE TABLE eva_kv ( 4 | namespace varchar(640) NOT NULL, 5 | id varchar(640) NOT NULL, 6 | attrs text, 7 | val longblob, 8 | CONSTRAINT pk_ns_id PRIMARY KEY (namespace, id) 9 | ) 10 | ENGINE=INNODB 11 | -------------------------------------------------------------------------------- /docs/api/clojure/highlight/solarized-light.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | background: #fdf6e3; 12 | color: #657b83; 13 | } 14 | 15 | .hljs-comment, 16 | .hljs-quote { 17 | color: #93a1a1; 18 | } 19 | 20 | /* Solarized Green */ 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-addition { 24 | color: #859900; 25 | } 26 | 27 | /* Solarized Cyan */ 28 | .hljs-number, 29 | .hljs-string, 30 | .hljs-meta .hljs-meta-string, 31 | .hljs-literal, 32 | .hljs-doctag, 33 | .hljs-regexp { 34 | color: #2aa198; 35 | } 36 | 37 | /* Solarized Blue */ 38 | .hljs-title, 39 | .hljs-section, 40 | .hljs-name, 41 | .hljs-selector-id, 42 | .hljs-selector-class { 43 | color: #268bd2; 44 | } 45 | 46 | /* Solarized Yellow */ 47 | .hljs-attribute, 48 | .hljs-attr, 49 | .hljs-variable, 50 | .hljs-template-variable, 51 | .hljs-class .hljs-title, 52 | .hljs-type { 53 | color: #b58900; 54 | } 55 | 56 | /* Solarized Orange */ 57 | .hljs-symbol, 58 | .hljs-bullet, 59 | .hljs-subst, 60 | .hljs-meta, 61 | .hljs-meta .hljs-keyword, 62 | .hljs-selector-attr, 63 | .hljs-selector-pseudo, 64 | .hljs-link { 65 | color: #cb4b16; 66 | } 67 | 68 | /* Solarized Red */ 69 | .hljs-built_in, 70 | .hljs-deletion { 71 | color: #dc322f; 72 | } 73 | 74 | .hljs-formula { 75 | background: #eee8d5; 76 | } 77 | 78 | .hljs-emphasis { 79 | font-style: italic; 80 | } 81 | 82 | .hljs-strong { 83 | font-weight: bold; 84 | } 85 | -------------------------------------------------------------------------------- /docs/api/java/allclasses-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/api/java/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/api/java/eva/error/v1/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | eva.error.v1 7 | 8 | 9 | 10 | 11 |

eva.error.v1

12 |
13 |

Interfaces

14 | 18 |

Enums

19 | 22 |

Exceptions

23 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/api/java/eva/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | eva 7 | 8 | 9 | 10 | 11 |

eva

12 |
13 |

Interfaces

14 | 23 |

Classes

24 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/api/java/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview List 7 | 8 | 9 | 10 | 11 | 12 |
13 |

Packages

14 | 18 |
19 |

 

20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/api/java/package-list: -------------------------------------------------------------------------------- 1 | eva 2 | eva.error.v1 3 | -------------------------------------------------------------------------------- /docs/api/java/script.js: -------------------------------------------------------------------------------- 1 | function show(type) 2 | { 3 | count = 0; 4 | for (var key in methods) { 5 | var row = document.getElementById(key); 6 | if ((methods[key] & type) != 0) { 7 | row.style.display = ''; 8 | row.className = (count++ % 2) ? rowColor : altColor; 9 | } 10 | else 11 | row.style.display = 'none'; 12 | } 13 | updateTabs(type); 14 | } 15 | 16 | function updateTabs(type) 17 | { 18 | for (var value in tabs) { 19 | var sNode = document.getElementById(tabs[value][0]); 20 | var spanNode = sNode.firstChild; 21 | if (value == type) { 22 | sNode.className = activeTableTab; 23 | spanNode.innerHTML = tabs[value][1]; 24 | } 25 | else { 26 | sNode.className = tableTab; 27 | spanNode.innerHTML = "" + tabs[value][1] + ""; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/attr-based-modelling/plantuml-src/classes-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/docs/attr-based-modelling/plantuml-src/classes-simple.png -------------------------------------------------------------------------------- /docs/attr-based-modelling/plantuml-src/classes-simple.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | ManualEntry --|> Source 3 | ManualEntry : description 4 | ManualEntry : amount 5 | ReceiptItem --|> Source 6 | CSVRow --|> Source 7 | Expense --> "1" Source : comes from > 8 | Receipt *-- "n" ReceiptItem : items 9 | CSVImport *-- "n" CSVRow : rows 10 | Expense : amount 11 | Expense : made_at 12 | CSVRow : text 13 | ReceiptItem : text 14 | @enduml 15 | -------------------------------------------------------------------------------- /docs/attr-based-modelling/plantuml-src/classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bowbahdoe/eva/6fba6fc259e49347d8e9be81b3f828561412b972/docs/attr-based-modelling/plantuml-src/classes.png -------------------------------------------------------------------------------- /docs/attr-based-modelling/plantuml-src/classes.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | ManualEntry --|> Source 3 | ManualEntry : description 4 | ManualEntry : amount 5 | ReceiptItem --|> Source 6 | CSVRow --|> Source 7 | Expense --> "1" Source : comes from > 8 | Receipt *-- "n" ReceiptItem : items 9 | CSVImport *-- "n" CSVRow : rows 10 | Expense : amount 11 | Expense : made_at 12 | CSVRow : text 13 | ReceiptItem : text 14 | Source --> "1" Source : **overrides** > 15 | @enduml 16 | -------------------------------------------------------------------------------- /docs/differences.md: -------------------------------------------------------------------------------- 1 | This document enumerates some differences between Eva and Datomic 2 | 3 | * Eva has no implementation of the top-level functions: 4 | * `sync` 5 | * `filter` 6 | * `since` 7 | * `tx-report-queue` 8 | * The `transact` function / core data model in Eva does not currently support: 9 | * Byte-type attributes 10 | * note: Eva has a partial implementation that has been tested that has issues 11 | * Excision 12 | * Schema alterations (adding new schema is supported, modifying extant schema is not) 13 | * Inferring of installation attributes on transaction data 14 | * Inferring implicit `:db/id`s at the root level of a map (implicit `:db/ids` on nested entity maps is supported) 15 | * String-type tempids 16 | * Attributes with `:db/noHistory`, `:db/fulltext`, `:db/index` 17 | * note: all non-byte attributes are indexed in AVET by default 18 | * Database functions written in Java 19 | * Eva's `q` api does not support: 20 | * A subset of the built-in expression functions and predicates 21 | * Eva's `pull` api does not support: 22 | * The "Attributes with Options" sub-grammar 23 | * Eva has a few specific features that are supported that Datomic does not: 24 | * There are a few minor API functions we have added or renamed 25 | * Eva's query engine also has more general support for cross-database queries 26 | * Eva's `connect` call is passed a baroque configuration map, whereas datomic uses a uri 27 | * Eva has a more typeful exception set 28 | * Eva's Client model is quite distinct from Datomic Cloud's Client 29 | -------------------------------------------------------------------------------- /docs/local-v2-h2.md: -------------------------------------------------------------------------------- 1 | # Using a fully local persistent h2 connection with the v2 API 2 | 3 | 1. Create the file you want to use as the backing db 4 | ```bash 5 | $> touch example/path/to/my.db 6 | ``` 7 | 8 | 2. Start up eva, build (And save!) a config similar to the following, 9 | generating your own random UUIDs: 10 | 11 | ```clojure 12 | (def config {:local true, 13 | :eva.v2.database.core/id #uuid "8b9b56bc-25a9-4ecc-8edf-ee5fb4b93509", 14 | :eva.v2.storage.value-store.core/partition-id #uuid "8230ebe8-84c0-45b8-b0d9-a5752c9fa031", 15 | :eva.v2.storage.block-store.types/storage-type :eva.v2.storage.block-store.types/sql, 16 | :eva.v2.storage.block-store.impl.sql/db-spec 17 | {:classname "org.h2.Driver", 18 | :subprotocol "h2", 19 | :subname "example/path/to/my.db", 20 | :user "sa"}}) 21 | ``` 22 | 23 | 3. Connect! If you use the same config and the file is accessible, 24 | you should have a persistent fully-local connection ready to go 25 | 26 | ```clojure 27 | (eva.api/connect config) 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/technical-faq.md: -------------------------------------------------------------------------------- 1 | This document contains some technical questions we've accumulated over time 2 | while supporting Eva in development and production. 3 | 4 | ### 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eva", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/Workiva/eva.git" 12 | }, 13 | "author": "", 14 | "license": "", 15 | "bugs": { 16 | "url": "https://github.com/Workiva/eva/issues" 17 | }, 18 | "homepage": "https://github.com/Workiva/eva#readme", 19 | "dependencies": { 20 | "markdown-toc": "^1.2.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scripts/ci/pull_composes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -d compose_remote/ ]; then 4 | echo deleting existing compose_remote directory 5 | rm -rf compose_remote 6 | fi 7 | echo Pulling compose files from remotes 8 | if [ ! -d compose_remote/ ]; then 9 | echo Creating compose_remote directory 10 | mkdir compose_remote 11 | fi 12 | 13 | cd compose_remote 14 | mkdir eva-catalog && cd eva-catalog 15 | git init && git remote add origin git@github.com:Workiva/eva-catalog.git 16 | git fetch --tags 17 | echo Checking out compose for eva-catalog at $(git describe --tags $(git rev-list --tags --max-count=1)) 18 | git checkout $(git describe --tags $(git rev-list --tags --max-count=1)) -- docker/docker-compose.yml 19 | cd ../.. 20 | cp compose_remote/eva-catalog/docker/docker-compose.yml ./compose_remote/local-compose-eva-catalog.yml 21 | rm -rf compose_remote/eva-catalog 22 | echo local-compose-eva-catalog.yaml cloned to compose_remote dir 23 | -------------------------------------------------------------------------------- /scripts/ci/workiva-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | [ -n "$DEBUG" ] && set -x 5 | 6 | SOURCE="${BASH_SOURCE[0]}" 7 | while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink 8 | base_dir="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 9 | SOURCE="$(readlink "$SOURCE")" 10 | [[ $SOURCE != /* ]] && SOURCE="$base_dir/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located 11 | done 12 | base_dir="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 13 | 14 | lein clean 15 | if [[ -z ${SKIP_TESTS+x} || ${SKIP_TESTS} == "false" ]]; then 16 | lein with-profile +aot,-dynamodb-local test 17 | fi 18 | lein jar 19 | mv ./target/eva-*.jar ./ 20 | lein clean 21 | 22 | lein with-profile +deployment uberjar 23 | mv ./target/transactor.jar ./ 24 | lein clean 25 | 26 | lein docs 27 | cd docs/api && tar cvfz "${base_dir}/eva-api-docs.tgz" ./ 28 | mv "${base_dir}/eva-api-docs.tgz" ../../ 29 | cd "${base_dir}" 30 | -------------------------------------------------------------------------------- /scripts/image/run_service.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Abort script on any error 4 | set -e 5 | 6 | if [ -f /usr/local/bin/set_mem_constraints.sh ]; then 7 | source /usr/local/bin/set_mem_constraints.sh 8 | else 9 | source "$(dirname "$0")"/set_mem_constraints.sh 10 | fi 11 | 12 | 13 | if [ -n $LOGBACK_CONFIG ] ; then 14 | JAVA_OPTS="${JAVA_OPTS} -Dlogback.configurationFile=${LOGBACK_CONFIG}" 15 | fi 16 | 17 | ## Support for enabling the YourKit Profiling Agent 18 | yourkit_options="" 19 | YOURKIT_AGENT_PATH="${YOURKIT_AGENT_PATH:-/opt/yourkit-agent/linux-x86-64/libyjpagent.so}" 20 | YOURKIT_AGENT_PORT="${YOURKIT_AGENT_PORT:-10001}" 21 | YOURKIT_FLAG=$(echo "${YOURKIT_AGENT_ENABLE:-false}" | awk '{print tolower($0)}') 22 | 23 | if [ "$YOURKIT_FLAG" == true ] ; then 24 | if [ -e "${YOURKIT_AGENT_PATH}" ] ; then 25 | yourkit_options="-agentpath:${YOURKIT_AGENT_PATH}=port=${YOURKIT_AGENT_PORT}" 26 | echo "Enabling YourKit Profiling Agent" 27 | else 28 | echo "WARNING: Cannot enable YourKit Profiling Agent!" 29 | echo " YourKit Agent lib does not exist at: ${YOURKIT_AGENT_PATH}" 30 | fi 31 | fi 32 | 33 | echo "Launching transactor with java opts: $JAVA_OPTS $yourkit_options" 34 | exec java -server ${JAVA_OPTS} ${yourkit_options} \ 35 | -XX:OnError='echo "Fatal JVM Error (pid: %p)"' \ 36 | -XX:OnOutOfMemoryError='echo "Fatal JVM OutOfMemoryError (pid: %p)"' \ 37 | -jar /eva-server/transactor.jar /eva-server/server-config.edn 38 | -------------------------------------------------------------------------------- /server/java-src/eva/Server.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Workiva Inc. 2 | // 3 | // Licensed under the Eclipse Public License 1.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://opensource.org/licenses/eclipse-1.0.php 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package eva; 16 | 17 | import ch.qos.logback.classic.LoggerContext; 18 | import clojure.java.api.Clojure; 19 | import clojure.lang.IFn; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | public final class Server { 24 | static Logger LOG = LoggerFactory.getLogger(Server.class); 25 | 26 | static { 27 | IFn require = Clojure.var("clojure.core", "require"); 28 | require.invoke(Clojure.read("eva.server.v2")); 29 | } 30 | 31 | private static void shutdown(int delayMs) { 32 | LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); 33 | loggerContext.stop(); 34 | try { 35 | Thread.sleep(delayMs); 36 | } catch (InterruptedException e) { 37 | // continue if interrupted 38 | } 39 | System.exit(1); 40 | } 41 | 42 | public static void main(String[] args) { 43 | try { 44 | IFn startServer = Clojure.var("eva.server.v2", "start-server!"); 45 | startServer.invoke(args); 46 | } 47 | catch(Throwable t) { 48 | System.out.println("Unhandled server error; printed this message to stdout; should also see an error log :/"); 49 | LOG.error("Unhandled Server error; Aborting!", t); 50 | shutdown(5000); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /server/src/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /server/test-resources/eva/server/v2/local.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} - %X{apiVersion} - %X{correlationId} - [%thread] %-5level %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /server/test-resources/eva/server/v2/local_transactors_test_config.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (configure-from-catalog 16 | ;; Address of Catalog 17 | (env "EVA_CATALOG_ADDRESS" "http://eva-catalog:3000") 18 | 19 | { 20 | ;; transactor-groups to manage 21 | :transactor-groups 22 | (env-parse "EVA_TRANSACTOR_GROUPS" 23 | parse-comma-sep-list) 24 | 25 | ;; also manage any database not in a transactor-group? 26 | :default-transactor? 27 | (env-parse "EVA_DEFAULT_TRANSACTOR" 28 | parse-bool 29 | false) 30 | 31 | ;; Apply these updates to alter *every* config for every database configuration 32 | ;; retrieved from the catalog 33 | :updates 34 | [[override-sql-storage-key :user (env "EVA_STORAGE_SQL_USER" "eva")] 35 | 36 | [override-sql-storage-key :password (env "EVA_STORAGE_SQL_PASSWORD" 37 | "notasecret")]] 38 | }) 39 | -------------------------------------------------------------------------------- /server/tests/v2/startup_test.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright 2015-2019 Workiva Inc. 2 | ;; 3 | ;; Licensed under the Eclipse Public License 1.0 (the "License"); 4 | ;; you may not use this file except in compliance with the License. 5 | ;; You may obtain a copy of the License at 6 | ;; 7 | ;; http://opensource.org/licenses/eclipse-1.0.php 8 | ;; 9 | ;; Unless required by applicable law or agreed to in writing, software 10 | ;; distributed under the License is distributed on an "AS IS" BASIS, 11 | ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | ;; See the License for the specific language governing permissions and 13 | ;; limitations under the License. 14 | 15 | (ns v2.startup-test 16 | (:require [eva.server.v2 :as v2] 17 | [clojure.test :refer :all])) 18 | 19 | (defn test-init-db [db] 20 | (let [sleep-time (if (= db 0) 200 1)] 21 | (Thread/sleep sleep-time) 22 | (* db 10))) 23 | 24 | (deftest unit:uncoordinated-pmap 25 | (let [started-dbs (#'v2/pmap "test-init-db" test-init-db (range 100))] 26 | (is (>= (nth started-dbs 0) 10)) 27 | (is (= (nth started-dbs 99) 0)) ;; the element which takes longest time to process does not block other elements 28 | (is (= (reduce + (range 0 1000 10)) 29 | (reduce + started-dbs))))) 30 | -------------------------------------------------------------------------------- /skynet.yaml: -------------------------------------------------------------------------------- 1 | name: eva_legacy_tests 2 | 3 | image: drydock.workiva.net/workiva/smithy-runner-generator:340896 4 | 5 | run: 6 | on-pull-request: true 7 | when-branch-name-is: .+ 8 | 9 | requires: 10 | Workiva/eva: docker 11 | 12 | scripts: 13 | # Spin up Docker containers 14 | - docker-compose version 15 | - >- 16 | docker-compose -f docker/docker-compose.yml 17 | -f docker/docker-compose.override.yml 18 | -f docker/docker-compose.skynet.override.yml 19 | up --build --force-recreate -d 20 | - >- 21 | docker-compose -f docker/docker-compose.yml 22 | -f docker/docker-compose.override.yml 23 | -f docker/docker-compose.skynet.override.yml 24 | logs -f > /shared/logs/docker-compose.log & 25 | # Wait for service to start up 26 | - wget -O /dev/stdout --tries=10 --wait=2 --retry-connrefused --content-on-error http://eva:9999/status 27 | 28 | timeout: moderate 29 | 30 | artifacts: 31 | - /shared/logs 32 | -------------------------------------------------------------------------------- /transactor.Dockerfile: -------------------------------------------------------------------------------- 1 | # Prepare Final Image 2 | FROM openjdk:8u181-jre-alpine3.8 3 | 4 | ## Setup Environment 5 | ### Alpine does not come with bash by default 6 | ### As well as some required c libraries for yourkit https://www.yourkit.com/docs/java/help/docker.jsp 7 | RUN apk add --update bash curl libc6-compat nss 8 | 9 | ENV EVA_SERVER_STATUS_HTTP_PORT 9999 10 | 11 | EXPOSE 5445/tcp 12 | EXPOSE 9999/tcp 13 | 14 | ## Copy in Artifact 15 | WORKDIR /eva-server 16 | RUN chown root:root /eva-server 17 | COPY target/transactor.jar /eva-server/ 18 | RUN chmod -R 755 /eva-server 19 | 20 | ## Copy in Scripts 21 | COPY ./scripts/image/set_mem_constraints.sh /usr/local/bin/set_mem_constraints.sh 22 | COPY ./scripts/image/run_service.sh /usr/local/bin/run_service.sh 23 | COPY server/test-resources/eva/server/v2/local_transactors_test_config.clj /local_transactors_test_config.clj 24 | COPY server/test-resources/eva/server/v2/local.xml /local_logback.xml 25 | 26 | ### Ensure scripts are executable 27 | RUN chmod +x /usr/local/bin/set_mem_constraints.sh 28 | RUN chmod +x /usr/local/bin/run_service.sh 29 | 30 | ### Update Packages for latest Security Updates 31 | ARG BUILD_ID 32 | RUN apk update && apk upgrade 33 | USER nobody 34 | HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=3 CMD [ "curl", "--fail" "http://localhost:9999/status", "||", "exit", "1" ] 35 | CMD [ "sh", "/usr/local/bin/run_service.sh" ] 36 | --------------------------------------------------------------------------------