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

Documentation for the ExecutionStore #5144

Merged
merged 4 commits into from
Nov 19, 2024
Merged

Documentation for the ExecutionStore #5144

merged 4 commits into from
Nov 19, 2024

Conversation

ritch
Copy link
Contributor

@ritch ritch commented Nov 19, 2024

Documentation for the ExecutionStore

Summary by CodeRabbit

  • Documentation
    • Enhanced guidance on developing plugins with a new section on "Execution Store" for data persistence.
    • Added subsections on "Saved Workspaces," "Accessing Secrets," and "Common Patterns" for improved panel management.
    • Refined document structure for clarity and usability, with updated examples reflecting best practices.
    • Minor formatting adjustments made throughout the document to enhance readability.

Copy link
Contributor

coderabbitai bot commented Nov 19, 2024

Walkthrough

The pull request introduces significant updates to the developing_plugins.rst documentation for FiftyOne. It adds new sections on "Execution Store," "Saved Workspaces," "Accessing Secrets," and "Common Patterns," providing detailed guidance for plugin development. The document's structure has been refined for clarity, and examples have been updated to reflect best practices for creating Python and JavaScript plugins. Additionally, the ExecutionStoreRepo class and related methods have been modified to enhance data retrieval and management, while the Executor class has been updated to streamline access to execution stores.

Changes

File Change Summary
docs/source/plugins/developing_plugins.rst Added sections on "Execution Store," "Saved Workspaces," "Accessing Secrets," and "Common Patterns"; refined document structure and updated examples for clarity and best practices.
fiftyone/factory/repos/execution_store.py Refactored list_stores and count_stores methods to use aggregation pipelines; modified has_store_global, list_stores_global, and count_stores_global methods for improved data handling.
fiftyone/operators/init.py Added import for ExecutionStore from .store.
fiftyone/operators/executor.py Updated store method to retrieve existing execution store with automatic creation; moved ExecutionStore import to the top.
fiftyone/operators/store/service.py Updated create_store method to explicitly include metadata parameter in the method call.
fiftyone/operators/store/store.py Removed get_ttl method and added get_metadata method to return metadata about keys.
tests/unittests/execution_store_unit_tests.py Removed test_list_stores method from integration tests.

Possibly related PRs

Suggested labels

feature, cleaning

Suggested reviewers

  • lanzhenw

Poem

In the garden of code, where plugins bloom,
New sections sprout, dispelling the gloom.
With stores for execution, secrets to keep,
Our documentation grows, a treasure to reap.
So hop to it, dear devs, let your plugins take flight,
In FiftyOne's world, everything feels right! 🐇✨


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 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.

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
Contributor

@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

🧹 Outside diff range and nitpick comments (3)
docs/source/plugins/developing_plugins.rst (3)

2438-2444: Consider adding more context about use cases

The introduction to the Execution Store could be enhanced by providing concrete examples of when to use it, such as:

  • Caching expensive computations
  • Storing user preferences
  • Sharing data between panel instances

2463-2464: Add explanation about TTL behavior

The TTL example should explain what happens when data expires:

  • Is it automatically removed?
  • Are there any events/callbacks when data expires?
  • How to handle expired data in the code?

2481-2492: Clarify global store usage

The global store example would benefit from:

  1. Explaining when to use global store vs regular store
  2. Mentioning any performance implications
  3. Describing scope and visibility of global data
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 76bd458 and 12e4270.

📒 Files selected for processing (1)
  • docs/source/plugins/developing_plugins.rst (1 hunks)
🔇 Additional comments (2)
docs/source/plugins/developing_plugins.rst (2)

2497-2502: Great note about store scoping!

The note about store scoping to dataset is clear and important for users to understand the lifecycle management.


2433-2502: Overall documentation quality is excellent

The new sections are well-integrated into the existing documentation with:

  • Clear explanations
  • Practical code examples
  • Proper context and warnings

Minor suggestions for enhancement:

  1. Consider adding more inline comments in code examples to explain complex operations
  2. Add cross-references to related sections where appropriate

