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

Enable caching on connections #214

Merged
merged 7 commits into from
Nov 27, 2017
Merged

Enable caching on connections #214

merged 7 commits into from
Nov 27, 2017

Conversation

jquick
Copy link
Contributor

@jquick jquick commented Nov 17, 2017

This changes adds a new connection called "CacheConnection". When passed a connection it will cache file and command calls. All connection methods will be accessible on the cached version.

Signed-off-by: Jared Quick jquick@chef.io

@jquick jquick requested review from chris-rock, a team and adamleff November 17, 2017 17:06
@jquick jquick force-pushed the jq/cache_connection branch 3 times, most recently from 9fa599f to b4a4785 Compare November 17, 2017 20:33
Copy link
Contributor

@adamleff adamleff left a comment

Choose a reason for hiding this comment

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

@jquick I really like the shape of this. I know this isn't exactly what @chris-rock was pitching initially, but after you and I talked about it, I think this is a better approach. It ensures that we don't have to do any Ruby magic to make the "Cache" connection have all the instance messages for the connection it represents, and it cleanly extends caching to ANY connection that subclasses BaseConnection. I think this is a more Rubyish way to accomplish this. Nice work.

I have some cleanup items and suggestions for you to review, and we can talk to @chris-rock more about this next week.

# @param command [String] command string to execute
# @return [CommandResult] contains the result of running the command
def run_command_via_connection(_command)
fail Train::ClientError, "#{self.class} does not implement #run_command_via_connection()"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should raise a NotImplementedError instead as that's the standard exception class for this type of issue. Is there a reason we shouldn't?

def file(_path, *_args)
fail Train::ClientError, "#{self.class} does not implement #file(...)"
def file_via_connection(_path, *_args)
fail Train::ClientError, "#{self.class} does not implement #file_via_connection(...)"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should raise a NotImplementedError instead as that's the standard exception class for this type of issue. Is there a reason we shouldn't?

}

@cache_enabled.each_key do |type|
@cache[type] = {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe call clear_cache here instead?


class Train::Plugins::Transport
class CacheConnection
attr_accessor :cache_enabled
Copy link
Contributor

Choose a reason for hiding this comment

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

Ruby nitpick, I'd rather see a cache_enabled? method that looks at this hash and returns true/false... just to keep consistency with ? methods returning booleans. If you choose to take this advice, this will obviously require some changes in BaseConnection, but not too many.

end

def file(path)
if @cache[:file].key?(path)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this be simplified to?:

@cache[:file][path] ||= @connection.file_via_connection(path)

That should return the value if it's there, otherwise, assign the new value and then return it.

end

def run_command(cmd)
if @cache[:command].key?(cmd)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above - I think we can do ||= and simplify a bit.

@@ -14,6 +14,10 @@
proc { connection.run_command('') }.must_raise Train::ClientError
end

it 'provides a run_command_via_connection method' do
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if this should be it 'raises an exception for run_command_via_connection', and then we add a it 'provides a run_command_via_connection method' check for each of our connection classes. Thoughts?

@@ -22,6 +26,10 @@
proc { connection.file('') }.must_raise Train::ClientError
end

it 'provides a file_via_connection method' do
proc { connection.file_via_connection('') }.must_raise Train::ClientError
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above...

@jquick jquick force-pushed the jq/cache_connection branch 4 times, most recently from 53b774c to e853f12 Compare November 21, 2017 20:29
@jquick
Copy link
Contributor Author

jquick commented Nov 22, 2017

This should be updated with all changes to date.

Copy link
Contributor

@chris-rock chris-rock left a comment

Choose a reason for hiding this comment

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

I think we are very close @jquick

#
# @param command [String] command string to execute
# @return [CommandResult] contains the result of running the command
def run_command_via_connection(_command)
Copy link
Contributor

Choose a reason for hiding this comment

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

Those two methods need to be private

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, moved.

else
Train::File::Remote::Linux.new(self, path)
end
def uri
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason to make this public?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Missed it, thank you.

nil # none, open your shell
end

def uri
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we exposing this one?

end

def file_via_connection(path)
@files[path] ||= file_not_found(path)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we use the file cache and just fill the cache? So this will become a noop then

Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
Signed-off-by: Jared Quick <jquick@chef.io>
@jquick jquick force-pushed the jq/cache_connection branch from e853f12 to 231bae3 Compare November 27, 2017 03:03
@jquick
Copy link
Contributor Author

jquick commented Nov 27, 2017

This is updated with all changes.

Copy link
Contributor

@chris-rock chris-rock left a comment

Choose a reason for hiding this comment

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

This looks great, I added some further comments. Would love to see this in action with https://github.com/chef/inspec/pull/2309/files before we merge. @jquick are you updating inspec/inspec#2309

@cache_enabled[type.to_sym]
end

def enable_cache(type)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need a comment to document which types are available.

@@ -1,7 +1,4 @@
# encoding: utf-8
#
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure why this is removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was a directive via Adam to remove any author tags on files we touch. I can add it back for now.

Signed-off-by: Jared Quick <jquick@chef.io>
@jquick
Copy link
Contributor Author

jquick commented Nov 27, 2017

This has been updated with changes. inspec/inspec#2309 was also updated to use this new functionality.

Copy link
Contributor

@chris-rock chris-rock left a comment

Choose a reason for hiding this comment

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

Great work @jquick

else
Train::File::Remote::Linux.new(self, path)
end
def uri
Copy link
Contributor

Choose a reason for hiding this comment

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

Missed it, thank you.

Copy link
Contributor

@adamleff adamleff left a comment

Choose a reason for hiding this comment

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

This is so freakin' close. I have a suggestion on making the run_command and file method just read a bit cleaner and remove some logic when returning.

# Enable caching types for Train. Currently we support
# :file and :command types
def enable_cache(type)
@cache_enabled[type.to_sym] = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Future enhancement: raise an exception if the user tries to enable/disable a cache that we don't support.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 great catch!

# This is the main command call for all connections. This will call the private
# run_command_via_connection on the connection with optional caching
def run_command(cmd)
return @cache[:command][cmd] ||= run_command_via_connection(cmd) if cache_enabled?(:command)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it might be a bit cleaner to read if it was structured to do the non-cache enabled stuff first:

return run_command_via_connection(cmd) unless cache_enabled?(:command)

@cache[:command][cmd] ||= run_command_via_connection(cmd)

The return combined with the ||= is hanging me up a bit. Feels like too much happening in one conditional statement.

Copy link
Contributor

Choose a reason for hiding this comment

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

Uh, I like that one. Thank you @adamleff

# This is the main file call for all connections. This will call the private
# file_via_connection on the connection with optional caching
def file(path, *args)
return @cache[:file][path] ||= file_via_connection(path) if cache_enabled?(:file)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same feedback as the run_command structure feedback.

Signed-off-by: Jared Quick <jquick@chef.io>
@@ -43,10 +43,12 @@ def cache_enabled?(type)
# Enable caching types for Train. Currently we support
# :file and :command types
def enable_cache(type)
fail Train::UnknownCacheType, "#{type} is not a valid cache type" unless @cache_enabled.keys.include?(type.to_sym)
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than getting a list of the keys, you can ask the Hash if it has the key:

... unless @cache_enabled.key?(type.to_sym)

Copy link
Contributor

@adamleff adamleff left a comment

Choose a reason for hiding this comment

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

Nice work, @jquick :)

@adamleff adamleff merged commit 00a3411 into master Nov 27, 2017
@adamleff adamleff deleted the jq/cache_connection branch November 27, 2017 17: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.

3 participants