Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve thread read performance #348

Merged
merged 1 commit into from
Jan 4, 2025
Merged

improve thread read performance #348

merged 1 commit into from
Jan 4, 2025

Conversation

Southclaws
Copy link
Owner

split nested query into separate concurrent queries

split nested query into separate concurrent queries
Copy link

vercel bot commented Jan 4, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
storyden ⬜️ Ignored (Inspect) Visit Preview Jan 4, 2025 5:30pm
storyden-homepage ⬜️ Ignored (Inspect) Jan 4, 2025 5:30pm

Copy link

coderabbitai bot commented Jan 4, 2025

📝 Walkthrough

Walkthrough

This pull request introduces significant changes across multiple packages, focusing on enhancing data mapping, lookup, and relationship handling. The modifications primarily involve creating new types like Accounts, Reacts, and Lookup, which provide more efficient ways to manage and access data. Key changes include simplifying mapping functions, introducing new methods for grouping and accessing data by ID, and refactoring how relationships between entities like posts, accounts, and reactions are managed.

Changes

File Change Summary
app/resources/account/account.go Added Accounts type, Map() method, and Lookup type for efficient account management
app/resources/post/reaction/react.go Introduced Reacts type, Map() method, Lookup type, and Mapper function for reaction handling
app/resources/post/thread/thread.go Replaced FromModel with Map and added Mapper function for thread mapping
internal/ent/post.go Added AccountPosts field and updated related methods
internal/ent/schema/post.go Added account_posts field and updated edge configuration

Sequence Diagram

sequenceDiagram
    participant Client
    participant Mapper
    participant Repository
    participant Database

    Client->>Mapper: Request data mapping
    Mapper->>Repository: Fetch related data
    Repository->>Database: Execute queries
    Database-->>Repository: Return data
    Repository-->>Mapper: Provide lookup data
    Mapper->>Mapper: Transform and map data
    Mapper-->>Client: Return mapped objects
Loading

Possibly related PRs

Poem

🐰 Mapping magic, data's delight
Accounts and threads now shine so bright
Lookups dancing, IDs in sync
CodeRabbit's touch, faster than a blink!
Efficiency leaps with each new line 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (6)
app/resources/tag/tag.go (1)

54-55: Commented out Items field might indicate dead code.
If the Items field is no longer required for performance, remove the items appending logic to avoid confusion. If it will be used in the future, consider documenting why it is commented out.

internal/ent/mutation.go (1)

18715-18715: Clarify naming consistency between “author” and “account_posts”.
Clearing the "author" edge also clears post.FieldAccountPosts here. This is presumably intentional, but it could confuse maintainers if the naming diverges or if the fields represent different concepts.

internal/ent/schema/post.go (1)

41-41: Consider renaming or clarifying usage of account_posts.

Currently, the newly introduced field is named account_posts, which might not align intuitively with storing a single account ID (xid.ID{}). Consider renaming it to something more descriptive, for example account_id, to improve clarity and consistency. If storing multiple accounts is intended in the future, a different type (like a multi-value field) may be more suitable.

internal/infrastructure/db/db.go (2)

22-22: Dependency on zap introduced.
The new logger dependency is a valuable addition to track queries and mutations. Ensure the logging level is configurable in different environments (development vs. production) to avoid verbosity or performance overhead.


70-113: Commented-out logging interceptor code.
The logging interceptor code is helpful for debugging but is currently disabled. If it’s not needed immediately, consider removing it or marking it with a TODO comment so others are aware of its purpose and potential usage.

internal/ent/post_create.go (1)

531-533: Validate necessity of requiring "account_posts" field.
This enforces the field as mandatory during creation. If there's a use case where a post might not belong to a specific account, consider making this field nullable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ccdbf70 and 4437cbc.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (23)
  • app/resources/account/account.go (2 hunks)
  • app/resources/account/mapping.go (1 hunks)
  • app/resources/event/event.go (1 hunks)
  • app/resources/post/reaction/react.go (3 hunks)
  • app/resources/post/reply/db.go (3 hunks)
  • app/resources/post/reply/reply.go (4 hunks)
  • app/resources/post/thread/db.go (6 hunks)
  • app/resources/post/thread/thread.go (3 hunks)
  • app/resources/profile/profile.go (1 hunks)
  • app/resources/tag/tag.go (2 hunks)
  • internal/ent/account_query.go (2 hunks)
  • internal/ent/category_query.go (0 hunks)
  • internal/ent/er.html (1 hunks)
  • internal/ent/link_query.go (0 hunks)
  • internal/ent/mutation.go (8 hunks)
  • internal/ent/post.go (4 hunks)
  • internal/ent/post/post.go (3 hunks)
  • internal/ent/post/where.go (2 hunks)
  • internal/ent/post_create.go (6 hunks)
  • internal/ent/post_query.go (2 hunks)
  • internal/ent/post_update.go (2 hunks)
  • internal/ent/schema/post.go (2 hunks)
  • internal/infrastructure/db/db.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/ent/category_query.go
  • internal/ent/link_query.go
🔇 Additional comments (86)
app/resources/post/thread/thread.go (7)

9-9: Import for github.com/rs/xid looks good.
This package provides a concise way to generate and parse globally unique IDs, which can help avoid collisions across distributed systems.


11-11: Import for github.com/Southclaws/storyden/app/resources/account is appropriate.
This aligns with the new lookups for account data in the Mapper function.


52-99: New Map function is well-structured and consistent with the existing patterns.
Constructing the Thread object directly from ent.Post is straightforward, and the error handling with fault.Wrap is good. The approach of mapping category, link, content, and profile is clear and maintainable.


101-107: Mapper function signature is clear.
Defining a higher-order function that provides a specialized mapper is a nice approach for injecting additional lookups (accounts, likes, etc.).


108-113: Category handling remains correct.
The retrieval of the Category edge and graceful error handling continues the pattern established in Map().


124-132: Potential nil pointer when accessing the author from am[m.AccountPosts].
If am[m.AccountPosts] is nil, dereferencing it will panic. If the schema or usage guarantees the presence of an account for each post, this should be fine. Otherwise, consider a nil check or fallback logic.


135-135: Reaction lookup is straightforward.
Retrieving the set of reactions via rl[xid.ID(m.ID)] is a seamless way to gather them without re-querying.

app/resources/tag/tag.go (1)

35-35: Switch to thread.Map is consistent and maintains error handling.
Replacing the old call with thread.Map unifies the new mapping approach across the codebase.

app/resources/post/reaction/react.go (3)

19-19: New target field improves association clarity.
Storing the target ID directly in each React helps group them efficiently by post or entity.


22-28: Reacts type and Map() method provide a clean way to group reactions.
Using lo.GroupBy on target is concise and well-suited for reusing grouped data.


52-63: Check for missing accounts in Mapper.
If am[xid.ID(in.AccountID)] returns nil, dereferencing it as *acc will cause a panic. Ensure the lookup is guaranteed by schema or handle the nil case.

app/resources/account/account.go (1)

50-52: Accounts.Map() leverages lo.KeyBy effectively.
This method cleanly creates a lookup map keyed by account ID. Just be aware of potential collisions if multiple Account objects share the same ID (which is unlikely if IDs are unique).

app/resources/event/event.go (1)

44-44: Switch to thread.Map is coherent with the broader refactor.
Calling thread.Map(threadEdge) aligns event mapping with the new thread-mapping approach across the codebase.

app/resources/profile/profile.go (1)

51-51: Double-check the removal of error handling for AccountRoles.

By directly assigning rolesEdge := a.Edges.AccountRoles without AccountRolesOrErr(), the code now silently ignores any missing or invalid roles data. If a.Edges.AccountRoles might be missing or inconsistent, it could cause downstream errors. Consider verifying that the roles edge always exists and is valid in this context.

app/resources/account/mapping.go (1)

19-19: Confirm the absence of role edge error handling.

Similar to profile.go, the direct assignment rolesEdge := a.Edges.AccountRoles removes any checks for potential edge retrieval errors. If there's a scenario where AccountRoles data is incomplete or unavailable, this might create silent failures. Verify that no upstream logic depends on the old AccountRolesOrErr() behavior.

app/resources/post/thread/db.go (30)

16-16: Add concurrency library import.
No issues with introducing "github.com/alitto/pond/v2" for parallel task management.


20-21: Add new utility and logging imports.
These imports ("github.com/samber/lo" and "go.uber.org/zap") are common and stable.


24-31: Additional resource imports.
Imports for assets, reactions, and tags look consistent with the rest of the file.


33-34: Ent account and asset imports.
No issues found; matches likely usage for ent-based queries.


38-39: Import ent reaction and tag.
Looks correct for referencing ent-based reaction and tag entities.


43-44: Add logger and db fields to the database struct.
Elevates maintainability by centralizing the logger.


48-53: New constructor function with logger injection.
This approach is good for dependency injection and keeps logging consistent across operations.


128-128: Return mapped thread object in Create.
Using Map(p) aligns with the new mapping approach.


166-166: Use of Map again in Update.
Consistent usage for mapping query results.