tom-vx51
tom-vx51 previously approved these changes Nov 19, 2024
docs/source/plugins/developing_plugins.rst Outdated Show resolved Hide resolved
Br2850
Br2850 previously approved these changes Nov 19, 2024
@brimoor brimoor dismissed stale reviews from Br2850 and tom-vx51 via 0ef0dc2 November 19, 2024 05:31
@@ -101,19 +102,24 @@ def update_ttl(self, key: str, new_ttl: int) -> None:
"""
self._store_service.update_ttl(self.store_name, key, new_ttl)

def get_ttl(self, key: str) -> Optional[int]:
Copy link
Contributor

Choose a reason for hiding this comment

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

Realized in testing that this method was broken

@@ -19,6 +19,7 @@
)
from .utils import ProgressHandler, is_new
from .panel import Panel, PanelConfig
from .store import ExecutionStore
Copy link
Contributor

Choose a reason for hiding this comment

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

By convention, I prefer that anything that we're publicly documenting for users to be accessible via the highest reasonable package level. For example in this case:

# happy
from fiftyone.operators import ExecutionStore

# sad; too low-level for end users
from fiftyone.operators.store import ExecutionStore

@@ -233,9 +221,7 @@ def has_store_global(self, store_name):
"""Determines whether a store with the given name exists across all
datasets and the global context.
"""
result = self._collection.find_one(
Copy link
Contributor

Choose a reason for hiding this comment

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

Realized in testing that this method was broken

@@ -78,33 +78,21 @@ def has_store(self, store_name) -> bool:

def list_stores(self) -> list[str]:
"""Lists the stores associated with the current context."""
result = self._collection.find(
Copy link
Contributor

Choose a reason for hiding this comment

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

Realized in testing that this method was broken

brimoor
brimoor previously approved these changes Nov 19, 2024
Copy link
Contributor

@brimoor brimoor left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@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: 2

🧹 Outside diff range and nitpick comments (6)
fiftyone/operators/store/service.py (1)

Line range hint 52-60: Document the metadata parameter in create_store method.

Given this PR's focus on ExecutionStore documentation, the create_store method's docstring should document the metadata parameter.

Here's the suggested docstring update:

 def create_store(
     self, store_name: str, metadata: Optional[dict[str, Any]] = None
 ) -> StoreDocument:
     """Creates a new store with the specified name.

     Args:
         store_name: the name of the store
