openSUSE:WebYaST 缓存

跳转到:导航搜索

WebYaST 缓存

工作原理

最近的发布版本表明,WebYaST 的后端速度太慢。特别是启动新的模块通常需要花费太多时间。

系统管理工具基于很少更改的数据(例如用户、打印机、网络设置),但评估这些数据需要消耗大量时间。因此,想法是在启动 WebYaST 时将这些数据预加载到缓存中,以便立即使用。

如果 UI 使用了缓存,将并行启动一个任务以再次从系统评估这些数据。如果新评估的数据与缓存不同,UI/用户将被告知,并且 UI 将重新加载


WebYaST http 通信 HTTP 浏览器
* 使用以下命令启动:rcwebyast start
* 遍历所有模型,调用 find 方法,
并将结果插入缓存
User.find(:all)
Network.find(:all)
Ldap.find(:all)
...
..
.

* 显示例如 用户索引页面
<--- GET User/ --- * 从 WebYaST 获取所有用户
* 读取 User.find(:all) 的缓存 --- User.find(:all) ---> * 在 UI 中显示所有用户
* 调用 User.find(:all) 以检查和更新缓存。
<--- GET notifier/user --- * 轮询缓存是否在此期间已更改。
* 检查用户缓存是否已更改 ? --- 是/否 --> * 如果数据在此期间已更改,则更新 UI
* 定期轮询更改的缓存
...
..
.

一个不错的“副作用”是,如果后台在此期间更改了一些数据,其他 UI 也会收到通知。例如,两个用户同时编辑网络配置。在一位用户保存了他的值后,第二位用户将被告知数据已更改,并且他将获得更新。

如何实现

如果要在插件中使用此缓存机制,则需要更改模型类中的以下方法。以下是 Group 模型类(文件:plugins/users/app/models/group.rb)的示例

require 'yast_service'

包含所需的库。

  def self.find (cn)
    return find_all if cn == :all
    YastCache.fetch(self, cn) {
      result = group_get( "system", cn )
      result = group_get( "local", cn )  if result.empty?
      return nil if result.empty?
      make_group result
    }
  end

  def self.find_all
    YastCache.fetch(self, :all) {
      result = groups_get "local"
      result.update( groups_get "system")
      result_array = []
      result.each { |k,v| result_array << make_group(v) }
      result_array.sort! {|x,y| x.cn <=> y.cn}
    }

YastCache.fetch(self, cn)YastCache.fetch(self, :all) 使用 ID cn:all 读取 groups 缓存。如果为空,将执行给定的代码块,并将评估值插入缓存并返回。

  def save
    existing_group = Group.group_get( group_type, old_cn )
    if existing_group.empty?
      result = YastService.Call( "YaPI::USERS::GroupAdd",
                                 { "type"      => ["s", group_type] },
                                 { "cn"        => ["s",cn], "userlist"  => ["as", members] } )
    else
      result = YastService.Call( "YaPI::USERS::GroupModify",
                                 { "type"      => ["s", group_type],
                                   "cn"        => ["s", old_cn]  },
                                 { "gidNumber" => ["i", gid],
                                   "cn"        => ["s",cn],
                                   "userlist"  => ["as", members] }
                               )
    end
    YastCache.reset(self, old_cn)
    result # result is empty string on success, error message otherwise
  end

使用 YastCache.reset(self, old_cn) 使缓存无效,并在后台重新填充。

  def destroy
    existing_group = Group.group_get( group_type, old_cn )
    if existing_group.empty?
      ret = ""
    else
      ret = YastService.Call( "YaPI::USERS::GroupDelete", {"type" => ["s",group_type], "cn" => ["s",old_cn]})
    end
    YastCache.delete(self,old_cn)
    ret
  end

YastCache.delete(self,old_cn) 删除该组的缓存。