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

[engine] Engine should automatically detect when classes and config are changed and reload the context #6223

Closed
5 tasks done
russdanner opened this issue Sep 21, 2023 · 11 comments

Comments

@russdanner
Copy link
Member

russdanner commented Sep 21, 2023

Latest version

  • The issue is in the develop branch
  • The issue is in the latest released 4.1.x
  • The issue is in the latest released 4.0.x
  • The issue is in the latest released 3.1.x

Duplicates

  • I have searched the existing issues

Is your enhancement request related to a problem? Please describe.

Today changes to nested groovy classes often require a context rebuild in order to get picked up. Ideally, CrafterCMS could detect a development change that would require a context rebuild and handle that seamlessly for the developer.

Example:
A rest controller imports a class written in groovy and uses it. The user changes the class but not the rest script. The updated class changes are not seen until after a context rebuild (or a change to the rest controller)

Describe the solution you'd like

Engine should automatically detect when classes and config are changed and reload the context.

@russdanner russdanner added enhancement triage Requires triage labels Sep 21, 2023
@russdanner
Copy link
Member Author

russdanner commented Sep 21, 2023

The goal is to allow the developer to modify all code and configuration and the test in Engine without needing to commit or manually execute any APIs. Groovy classes, Engine Config and Spring Config updates all require the developer to act in order for Engine to see their changes.`

@phuongnq
Copy link
Member

@sumerjabri @russdanner The implementation enables the DirectoryWatcher for /scripts and /site/engine and for preview mode.
Should we have a separate flag to enable this instead of preview mode?

@sumerjabri sumerjabri self-assigned this Sep 25, 2023
@sumerjabri
Copy link
Member

@phuongnq the Deployer should not rebuild context for Preview targets now that we're doing that in Engine. See if that's possible, please.

@sumerjabri sumerjabri removed their assignment Sep 25, 2023
@sumerjabri
Copy link
Member

Suggested test cases:

  • Write/change/delete files to disk (no commit) in the monitored paths: /scripts/classes/.../*.java (a class file) -- see if Engine picks it up and it runs with the new code
  • Same for config files (Spring context updates, etc.)
  • Git pull similar files from remote where these files are updated

@phuongnq
Copy link
Member

@sumerjabri Regarding the Deployer, since we use the local-target-template.yaml for the preview. I have removed the http processor to do the rebuild. (Assuming we use this template for preview only?).

Those test cases are tested in Linux. For the pull, since they will have the same modified date, I updated the logic to do just one rebuild instead of multiple rebuilds for each file since one rebuild would be enough. If the modified date are different for multiple files, we will treat it as multiple rebuild requests.

We may also want to test the same in MacOS since the library handle watcher differently in the MacOS.

@sumerjabri
Copy link
Member

We're okay with the Deployer template.

The main issue is the algorithm. My suggested algorithm is:
Main idea: Trigger once for a large set of changes, but never wait more than 1 second
Ingredients:

  • A counter with a configurable limit (default 5)
  • A configurable timeout (default 200 milliseconds)

Alg:

  • When the watcher triggers, set a counter to 1 and sleep for 200 milliseconds.
  • Wake up and check:
    • Is the counter 5 (one second has passed)? Then, trigger a rebuild.
    • Has anything else changed (more changes since we slept)? If so, increment the counter and sleep for 200 milliseconds. If nothing has changed, then trigger a rebuild.
  • All of the above happens in the same thread, or a thread pool with limits is used.

Let me know your thoughts. I can also meet with you as needed.

@sumerjabri
Copy link
Member

@yacdaniel you may start testing in develop

@phuongnq please port to 4.0

@Euquimides
Copy link

Euquimides commented Oct 16, 2023

Hi @sumerjabri and @phuongnq ! While validating the ticket I noticed the following. Let's say we change the configuration of the new engine watcher to watch paths in general like:

# Engine file change watcher paths
crafter.engine.watcher.paths=\
  /scripts,\
  /config/engine,\
  /
# Engine file change watcher counter limit to rebuild
crafter.engine.watcher.counter.limit=5
# Engine file change watcher thread interval in milliseconds
crafter.engine.watcher.interval.period=200

The watcher will follow changes to /.git/ files, giving away something like this in the logs:

[INFO] 2023-10-16T16:27:16,477 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/site/website/index.xml'. Hash value: 'AAAAAGUtuMQAAAAAHFOFgw==' 
[INFO] 2023-10-16T16:27:16,479 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/index.lock'. Hash value: 'AAAAAGUtuMQAAAAAHFOFgw==' 
[INFO] 2023-10-16T16:27:16,480 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/b6'. Hash value: 'DIRECTORY' 
[INFO] 2023-10-16T16:27:16,480 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/b6/2c8d009a5ee7df6d74ef016292e38ac970eebb'. Hash value: 'AAAAAGUtuMQAAAAAHFOFgw==' 
[INFO] 2023-10-16T16:27:16,480 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'DELETE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/index.lock'. Hash value: 'none' 
[INFO] 2023-10-16T16:27:16,480 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/index'. Hash value: 'AAAAAGUtuMQAAAAAHFOFgw==' 
[INFO] 2023-10-16T16:27:16,482 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/index.lock'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,482 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/b6/2c8d009a5ee7df6d74ef016292e38ac970eebb'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,483 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/7c'. Hash value: 'DIRECTORY' 
[INFO] 2023-10-16T16:27:16,483 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/7c/a1f6f5d0ee5c36a9f0286ff61b36e3db20fee2'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,483 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/62/54aea307ece02a5583cbd6b4c2d81ea3562395'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,483 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/6e/3e55a9994e40b99a11c1b6f58ee3dba0774839'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,483 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/next-index-66222.lock'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,483 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/COMMIT_EDITMSG'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/20/tmp_obj_2YAa7G'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/HEAD.lock'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/refs/heads/master'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'CREATE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/20/fe91798954972b7c3493b80ff52bee386952ae'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'DELETE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/objects/20/tmp_obj_2YAa7G'. Hash value: 'none' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/logs/HEAD'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/logs/refs/heads/master'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'DELETE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/HEAD.lock'. Hash value: 'none' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'DELETE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/index.lock'. Hash value: 'none' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'MODIFY'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/index'. Hash value: 'AAAAAGUtuMQAAAAAHJCOrA==' 
[INFO] 2023-10-16T16:27:16,484 [ForkJoinPool.commonPool-worker-31] [] [context.SiteContextManager] | File watcher event type: 'DELETE'. File affected: '/home/juanvasquez/crafter/craftercms/crafter-authoring/data/repos/sites/test3/sandbox/.git/next-index-66222.lock'. Hash value: 'none' 

Should we consider /.git/ files to be excluded by default from engine watcher? This to avoid potentially filling the logs by some sort of configuration from the users, specially with big sites or any sort of CI/CD. Thank you for your response!

@phuongnq
Copy link
Member

@sumerjabri We can have a list of ignore path patterns such as:

# Engine file change watcher ignores path patterns
crafter.engine.watcher.ignorePathPatterns=\
  /.git/**

Please let me know if we want to implement this. However, in a normal case, we should only rebuild on the default value including the /config/engine and /scripts folder.

@sumerjabri
Copy link
Member

@phuongnq let's build the ignore paths feature and default it to /.git as you indicated. It would be great if we can do the logic like this:

  • Compute what we are asked to watch
  • Subtract what we are asked to ignore
    This way we can have it exclude specific files even in /config

@Euquimides
Copy link

Hi! Fix verified for Crafter v4.0.8 and v.4.1.2. Thank you! Closing this ticket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Status: Done
Development

No branches or pull requests

5 participants