Skip to content

refactor: gRPC/Armeria migration with full module boundary enforcement#612

Merged
yasithdev merged 1 commit into
masterfrom
feat/grpc-armeria-migration
Apr 10, 2026
Merged

refactor: gRPC/Armeria migration with full module boundary enforcement#612
yasithdev merged 1 commit into
masterfrom
feat/grpc-armeria-migration

Conversation

@yasithdev
Copy link
Copy Markdown
Contributor

@yasithdev yasithdev commented Apr 1, 2026

Summary

Complete modernization of Airavata's service architecture — replaces Thrift with gRPC/Armeria, consolidates entities (-107K lines net), enforces module boundaries, adds server-side user storage API, and provides a transport-agnostic Python SDK facade.

1,681 files changed | 88,340 insertions | 193,478 deletions

What Changed

Service Communication: Thrift → gRPC/Armeria

  • Unified server on port 9090: gRPC + REST (HTTP/JSON transcoding) via Armeria
  • 23 proto service definitions, 249 RPC methods, all with REST annotations
  • Centralized GrpcStatusMapper for consistent error codes across all handlers
  • GrpcAuthInterceptor for Bearer token authentication
  • DocService at /docs

Entity Consolidation

  • Remove 55 dead entity/PK classes across 5 modules
  • Consolidate status/error/IO entities with discriminator columns
  • Convert child tables to JSON columns
  • Flyway V1 (baseline) + V2 (consolidation) covering all 76 entity tables

Module Boundary Enforcement

~45 entities/repositories relocated to correct bounded-context modules. All cross-module access via shared interfaces.

Move From → To
App catalog + parsers compute → research
Agent deployment info agent → compute
Community users credential → iam
Usage reporting commands iam → compute
Tags, resources, resource stars research → sharing
User storage preferences storage → compute
Resource scheduling entities orchestration → compute

Server-Side User Storage API (NEW)

New UserStorageService gRPC API (13 RPCs) for managing user files on any registered storage resource:

RPC REST Path Description
UploadFile POST /api/v1/user-storage/{id}/files/{path} Upload file to storage
DownloadFile GET /api/v1/user-storage/{id}/files/{path} Download file content
FileExists GET /api/v1/user-storage/{id}/files/{path}:exists Check file existence
DirExists GET /api/v1/user-storage/{id}/dirs/{path}:exists Check directory existence
ListDir GET /api/v1/user-storage/{id}/dirs/{path} List directory contents
DeleteFile DELETE /api/v1/user-storage/{id}/files/{path} Delete file
DeleteDir DELETE /api/v1/user-storage/{id}/dirs/{path} Delete directory
MoveFile POST /api/v1/user-storage/{id}/files/{path}:move Move/rename file
CreateDir POST /api/v1/user-storage/{id}/dirs/{path} Create directory
CreateSymlink POST /api/v1/user-storage/{id}/files/{path}:symlink Create symlink
GetFileMetadata GET /api/v1/user-storage/{id}/files/{path}:metadata Get file metadata
ListExperimentDir GET /api/v1/user-storage/experiments/{id}/dirs/{path} List experiment dir
GetDefaultStorageResourceId GET /api/v1/user-storage/default-storage-resource Get default storage

Eliminates client-side storage backends — portal just calls the SDK.

Python SDK: Transport-Agnostic Facade

from airavata_sdk import AiravataClient

client = AiravataClient(host, port, token, gateway_id)
client.research.create_experiment(...)
client.storage.upload_file(path, content, name)
client.sharing.share_resource_with_users(...)
Sub-client Methods Wraps
client.compute 68 ResourceService, Gateway/Group/User ResourceProfile
client.storage 28 Storage resources, data movement, user storage operations
client.credential 10 CredentialService
client.research 107 Experiment, Project, AppCatalog, Parser, DataProduct, Notification + 5 research services
client.iam 30 GatewayService, IamAdmin, UserProfile
client.sharing 81 SharingService, GroupManager
client.agent 24 AgentInteraction, Plan