232-232: Ordering assets by updated time then created time.
Verify that this meets your intended sort order: updated first, then created.


285-285: Instantiate mapper with nil parameters.
Confirm that the Mapper function correctly handles nil values to avoid potential runtime errors.


343-347: Initialize a new pond group and set up logger context.
This concurrent group creation is a solid design choice for parallel queries.


349-354: Create a logduration helper function.
A concise way to measure and log execution time of concurrent tasks.


356-368: Concurrent retrieval of reply stats.
Well-structured concurrency block with proper error wrapping.


369-383: Concurrent retrieval of likes.
Follows the same concurrency pattern; no concerns.


384-398: Concurrent retrieval of collection statuses.
Implementation appears consistent and correct.


399-412: Concurrent retrieval of tags.
Same concurrency approach, error handling is good.


413-426: Concurrent retrieval of assets.
No concerns with the parallel fetching pattern.


427-449: Concurrent retrieval of replies.
Logic aligns with the rest of the concurrency approach.


450-477: Concurrent retrieval of the thread root.
Error handling is robust.


478-479: Wait for all concurrent tasks to finish.
Ensures data consistency before proceeding.


484-503: Build combined post lists and deduplicate account IDs.
Use of lo.Uniq is concise and effective.


504-508: Query relevant account edges.
Code correctly fetches all referenced accounts.


513-515: Map ent accounts to domain accounts.
No issues beyond verifying that mapping covers all necessary fields.


518-519: Construct account lookup.
Straightforward approach for quick account references.


520-529: Combine all data using domain-specific mappers.
Keeps reaction, like, and collection data organized.


531-534: Map replies with concurrency results.
Error handling is consistent; no concerns.


536-536: Obtain the main thread object with threadMapper.
Implementation fits the established mapping pattern.


541-543: Prepare pagination info for replies.
The pagination logic seems correct.


545-546: Attach tags and assets to the final thread object.
No concerns, final data struct is updated appropriately.

internal/ent/mutation.go (7)

18573-18608: Implementation follows standard Ent mutation patterns.
These methods for setting, retrieving, and resetting the "account_posts" field (stored internally as m.author) appear consistent with Ent’s generated code approach. The logic is sound, and the error handling for OldAccountPosts looks correct.


19455-19455: Good capacity increment for new field.
Allocating a capacity of 17 accommodates the new "account_posts" field. This minor detail supports efficient appending.


19498-19500: Conditionally appending the "account_posts" field is correct.
This ensures the field is included only when it’s set, avoiding unintended updates.


19543-19544: Switch case to retrieve the "account_posts" field is valid.
This maintains consistency with other fields within the same logical block.


19586-19587: Switch case to retrieve old "account_posts" value is correct.
Relying on OldAccountPosts(ctx) ensures the historical value is fetched only when valid for UpdateOne.


19699-19705: Type safety for setting "account_posts" is well-implemented.
Forcing a cast to xid.ID prevents runtime type mismatches and ensures consistent data handling.


19868-19870: Reset logic aligns with Ent’s mutation pattern.
Clearing m.author in ResetAccountPosts properly undoes any mutation to the field, preserving data integrity.

internal/ent/schema/post.go (1)

51-51: Enforce correct integrity checks on the new field.

This edge uses .Field("account_posts") for the author relationship. Verify that the database enforces foreign key constraints or validations to ensure the field references a valid account, preventing orphan records.

app/resources/post/reply/db.go (3)

87-87: Replacing FromModel(nil)(p) with Map(p)
The switch to a direct Map(p) call looks simpler. However, ensure that all fields previously handled by FromModel are now correctly mapped by Map to prevent any missing data.


110-110: Retaining consistency with existing business logic.
Again, returning Map(p) is consistent with the new approach. Verify that any filtering or transformations that previously occurred in FromModel have been moved into the Map function if needed.


148-148: Confirm the deprecation of FromModel usage.
This change finalizes the migration to Map. Ensure the old function is fully removed or marked as deprecated in code comments to discourage future use.

app/resources/post/reply/reply.go (3)

10-10: Dependency import added.
Importing "github.com/Southclaws/storyden/app/resources/account" makes sense if you are now leveraging account lookups here. Confirm that this import is needed in all relevant build configs and not left unused in certain build variants.


69-102: New Map function to transform ent.Post into Reply.
This function is straightforward, focusing on converting an ent.Post into a Reply by extracting author, rich text content, and optional reply references. It’s a good approach to keep the function short and clear.

  • Ensure error handling covers all required fields (e.g., if Edges.Author is missing).
  • Double-check whether the DeletedAt field is relevant beyond soft-deletes in your domain logic.

Line range hint 104-133: New Mapper function for advanced mappings.
This function extends the Map logic with account, likes, and reaction lookups.

  • The parameter-based approach (am, ls, rl) introduces a clear separation of concerns.
  • Confirm that concurrency or caching strategies for these lookups are not inadvertently impacted by heavy usage in production.
internal/infrastructure/db/db.go (1)

61-61: newEntClient signature updated to accept a logger.
Accepting a logger in newEntClient is a clean way to integrate structured logging. Make sure that any existing callers of newEntClient are updated accordingly, preventing compilation or injection failures.

internal/ent/post.go (5)

53-54: Well-structured field addition for AccountPosts.

Adding AccountPosts xid.ID makes the relationship clearer. Ensure external usage references this field consistently.


61-62: No issues noted.

Lines declaring Edges and selectValues remain consistent with the ent code generation pattern.


260-260: Good inclusion in scanValues.

Including post.FieldAccountPosts in the scanValues switch statement correctly ensures that the field is recognized for scanning.


371-376: Correct assignment logic.

The assignment logic for post.FieldAccountPosts appears correct, properly handling the scanned value.


546-548: Enhanced String() representation.

Including account_posts in the string builder improves debuggability and clarity of object logs.

internal/ent/post/post.go (3)

47-48: Meaningful constant addition.

Declaring FieldAccountPosts = "account_posts" aligns with ent's naming convention for schema fields.


189-189: Correct field inclusion in Columns slice.

Adding FieldAccountPosts to the Columns slice ensures it’s properly recognized by queries and mutations.


331-334: Convenient ordering utility.

ByAccountPosts is a well-structured helper for sorting by account_posts. No concerns detected.

internal/ent/post/where.go (2)

119-123: Consistent naming for equality predicate.

AccountPosts function neatly mirrors established naming patterns, ensuring consistent usage in queries.


804-873: Comprehensive predicates for account_posts.

These new functions (e.g., AccountPostsEQ, AccountPostsNEQ, etc.) enrich query flexibility. Implementation follows ent’s best practices.

internal/ent/post_query.go (2)

1022-1022: Clear foreign-key lookup.

Accessing fk := nodes[i].AccountPosts to load Author is correct and ensures the right reference.


1617-1619: Conditional column loading is appropriate.

Only adding post.FieldAccountPosts when withAuthor is set helps avoid unnecessary data loading.

internal/ent/post_create.go (8)

193-197: Add null-check for ID parameters if needed.
Currently, the setter accepts an xid.ID without any validation. Ensure that a nil or zero-value ID won't break the logic downstream, if that scenario is feasible.


1121-1125: SetAccountPosts method looks straightforward.
This setter properly updates the PostUpsert struct with the new field.


1127-1131: UpdateAccountPosts ensures upsert uses the create-time value.
Good addition for concurrency scenarios in upsert logic.


1451-1456: Add “SetAccountPosts” to PostUpsertOne.
Method is consistent with the overall pattern for setting fields upon upsert one.


1458-1463: “UpdateAccountPosts” in PostUpsertOne parallels other fields.
Maintains consistency in upsert behavior.


1956-1961: Bulk upsert “SetAccountPosts.”
Code conveys the new field to bulk operations effectively.


1963-1969: Bulk upsert “UpdateAccountPosts.”
Appears correct for ensuring post creation-time value is used during conflicts.


640-640: Confirm correct assignment to 'AccountPosts'.
The code assigns nodes[0] (from author edge) to _node.AccountPosts. Double-check this logic to ensure you don’t inadvertently overwrite the correct field.

internal/ent/account_query.go (1)

Line range hint 1430-1444: Ensure mapping is correct for multi-post scenarios.
The logic sets a single node per AccountPosts ID. If multiple posts belong to one account, check for potential collisions or missing associations in the loop.

internal/ent/post_update.go (4)

259-263: Setter added for “account_posts.”
This is consistent with the create methods. No issues spotted.


265-271: Nillable setter matches other fields’ pattern.
Ensures optional assignment if the field can be omitted.


1706-1710: SetAccountPosts for PostUpdateOne.
Maintains a consistent approach in single-entity updates.


1712-1718: Nillable setter for PostUpdateOne.
Good addition for avoiding forced assignment of “account_posts.”

internal/ent/er.html (1)

206-206: Added “account_posts” to ER diagram.
If it denotes a required one-to-one reference, consider making that explicit with the appropriate notation or clarifying in the docs.

@Southclaws Southclaws merged commit 6c2d743 into main Jan 4, 2025
4 checks passed
@Southclaws Southclaws deleted the thread-perf branch January 4, 2025 20:03
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