Skip to content

Conversation

@vobradovich
Copy link
Member

No description provided.

@vobradovich vobradovich self-assigned this Dec 22, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @vobradovich, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a fundamental change to the IDL specification by integrating a unique interface_id into service definitions. This enhancement provides a robust mechanism for identifying services, which is crucial for managing service inheritance, program exports, and preventing ambiguities. The changes span across the IDL parsing, AST representation, IDL generation, and client code generation components, ensuring consistent and validated usage of interface_id throughout the ecosystem. This update improves the overall reliability and clarity of service contracts.

Highlights

  • Introduction of interface_id: A new interface_id field has been added to service definitions, allowing for unique identification of services within the IDL. This ID is now part of the ServiceIdent struct.
  • AST and Parser Updates: The Abstract Syntax Tree (AST) in sails-idl-meta and the IDL parser in sails-idl-parser-v2 have been updated to recognize and process the new interface_id syntax (e.g., service MyService@0x...).
  • IDL Generation Logic Refinement: The IDL generation (idl-gen) now incorporates interface_id for service and program building. This includes improved handling of base services, such as deduplication based on interface_id and cycle detection in service inheritance hierarchies.
  • Client Generator Adaptation: The client code generator (client-gen) has been updated to correctly interpret and utilize the new ServiceIdent structure, ensuring that generated client code reflects the interface_id where necessary, particularly for extended services.
  • Error Handling Consolidation: Multiple specific error types related to invalid function or event metadata (FuncMetaIsInvalid, EventMetaIsInvalid, EventMetaIsAmbiguous) have been consolidated into a more general MetaIsInvalid error type for simplified error management.
  • Dependency Update: The sails-idl-meta crate has been introduced as a new dependency in Cargo.toml and Cargo.lock to support the new interface_id functionality.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully adds interface_id to the IDL's Abstract Syntax Tree (AST), and correctly updates the IDL generator and validation logic. The introduction of the ServiceIdent struct is a good structural improvement. The new logic for deduplicating services by interface_id and the addition of cycle detection for base services are excellent enhancements. I have included a couple of performance-related suggestions for the builder logic to optimize lookups.

Comment on lines +92 to +120
let expos: Result<Vec<_>> = self
.service_expos
.into_iter()
.enumerate()
.map(|(idx, (route, meta))| {
let interface_id = meta.interface_id();
let Some(service) = services
.iter()
.find(|s| s.name.interface_id == Some(interface_id))
else {
return Err(Error::MetaIsInvalid(format!(
"service `{route}@{interface_id}` not defined"
)));
};
let route = if service.name.name == route {
None
} else {
Some(route.to_string())
};

Ok(ServiceExpo {
name: service.name.clone(),
route,
route_idx: (idx as u8) + 1,
docs: vec![],
annotations: vec![],
})
})
.collect();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The find operation inside this loop results in a time complexity of O(N*M), where N is the number of exposed services and M is the total number of service definitions. This can be optimized by creating a HashMap of services keyed by their interface_id before iterating. This would reduce the complexity to O(N+M), improving performance for programs with many services.

        let services_by_id: std::collections::HashMap<_, _> = services
            .iter()
            .filter_map(|s| s.name.interface_id.map(|id| (id, s)))
            .collect();

        let expos: Result<Vec<_>> = self
            .service_expos
            .into_iter()
            .enumerate()
            .map(|(idx, (route, meta))| {
                let interface_id = meta.interface_id();
                let Some(service) = services_by_id.get(&interface_id) else {
                    return Err(Error::MetaIsInvalid(format!(
                        "service `{route}@{interface_id}` not defined"
                    )));
                };
                let route = if service.name.name == route {
                    None
                } else {
                    Some(route.to_string())
                };

                Ok(ServiceExpo {
                    name: (*service).name.clone(),
                    route,
                    route_idx: (idx as u8) + 1,
                    docs: vec![],
                    annotations: vec![],
                })
            })
            .collect();

Comment on lines +200 to +203
if let Some(service) = services
.iter()
.find(|s| s.name.interface_id == Some(interface_id))
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The find operation on the services vector inside build_inner is a linear search. Since build_inner is called recursively for each base service, this can lead to quadratic complexity in cases of services with many direct base services (e.g., a service extending many other services). To optimize this, consider using a HashMap<InterfaceId, ServiceUnit> instead of a Vec<ServiceUnit> to store the services. This would make the lookup for an already built service an O(1) operation on average.

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.

3 participants