Infrastructure

  • Dockerfile health check: port 9090, /internal/actuator/health
  • persistence.xml regenerated (76 entities match code)
  • Explicit @Table annotations on all entities
  • All cross-module repo instantiation replaced with interface injection

Modules After Refactor

Module Responsibility
agent-service Agent sidecar lifecycle, bidirectional gRPC, execution state
compute-service HPC resource catalog, profiles, scheduling, agent deployment
credential-service SSH keys, passwords, credential store
storage-service Storage resources, data movement, user storage file API
research-service Research catalog, app catalog, parsing, data products, replicas
iam-service Identity, access management, gateways, user profiles
sharing-service Permissions, groups, tags, resource discovery
orchestration-service Process/task/job execution, workflow orchestration

Test Plan

  • mvn clean compile -T4 — BUILD SUCCESS
  • mvn test -T4 — 23/23 tests pass
  • Python SDK imports verified (7 sub-clients, 348 methods)
  • Architect review: no circular deps, no orphaned files, no stale references
  • LaunchExperiment flow verified — server handles storage setup, no client pre-processing needed
  • tilt up — verify health at http://localhost:9090/internal/actuator/health
  • Integration tests: mvn test -pl airavata-api -Dgroups=runtime

🤖 Generated with Claude Code

@yasithdev yasithdev force-pushed the feat/grpc-armeria-migration branch from 73ff17e to e838c4d Compare April 4, 2026 22:04
@yasithdev yasithdev changed the title Replace Thrift with gRPC+Armeria, modularize airavata-api, rewrite Python SDK refactor: gRPC Armeria migration — module boundary enforcement and service decomposition Apr 4, 2026
@yasithdev yasithdev changed the title refactor: gRPC Armeria migration — module boundary enforcement and service decomposition refactor: gRPC/Armeria migration + module boundary enforcement + entity placement Apr 6, 2026
@yasithdev yasithdev force-pushed the feat/grpc-armeria-migration branch 3 times, most recently from 76915fd to f1c6024 Compare April 7, 2026 21:33
@yasithdev yasithdev changed the title refactor: gRPC/Armeria migration + module boundary enforcement + entity placement refactor: gRPC/Armeria migration with full module boundary enforcement Apr 7, 2026
@yasithdev yasithdev force-pushed the feat/grpc-armeria-migration branch 4 times, most recently from f03e1d2 to 52dacc8 Compare April 8, 2026 08:32
Complete modernization of Airavata's service architecture. Server starts
and serves gRPC + REST on port 9090. All tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@yasithdev yasithdev force-pushed the feat/grpc-armeria-migration branch from 52dacc8 to b3ab528 Compare April 8, 2026 10:28
@yasithdev yasithdev merged commit f250f6d into master Apr 10, 2026
7 of 8 checks passed
yasithdev added a commit to yasithdev/airavata that referenced this pull request Apr 12, 2026
* refactor: gRPC/Armeria migration with full module boundary enforcement (apache#612)

Complete modernization of Airavata's service architecture. Server starts
and serves gRPC + REST on port 9090. All tests pass.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: airavata server fixes, SDK facades, auto-generated SFTP keys

- Fix sharing EntityRepository null-safe casting
- Fix ResearchMapper projectId/projectID mapping
- Update credential store encryption and key generation
- SDK facade clients updated for gRPC service alignment
- Tiltfile auto-generates SSH keypair for SFTP container (no static keys in repo)
- DevStorageInitializer reads keypair from conf/sftp/ instead of generating
- Keycloak custom theme for dev login
- Gitignore conf/sftp/id_* generated keys

* fix: use proc check instead of ss for SFTP healthcheck (ss not available in image)

* fix: map DataMovementInterfaceEntity to STORAGE_INTERFACE table instead of DATA_MOVEMENT_INTERFACE

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant