feat: extract transport-agnostic service layer from Thrift handlers#594
Merged
feat: extract transport-agnostic service layer from Thrift handlers#594
Conversation
Extracts experiment business logic from AiravataServerHandler into a clean service class with explicit dependency injection. Uses isSharingEnabled() helper to safely default to false when the setting is absent.
Extract gateway and notification business logic from AiravataServerHandler into GatewayService and NotificationService with full Mockito test coverage.
…layer Replace inline gateway and notification method bodies in AiravataServerHandler with ThriftAdapter one-liners delegating to GatewayService and NotificationService.
Extract credential business logic from AiravataServerHandler into CredentialService, using RequestContext instead of AuthzToken claims and direct sharingHandler.userHasAccess() for permission checks.
Replace all 6 credential method bodies in AiravataServerHandler with ThriftAdapter one-liners delegating to CredentialService.
Extracts createProject, updateProject, deleteProject, getProject, getUserProjects, and searchProjects business logic from AiravataServerHandler into a dedicated ProjectService following the established service layer pattern.
Replace the inline business logic in all 6 project methods (createProject, updateProject, deleteProject, getProject, getUserProjects, searchProjects) with ThriftAdapter one-liners delegating to ProjectService.
…ata movement Extracts all resource-related registry delegates into ResourceService covering compute resources, storage resources, job submission interfaces (LOCAL, SSH, SSHFork, Cloud, UNICORE), data movement interfaces (LOCAL, SCP, UNICORE, GridFTP), resource job managers, and batch queues. Includes 16 unit tests covering each sub-domain.
Replace all compute resource, storage resource, job submission, data movement, resource job manager, and batch queue method bodies in AiravataServerHandler with ThriftAdapter one-liners delegating to ResourceService.
Extracts application module, deployment, and interface logic from AiravataServerHandler into a dedicated service layer class, including sharing/permission logic for deployments. Adds 15 unit tests covering all three sub-domains.
Adds getExperimentStatistics, getExperimentsInProject, getUserExperiments, getDetailedExperimentTree, updateExperiment, updateExperimentConfiguration, updateResourceScheduleing, validateExperiment, getJobStatuses, getJobDetails. Rewires corresponding AiravataServerHandler methods to ThriftAdapter one-liners.
Extracts all gateway resource profile operations (CRUD, compute/storage preferences, SSH account provisioners) from AiravataServerHandler into GatewayResourceProfileService. Rewires handler methods to ThriftAdapter one-liners.
Extracts all user resource profile operations (CRUD, compute/storage preferences, queue statuses) from AiravataServerHandler into UserResourceProfileService. Rewires handler methods to ThriftAdapter one-liners.
…ervice layer Rewires all remaining experiment methods (getExperimentStatistics, getExperimentsInProject, getUserExperiments, getDetailedExperimentTree, updateExperiment, updateExperimentConfiguration, updateResourceScheduleing, validateExperiment, getJobStatuses, getJobDetails) and all gateway and user resource profile methods in AiravataServerHandler to ThriftAdapter one-liners delegating to the new service classes.
Extracts registerDataProduct, getDataProduct, registerReplicaLocation, getParentDataProduct, and getChildDataProducts into DataProductService. Rewires AiravataServerHandler to delegate via ThriftAdapter.
Extracts shareResourceWithUsers, shareResourceWithGroups, revoke* variants, getAllAccessible*/getAllDirectlyAccessible* methods, and userHasAccess into ResourceSharingService. Rewires AiravataServerHandler to delegate via ThriftAdapter.
Extracts createGroupResourceProfile (with sharing rollback), updateGroupResourceProfile, getGroupResourceProfile, removeGroupResourceProfile, getGroupResourceList, removeGroupCompute*, getGroupCompute*/getBatchQueue*, and getGatewayGroups into GroupResourceProfileService. Includes credential validation and sharing entity management. Rewires AiravataServerHandler to delegate via ThriftAdapter.
Extracts getParser, saveParser, listAllParsers, removeParser, getParsingTemplate, getParsingTemplatesForExperiment, saveParsingTemplate, removeParsingTemplate, and listAllParsingTemplates into ParserService. Rewires AiravataServerHandler to delegate via ThriftAdapter.
- Add isUserExists to GatewayService - Add fetchIntermediateOutputs, getIntermediateOutputProcessStatus, and launchExperiment to ExperimentService - Add tests for new methods in ExperimentServiceTest and GatewayServiceTest
…elete orphaned helpers - isUserExists, fetchIntermediateOutputs, getIntermediateOutputProcessStatus, and launchExperiment now delegate to service layer - Delete orphaned private helpers: validateString, submitExperiment, submitCancelExperiment, submitExperimentIntermediateOutputsEvent, shareEntityWithAdminGatewayGroups, userHasAccessInternal, getResourceType, createManageSharingPermissionTypeIfMissing, retrieveGatewayGroups
- Accept RegistryServerHandler in constructor (backwards-compatible overload kept) - Implement retrieveGatewayGroups helper using registry - validateAdminGroupNotRevoked now checks actual GatewayGroups admin group id - Pass registryHandler from AiravataServerHandler constructor
Consolidate duplicated isSharingEnabled(), userHasAccess(), retrieveGatewayGroups(), shareEntityWithAdminGatewayGroups(), and createManageSharingPermissionTypeIfMissing() from ExperimentService, ProjectService, CredentialService, ApplicationCatalogService, GatewayService, GroupResourceProfileService, and ResourceSharingService into a single SharingHelper utility class.
…tAdapter ServiceNotFoundException was incorrectly mapped to ExperimentNotFoundException, which is semantically wrong for non-experiment resources. Map to AiravataSystemException with a "not found" prefix message instead, since there is no generic Thrift not-found exception type.
Move initSharingRegistry() and postInitDefaultGateway() calls out of the constructor into a new public initialize() method. The constructor now only wires dependencies, while initialization side effects are deferred to initialize(), which is called explicitly by AiravataServer after construction.
…rvice Migrated getResourceStorageInfo, getStorageDirectoryInfo, resolveComputeStorageInfoContext, and resolveStorageStorageInfoContext from AiravataServerHandler into ResourceService. Handler methods are now pure ThriftAdapter one-liners. ResourceService gains a GroupResourceProfileService dependency for the group preference fallback chain.
Extracted doesUserHaveSSHAccount, isSSHSetupCompleteForUserComputeResourcePreference, and setupUserComputeResourcePreferencesForSSH from AiravataServerHandler into a dedicated SSHAccountService. Handler methods are now ThriftAdapter one-liners. Includes 6 unit tests covering all methods and error paths.
Moved group resource profile lookup from AiravataServerHandler.launchExperiment into ExperimentService.launchExperiment, removing the List<GroupResourceProfile> parameter. ExperimentService gains an optional GroupResourceProfileService set via setter. Handler method is now a single ThriftAdapter.executeVoid call.
- AbstractIntegrationTest base class with @tag("integration") and MariaDB container - SharingServiceIntegrationTest: rewrites monolithic sharing test into 13 ordered tests - ExperimentRepositoryIntegrationTest: template for repository integration tests - Surefire configured to exclude integration tests by default (run with -Dgroups=integration)
…orts - README: document the 14-service architecture and transport-agnostic design - Dockerfile: remove obsolete per-service ports (all Thrift on 8930)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extracts all business logic from
AiravataServerHandlerinto a transport-agnostic service layer (org.apache.airavata.service.*), enabling future REST/gRPC transports without duplicating logic.ThriftAdapterutility eliminates boilerplate try/catch andRequestContextconstruction — handler methods are one-liner delegatesSharingHelperconsolidates duplicated sharing utilities across servicesRequestContextprovides transport-agnostic identity (userId, gatewayId, claims)EventPublisherwraps RabbitMQ messaging with typed methodsAbstractIntegrationTestbase with Testcontainers MariaDB, surefire tag filtering (@Tag("integration"))ThriftAdapterinitSharingRegistry,postInitDefaultGateway) extracted toinitialize()methodArchitecture
Test plan
mvn test -DexcludedGroups=integration)mvn compilesucceeds for full projectdocker compose up -d+mvn exec:java(verified: DB init, RabbitMQ, ZooKeeper all connect)mvn test -Dgroups=integration -DexcludedGroups=""(requires Docker)🤖 Generated with Claude Code