-
Notifications
You must be signed in to change notification settings - Fork 45
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
initial API proposal for manager #42
Conversation
Pull Request Test Coverage Report for Build 1922880105
💛 - Coveralls |
# TODO | ||
0 | ||
dbus_method :probe, "" do | ||
# TODO: do it assynchronous. How? ractors will have problem with sharing yast data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
np: asynchronous
We need to do some research here. By now, we have been using threads and, although it is far from ideal, it worked. But sure we need a better solution. Ideally, we could have an actors-like solution where every subsystem is represented by an actor and they share nothing. But that's not realistic at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sadly with way how we using yast I worry it will be very challenging
Asynchronous calls and D-Bus(This is probably different from what you've started to discuss, but I want to summarize it anyway) In the old times (before 2009) the bus itself (dbus-daemon) would have a method call timeout (about 30 seconds) so things taking a long time had to be designed as void methods + signals bearing the reply. But that has changed (suprisingly to me), and now the D-Bus API Design Guildelines say that a normal call+reply should be used, possibly disabling a timeout implemented in the language binding:
No timeout in ruby-dbus (yet)Anyway, ruby-dbus does not currently impose a timeout on method calls, but there is an issue (mvidner/ruby-dbus#61) asking for it. Client-side Asynchronous Calls in ruby-dbusAlso not what you're doing here, but for completeness: Instead of a synchronous call value = object_interface.some_method(args)
foo(value)
bar you can do it asynchronously with object_interface.some_method(args) { |value| foo(value) }
bar so |
@jreidinger please remember to fill the PR description. It provides CONTEXT for people who happen to not have a copy of your brain. A link to Bugzilla/Trello is a good start. |
# t current major step | ||
# t total minor steps. Can be zero which means no minor steps | ||
# t current minor step | ||
dbus_reader :progress, "(stttt)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So a D-Bus client can poll the progress by reading the property, or listen for PropertiesChanged signals, right?
InstallationProgress has @dbus_obj&.Progress(...args...)
. How is that related? Which class (interface) is @dbus_obj
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. I see that pattern often.
InstallationProgress will be dropped. Plan is to use Progress.new in dbus Manager object and assign callback to it that raise signal. And attach progress to data structure read from that progress.object.
def_delegators :@software, :products, :product | ||
|
||
# @return [InstallerStatus] | ||
attr_reader :status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP: Please, document its type.
# proposing installer instead of reading current one | ||
Yast::Stage.Set("initial") | ||
end | ||
attr_reader :progress |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP: Please, document its type.
@@ -23,29 +23,16 @@ | |||
module DInstaller | |||
# This class represents the installer status | |||
class InstallerStatus |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe having a class is too much. Is this expected to grow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea: What about having something like DInstaller::StatusManager
class, which defines possible statuses, implement logic for changing status, for calling callbacks and so on? And DInstaller::Manager
would simply instanciate a StatusManager
and would request a status change when needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I am not sure. I try to not touch this part :) Just change it from string to unsigned.
service/lib/dinstaller/manager.rb
Outdated
Yast::Installation.destdir = "/mnt" | ||
# lets propose it here to be sure that software proposal reflects product selection | ||
# FIXME: maybe repropose after product selection change? | ||
# first make bootloader proposal to be sure that required packages is installed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: are installed.
ensure | ||
change_status(InstallerStatus::IDLE) | ||
Thread.new do | ||
sleep(1) # do sleep to ensure that dbus service is already attached |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this would not be needed if probing is launched by a client calling to Manager#probe
dbus method, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeap, but my goal is to get to probed status as soon as possible. That is why I do it when starting service.
# progress.next_minor_step("Doing subtask2") | ||
# subtask2 | ||
# progress.next_minor_step("Finished subtask2") | ||
class Progress |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it would too much, but I also imagine this as a kind of ProgressManager
, generating steps when requested:
steps_manager = StepsManager.new(steps: 3)
steps_manager.next_step("Doing step1") #=> DInstaller::Step
do_step1(steps_manager)
steps_manager.next_step("Doing step2")
do_step2(steps_manager)
steps_manager.next_step("Doing step3")
do_step3(steps_manager)
...
def do_step1(steps_manager)
current_step = steps_manager.current_step
sub_steps_manager = current_step.sub_steps(2) #=> DInstaller::StepsManager
sub_steps_manager.next_step("Doing" subtask1")
subtask1
sub_steps_manager.next_step("Doing" subtask2")
subtask2
This would allow to generate a tree of steps: step1 -> step 1.1 -> step 1.1.1. With this, we could also have different callbacks for substeps, etc. But as said, maybe is too much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, having tree of steps is something that is hard to imagine for me how to display it in UI. I try to keep it simple now. So top level manager knows about top level steps and then module knows about module specific substeps if needed. ( from my current testing some steps like language probe is super fast, that it is even hard to notice it ).
Co-authored-by: Martin Vidner <[email protected]>
Goal of this PR is to write top level manager API that control probing and installing. It is also responsible for providing reasonable progress information back to user.