V Tue, 14 May 2019 15:04:43 +0200
Ladislav Slezak <[email protected]> napsáno:

> Hi all,
> 
> I'd like to discuss how to improve the pkg-bindings API in YaST, more 
> specifically
> the Pkg.ResolvableProperties(name, kind, version) call.
> 
> But if you find some other pkg-bindings API calls difficult to use just ping 
> me,
> we can improve more calls.
> 
> 
> There are basically two problems with Pkg.ResolvableProperties() call:
> 
> - You cannot use any input filters, you can only filter by name, kind or 
> version.
>   That's quite limited, for the other cases you need to get *all* objects and 
> filter
>   the returned list.
> 
> - The result contains all possible attributes for each object, even those you 
> do not
>   need in most cases (like the package description and summary, installed 
> size, RPM
>   size, full RPM name, vendor, ...). That is wasting the memory space.
> 
> If you call Pkg.ResolvableProperties("", :package, "") in Leap with the online
> repositories enabled you will get a huge detailed list with about 40.000 (!)
> packages. And that requires quite a lot of memory and might freeze the 
> installer as
> reported in [1].
> 
> 
> A GraphQL Side Note
> -------------------
> 
> I was interested in some existing generic solution for this problem. And I 
> found a
> quite nice GraphQL project. It can not only describe the search query but also
> describe the result (which objects or attributes you need in the response).
> 
> Although there is a C++ library [2] or a Ruby library [3] in the end it looks 
> like an
> overkill for the internal API. But if you would need to design some big and
> complicated REST API then you could consider it. See more details in [4] or 
> in the
> specification [5].
> 
> 
> The Proposal
> ============
> 
> To not break the backward compatibility we cannot change the 
> ResolvableProperties()
> call so let's create a new one:
> 
> # <filter_hash> = required matching values
> # <attributes_list> = returned attributes, empty list => return all
> Yast::Pkg.Resolvables(<filter_hash>, <attributes_list>)
> 
> 
> # a ResolvableProperties() compatible version:
> Yast::Pkg.Resolvables({kind: :package, name: "yast2"}, []) => Array<Hash>
> 
> [{
>   "arch"=>"x86_64",
>   "description"=>  
>    "This package contains scripts and data needed for SUSE Linux\n" +
>    "installation with YaST2",
>   "download_size"=>518308,
>   "inst_size"=>2388454,
>   "location"=>"yast2-4.0.87-lp150.2.9.1.x86_64.rpm",
>   "locked"=>false,
>   "medium_nr"=>1,
>   "name"=>"yast2",
>   "on_system_by_user"=>false,
>   "path"=>"./rpms/x86_64/yast2-4.0.87-lp150.2.9.1.x86_64.rpm",
>   "source"=>7,
>   "status"=>:available,
>   "summary"=>"YaST2 - Main Package",
>   "transact_by"=>:solver,
>   "vendor"=>"openSUSE",
>   "version"=>"4.0.87-lp150.2.9.1",
>   "version_epoch"=>nil,
>   "version_release"=>"lp150.2.9.1",
>   "version_version"=>"4.0.87"  
> }]
> 
> 
> # new functionality: more search criteria and limiting the result:
> Yast::Pkg.Resolvables({kind: :package, status: :available, name: "yast2"},
>   [:name, :version]) => Array<Hash>
> 
> [{
>   "name"=>"yast2",
>   "version"=>"4.0.87-lp150.2.9.1",  
> }]
> 
> 
> Quite often we just need to know whether an object with some attributes exists
> without need to know the specific details, like a package is installed:
> 
> Yast::Pkg.AnyResolvable(name: "foo", kind: :package, status: :installed) => 
> Boolean
> 
> That would be basically the same as Pkg.Resolvables, just returning a simple 
> Boolean
> as the result instead of the details. (And it could be faster, it can return 
> after
> finding the first matching item, it does not need to iterate over all 
> objects.)
> 
> 
> Ruby Wrapper
> ------------
> 
> Unfortunately the C++ Pkg-bindings API does not allow specifying optional 
> parameters
> (that's a limitation of the YaST component system)

In fact there is a way, just not so easy. 

see e.g. 
https://github.com/yast/yast-core/blob/master/libycp/src/YCPBuiltinPath.cc#L155

so you need to define it multiple times there. ( just note that I do not test 
it enough with ruby, as it is used now only in builtins which is already 
defined in ruby itself.

I do not test it, but maybe also in ruby you can have something like:

publish function: :test, signature: "string (string)"
publish function: :test, signature: "string (string, string)"

You can try it and maybe it will work. If not, I can check a bit more code as 
in general component system should allow it, just ycp does not allow it.

Josef


> and cannot provide an
> object-oriented API so probably having a small Ruby wrapper would be nice:
> 
> Yast::Resolvable.find(<filter_hash>) => Array<Resolvable>)
> 
> Where the Resolvable would be an object wrapper for the pkg-bindings Hash.
> 
> Examples:
> 
> Yast::Resolvable.find(kind: :package, status: :selected)
> Yast::Resolvable.find(name: "package", kind: :package, status: :installed)
> 
> Similarly for the existence check (just for completeness):
> 
> Yast::Resolvable.any?(kind: :package, status: :selected)
> 
> 
> I'll propose some code snippets at GitHub, I think it will be better to 
> discuss some
> details in a draft pull request with some real code...
> 
> 
> 
> [1] https://bugzilla.suse.com/show_bug.cgi?id=1132650
> [2] https://github.com/graphql/libgraphqlparser
> [3] https://graphql-ruby.org/
> [4] https://graphql.org/
> [5] https://graphql.github.io/graphql-spec/
> 

--
To unsubscribe, e-mail: [email protected]
To contact the owner, e-mail: [email protected]

Reply via email to