+        metadata: optional metadata to associate with the store
 
     Returns:
         a :class:`fiftyone.store.models.StoreDocument`
     """
docs/source/plugins/developing_plugins.rst (5)

2457-2458: Consider adding TTL explanation.

The concept of TTL (time-to-live) is used here but not explicitly explained. Consider adding a brief explanation of what TTL means and its implications for data persistence.

-        store.set("my_key", {"foo": "bar"}, ttl=60)
+        # Store data that will automatically expire after 60 seconds
+        store.set("my_key", {"foo": "bar"}, ttl=60)  # ttl is in seconds

2513-2516: Enhance global store warning.

The warning about global stores could be more specific about the potential consequences of not using TTLs.

-    Global stores have no automatic garbage collection, so take care when
-    creating and using global stores whose keys do not utilize TTLs.
+    Global stores have no automatic garbage collection. Keys without TTLs in global 
+    stores will persist indefinitely and could lead to memory/storage issues over 
+    time. Consider always using TTLs or implementing manual cleanup strategies.

Line range hint 2517-2533: Add cross-reference to panel data section.

Consider adding a cross-reference to the panel data section for better navigation and understanding.

 :ref:`Panel data <panel-data>` (which may be large), on the other hand, is
 *not* explicitly persisted. Instead it should be hydrated when the panel is
-loaded using the pattern :ref:`demonstrated here <panel-data>`.
+loaded using the pattern :ref:`demonstrated here <panel-data>`. For more details
+about panel data management, see the :ref:`Panel Data <panel-data>` section.

Line range hint 2534-2550: Add security best practices note.

Consider adding a note about security best practices when handling secrets.

 def on_load(self, ctx):
     url = ctx.secrets["FIFTYONE_CVAT_URL"]
     username = ctx.secrets["FIFTYONE_CVAT_USERNAME"]
     password = ctx.secrets["FIFTYONE_CVAT_PASSWORD"]
+
+.. note::
+
+    Security best practices:
+    - Never log or display secrets in your panel
+    - Avoid storing secrets in panel state or data
+    - Use secrets only in secure API calls
+    - Handle missing secrets gracefully

Line range hint 2551-2580: Enhance common patterns overview.

Consider expanding the introduction to provide more context about when to use each pattern.

 Common patterns
 ---------------
 
 Most panels make use of common patterns like callbacks, menus, interactive
-plots, and walkthrough layouts.
+plots, and walkthrough layouts. These patterns serve different purposes:
+
+- **Callbacks**: For handling user interactions and events
+- **Menus**: For organizing actions and navigation
+- **Interactive Plots**: For data visualization and exploration
+- **Walkthrough Layouts**: For guided user experiences and tutorials
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 12e4270 and 85a46fe.

📒 Files selected for processing (7)
  • docs/source/plugins/developing_plugins.rst (1 hunks)
  • fiftyone/factory/repos/execution_store.py (2 hunks)
  • fiftyone/operators/__init__.py (1 hunks)
  • fiftyone/operators/executor.py (2 hunks)
  • fiftyone/operators/store/service.py (1 hunks)
  • fiftyone/operators/store/store.py (2 hunks)
  • tests/unittests/execution_store_unit_tests.py (0 hunks)
💤 Files with no reviewable changes (1)
  • tests/unittests/execution_store_unit_tests.py
🧰 Additional context used
🪛 Ruff
fiftyone/operators/__init__.py

22-22: .store.ExecutionStore imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

🔇 Additional comments (8)
fiftyone/operators/__init__.py (1)

22-22: LGTM! The import location follows our convention.

The high-level import location is perfect for end-user documentation, making it easily accessible via from fiftyone.operators import ExecutionStore.

🧰 Tools
🪛 Ruff

22-22: .store.ExecutionStore imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

fiftyone/operators/store/store.py (1)

9-9: LGTM: Clean datetime import

The datetime import is appropriately placed and follows Python import best practices by importing specifically what's needed.

fiftyone/operators/store/service.py (1)

66-66: LGTM! Explicit parameter passing improves code clarity.

Making the metadata parameter explicit in the method call enhances code readability and maintainability.

fiftyone/operators/executor.py (2)

880-887: LGTM! Improved store retrieval with better reliability.

The changes to the store method are well-implemented:

  1. The docstring now clearly describes the auto-creation behavior
  2. Using dataset._doc.id instead of dataset name provides better reliability as IDs are immutable
  3. The implementation is more concise by leveraging ExecutionStore.create

880-887: Verify backward compatibility of store method changes

Since this modifies existing behavior, we should verify that current usage patterns are preserved.

✅ Verification successful

Let me gather more information about the ExecutionStore tests and implementation to verify the auto-creation behavior.


Let me check one more thing to see the actual implementation of the store method and its auto-creation behavior.


Auto-creation behavior is properly tested and implemented

Based on the comprehensive test suite in execution_store_unit_tests.py and the implementation details, the store auto-creation behavior is well-tested and maintains backward compatibility:

  • The ExecutionStoreServiceIntegrationTests class includes specific tests for store creation
  • The implementation in store/service.py shows proper handling of store creation
  • Existing usage patterns in the codebase (found in docs and model evaluation code) align with this behavior
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all usages of the store method to verify compatibility
rg -A 3 "\.store\(" 

# Search for any tests related to ExecutionStore
rg -l "ExecutionStore.*test"

Length of output: 769


Script:

#!/bin/bash
# Check the test implementation for store creation
cat tests/unittests/execution_store_unit_tests.py

# Look for ExecutionStore implementation
ast-grep --pattern 'class ExecutionStore'

# Check for store method implementation in executor
ast-grep --pattern 'def store($$$)'

Length of output: 13285


Script:

#!/bin/bash
# Find the implementation of the store method in executor.py
rg -A 10 "def store\(" fiftyone/operators/executor.py

# Look for store creation logic
rg -A 5 "create_store" fiftyone/operators/store

Length of output: 1241

fiftyone/factory/repos/execution_store.py (3)

81-85: Efficient retrieval of unique store names using aggregation pipeline

The use of an aggregation pipeline to group by store_name enhances performance and ensures accurate retrieval of unique store names associated with the current context.


90-91: Accurate counting of stores using aggregation pipeline

By grouping and counting unique store_name entries, the aggregation pipeline provides an accurate count of stores associated with the current context.


225-225: Verify the impact of removing the key filter in has_store_global

Removing the key filter in has_store_global changes the method's behavior to check for any document with the given store_name, regardless of the key. Ensure that this aligns with the intended functionality and does not introduce unintended results.

Run the following script to identify usages of has_store_global and review their context:

✅ Verification successful

Let me gather more context about the implementation and usage of this store functionality.


Let me try a different approach to understand the store implementation.


Removing the key filter in has_store_global is correct and intentional

The change to remove the key filter in has_store_global is correct because:

  1. The method's purpose is to check for store existence across all contexts, not specific keys
  2. All other key-specific operations (has_key, get_key, set_key, etc.) maintain their key filters
  3. The test cases in execution_store_service_tests.py verify this behavior by only checking store existence without key consideration
  4. The store implementation maintains a clear separation between store-level operations (global checks) and key-level operations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for all usages of `has_store_global` in the codebase.

rg 'has_store_global\(' -A 3 -B 3

Length of output: 2653


Script:

#!/bin/bash
# Search for the collection definition and store document structure
rg -B 5 -A 5 '_collection.*=.*MongoCollection'

# Search for other methods in the execution store that work with store_name
ast-grep --pattern 'def $_($$$) {
  $$$
  store_name
  $$$
}'

Length of output: 112


Script:

#!/bin/bash
# Look for the store implementation and related methods
rg -B 10 -A 10 'class ExecutionStore'

# Search for methods that use store_name with key
rg 'store_name.*key' -B 3 -A 3

Length of output: 20811

@@ -19,6 +19,7 @@
)
from .utils import ProgressHandler, is_new
from .panel import Panel, PanelConfig
from .store import ExecutionStore
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add ExecutionStore to all to expose it properly.

The ExecutionStore is imported but not included in the __all__ list, which means it won't be exposed when users do from fiftyone.operators import *. Since this is being documented for users, it should be properly exposed.

Add this line before the __all__ definition:

from .store import ExecutionStore
from .categories import Categories

+ __all__ = ["ExecutionStore"]  # Add this before the dynamic __all__ computation
# This enables Sphinx refs to directly use paths imported here
__all__ = [k for k, v in globals().items() if not k.startswith("_")]

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff

22-22: .store.ExecutionStore imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

fiftyone/operators/store/store.py Outdated Show resolved Hide resolved
Copy link
Contributor

@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: 1

🧹 Outside diff range and nitpick comments (1)
fiftyone/operators/store/store.py (1)

9-9: Add type hints for metadata dictionary values

While the datetime import is used indirectly through key_doc attributes, we should explicitly use it in type hints for better code clarity.

-from datetime import datetime
+from datetime import datetime
 from typing import Any, Optional

+MetadataDict = dict[str, datetime]
🧰 Tools
🪛 Ruff

9-9: datetime.datetime imported but unused

Remove unused import: datetime.datetime

(F401)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 85a46fe and d1bbf93.

📒 Files selected for processing (1)
  • fiftyone/operators/store/store.py (2 hunks)
🧰 Additional context used
🪛 Ruff
fiftyone/operators/store/store.py

9-9: datetime.datetime imported but unused

Remove unused import: datetime.datetime

(F401)

fiftyone/operators/store/store.py Show resolved Hide resolved
@ritch ritch merged commit a4e2a6b into release/v1.1.0 Nov 19, 2024
13 checks passed
@ritch ritch deleted the doc/estore branch November 19, 2024 18:35
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.

4 participants