Issue:
Bug: fix(external_services): add proto compilation under a feature flag



add proto compilation under a feature flag

Pull request description:
## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [ ] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
add proto build under the dynamic_routing feature flag. Now the application would run without having to install protoc


### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?

Cannot be tested as it is for compiling the application without having to mandatorily install proton


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [ ] I formatted the code `cargo +nightly fmt --all`
- [ ] I addressed lints thrown by `cargo clippy`
- [ ] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible


Testing:
Cannot be tested as it is for compiling the application without having to mandatorily install proton

Patch:
diff --git a/config/config.example.toml b/config/config.example.toml
index a6af984b01f..8345185238d 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -748,3 +748,7 @@ check_token_status_url= ""    # base url to check token status from token servic
 
 [network_tokenization_supported_connectors]
 connector_list = "cybersource" # Supported connectors for network tokenization
+
+[grpc_client.dynamic_routing_client] # Dynamic Routing Client Configuration
+host = "localhost" # Client Host
+port = 7000        # Client Port
diff --git a/config/deployments/env_specific.toml b/config/deployments/env_specific.toml
index 62350376271..319cdafed1d 100644
--- a/config/deployments/env_specific.toml
+++ b/config/deployments/env_specific.toml
@@ -311,3 +311,7 @@ private_key= ""               # private key to decrypt  response payload from to
 key_id= ""                    # key id to encrypt data for token service
 delete_token_url= ""          # base url to delete token from token service
 check_token_status_url= ""    # base url to check token status from token service
+
+[grpc_client.dynamic_routing_client] # Dynamic Routing Client Configuration
+host = "localhost" # Client Host
+port = 7000        # Client Port
diff --git a/crates/external_services/Cargo.toml b/crates/external_services/Cargo.toml
index a882cdc9f51..fd7391c13bc 100644
--- a/crates/external_services/Cargo.toml
+++ b/crates/external_services/Cargo.toml
@@ -13,7 +13,7 @@ email = ["dep:aws-config"]
 aws_s3 = ["dep:aws-config", "dep:aws-sdk-s3"]
 hashicorp-vault = ["dep:vaultrs"]
 v1 = ["hyperswitch_interfaces/v1"]
-dynamic_routing = ["dep:prost", "dep:tonic", "dep:tonic-reflection", "dep:tonic-types", "dep:api_models", "tokio/macros", "tokio/rt-multi-thread"]
+dynamic_routing = ["dep:prost", "dep:tonic", "dep:tonic-reflection", "dep:tonic-types", "dep:api_models", "tokio/macros", "tokio/rt-multi-thread" , "dep:tonic-build", "dep:router_env"]
 
 [dependencies]
 async-trait = "0.1.79"
@@ -49,7 +49,8 @@ api_models = { version = "0.1.0", path = "../api_models", optional = true }
 
 
 [build-dependencies]
-tonic-build = "0.12"
+tonic-build = { version =  "0.12" , optional = true }
+router_env = { version = "0.1.0", path = "../router_env", default-features = false, optional = true }
 
 [lints]
 workspace = true
diff --git a/crates/external_services/build.rs b/crates/external_services/build.rs
index 61e19f308d8..605ef699715 100644
--- a/crates/external_services/build.rs
+++ b/crates/external_services/build.rs
@@ -1,15 +1,13 @@
-use std::{env, path::PathBuf};
-
 #[allow(clippy::expect_used)]
 fn main() -> Result<(), Box<dyn std::error::Error>> {
-    // Get the directory of the current crate
-    let crate_dir = env::var("CARGO_MANIFEST_DIR")?;
-    let proto_file = PathBuf::from(crate_dir)
-        .join("..")
-        .join("..")
-        .join("proto")
-        .join("success_rate.proto");
-    // Compile the .proto file
-    tonic_build::compile_protos(proto_file).expect("Failed to compile protos ");
+    #[cfg(feature = "dynamic_routing")]
+    {
+        // Get the directory of the current crate
+        let proto_file = router_env::workspace_path()
+            .join("proto")
+            .join("success_rate.proto");
+        // Compile the .proto file
+        tonic_build::compile_protos(proto_file).expect("Failed to compile success rate proto file");
+    }
     Ok(())
 }
diff --git a/crates/external_services/src/grpc_client/dynamic_routing.rs b/crates/external_services/src/grpc_client/dynamic_routing.rs
index 17bd43ca3a8..2681bffb0ce 100644
--- a/crates/external_services/src/grpc_client/dynamic_routing.rs
+++ b/crates/external_services/src/grpc_client/dynamic_routing.rs
@@ -112,12 +112,12 @@ impl SuccessBasedDynamicRouting for SuccessRateCalculatorClient<Channel> {
         let params = success_rate_based_config
             .params
             .map(|vec| {
-                vec.into_iter().fold(String::new(), |mut acc_vec, params| {
-                    if !acc_vec.is_empty() {
-                        acc_vec.push(':')
+                vec.into_iter().fold(String::new(), |mut acc_str, params| {
+                    if !acc_str.is_empty() {
+                        acc_str.push(':')
                     }
-                    acc_vec.push_str(params.to_string().as_str());
-                    acc_vec
+                    acc_str.push_str(params.to_string().as_str());
+                    acc_str
                 })
             })
             .get_required_value("params")
@@ -177,12 +177,12 @@ impl SuccessBasedDynamicRouting for SuccessRateCalculatorClient<Channel> {
         let params = success_rate_based_config
             .params
             .map(|vec| {
-                vec.into_iter().fold(String::new(), |mut acc_vec, params| {
-                    if !acc_vec.is_empty() {
-                        acc_vec.push(':')
+                vec.into_iter().fold(String::new(), |mut acc_str, params| {
+                    if !acc_str.is_empty() {
+                        acc_str.push(':')
                     }
-                    acc_vec.push_str(params.to_string().as_str());
-                    acc_vec
+                    acc_str.push_str(params.to_string().as_str());
+                    acc_str
                 })
             })
             .get_required_value("params")