I am looking for something like this:
update data
set data = new_data
where data.updated_at < new_data.updated_at
I can't find a solution for this problem,
The close one is to use WATCH but unfortunately it can't watch for specific value condition.
If redis can't do this, do you have any recommended in memory like Redis that support this feature?
You can do this with Lua Scripts, using EVAL command
Assuming you want to set both the update timestamp and the data value, and if no timestamp also set the values (for first-time set), the Lua script can be something like:
local updt = redis.call('GET', KEYS[1])
if (not updt) or (tonumber(updt) < tonumber(ARGV[1])) then
return redis.call('MSET', KEYS[1], ARGV[1], KEYS[2], ARGV[2])
else
return redis.error_reply('data is newer on server!')
end
You can invoke as:
EVAL "local updt = redis.call('GET', KEYS[1]) if (not updt) or (tonumber(updt) < tonumber(ARGV[1])) then return redis.call('MSET', KEYS[1], ARGV[1], KEYS[2], ARGV[2]) else return redis.error_reply('data is newer on server!') end" 2 dataUpdated data 1 initVal
You will find in Lua Scripts a very powerful tool to get the most out of Redis.
Related
GPGME provides information about a key's trust level as the owner_trust field which is of gpgme_validity_t type. However, I could not find a function in the documentation or the gpgme.h header file that allows me to change the validity of a key.
The GnuPG command line tool sure allows to change the trust level of a key:
$ gpg --edit-key alice#example.com
> trust
Does the GPGME library even support changing the owner_trust field? If so, how do I use it?
I am using the newest version of GPGME which is 1.16.0 (commit hash 1021c8645555502d914afffaa3707609809c9459).
It should be possible to use gpgme_op_interact to accomplish this.
The following demonstrates the process with Python bindings, but analogous code should be possible to write with the C API.
import gpg
def trust_at(level):
done = False
def interact_cb(status, arg):
nonlocal done
if status in ('KEY_CONSIDERED', 'GOT_IT', ''):
return
if status == 'GET_LINE':
if arg == 'keyedit.prompt':
if done:
return 'quit'
done = True
return 'trust'
if arg == 'edit_ownertrust.value':
return level
# needed if we set trust level to 5
if (status, arg) == ('GET_BOOL', 'edit_ownertrust.set_ultimate.okay'):
return 'y'
assert False
return interact_cb
with gpg.Context() as gnupg:
key = gnupg.get_key(FINGERPRINT)
gnupg.interact(key, trust_at('4'))
So.. I've been coding to make a GUI show the quantity of currency of a player, the datastore API works perfectly but the local script doesn't (it's local because else it would just update it each time a player's currency gets updated and would be a mess being the opposite of what I want to)
and well... sometimes it loads the currency into the GUI but other times it just stays on the original text: "Label" instead of my current currency (4600)
here's the proof
What normally happens and should always happen
What sometimes happens and shouldn't happen:
here's the script, I've tried putting waits on the start but the original code is inside the while true do..
wait(game.Players.LocalPlayer:WaitForChild("Data")
wait(game.Players.LocalPlayer.Data:WaitForChild("Bells"))
while true do
script.Parent.TextLabel.Text = game.Players.LocalPlayer:WaitForChild("Data"):WaitForChild("Bells").Value
wait() --wait is for not making the loop break and stop the whole script
end
well.. if you want to see if data is really in the player, here's the script, it requires a API (DataStore2)
--[Animal Crossing Roblox Edition Data Store]--
--Bryan99354--
--Module not mine--
--Made with a AlvinBlox tutorial--
--·.·.*[Get Data Store, do not erase]*.·.·--
local DataStore2 = require(1936396537)
--[Default Values]--
local DefaultValue_Bells = 300
local DefaultValue_CustomClothes = 0
--[Data Store Functions]--
game.Players.PlayerAdded:Connect(function(player)
--[Data stores]--
local BellsDataStore = DataStore2("Bells",player)
local Data = Instance.new("Folder",player)
Data.Name = "Data"
Bells = Instance.new("IntValue",Data)
Bells.Name = "Bells"
local CustomClothesDataStore = DataStore2("CustomClothes",player)
local CustomClothes = Instance.new("IntValue",Data)
CustomClothes.Name = "CustomClothes"
local function CustomClothesUpdate(UpdatedValue)
CustomClothes.Value = CustomClothesDataStore:Get(UpdatedValue)
end
local function BellsUpdate(UpdatedValue)
Bells.Value = BellsDataStore:Get(UpdatedValue)
end
BellsUpdate(DefaultValue_Bells)
CustomClothesUpdate(DefaultValue_CustomClothes)
BellsDataStore:OnUpdate(BellsUpdate)
CustomClothesDataStore:OnUpdate(CustomClothesUpdate)
end)
--[test and reference functions]--
workspace.TestDevPointGiver.ClickDetector.MouseClick:Connect(function(player)
local BellsDataStore = DataStore2("Bells",player)
BellsDataStore:Increment(50,DefaultValue_Bells)
end)
workspace.TestDevCustomClothesGiver.ClickDetector.MouseClick:Connect(function(player)
local CustomClothesDataStore = DataStore2("CustomClothes",player)
CustomClothesDataStore:Increment(50,DefaultValue_CustomClothes)
end)
the code that creates "Data" and "Bells" is located in the comment: Data Stores
the only script that gets the issue is the short one with no reason :<
I hope that you can help me :3
#Night94 I tryed your script but it also failed sometimes
The syntax in your LocalScript is a little off with the waits. With that fixed, it works every time. Also, I would use an event handler instead of updating the value with a loop:
game.Players.LocalPlayer:WaitForChild("Data"):WaitForChild("Bells").Changed:Connect(function(value)
script.Parent.TextLabel.Text = value
end)
Currently i am trying to automate the start mode in windows server services. i tried to use puppetlabs registry but realized that the module didn't work as i expected.
Basically i have list of windows services that i need to update on each server but on some servers, the services might not exist, but puppetlabs registry will just create the new key if it's not exist which is not the expected behaviour. By right, it should work as mentioned below:
Check whether the service is in the servers or not
If it does, then update the start mode as mentioned inside the manifest/hiera
If not exist, just do nothing and skip to the next service immediately
Based from what i knew, it seems the only way to check whether the service key exist or not is by using custom function. So i already tried to write some custom function using win32/registry, but was unsuccessful by getting some error such as Win32API not supported. Another way i can think of is using the reg command line to check whether the key exist or not. Here is the puppet code functions:
module Puppet::Parser::Functions
newfunction(:check_winservice_exist, :type => :rvalue) do |args|
service_name = args[0]
unless args.length > 0 then
raise Puppet::ParseError, ("check_winservice_exist(): wrong number of arguments (#{args.length}; must be > 0)")
end
command = "reg query HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\#{service_name} /f DisplayName"
result = system command
return result
#if result == true
# return result
#else
# return result
#end
end
end
When i run the simplified ruby scripts in command line, it works and return the expected value. But when i used above scripts as puppet custom functions, it always return empty.
This is my first time to write a puppet custom functions so i am not sure what i did wrong here. Please advise whether there are another alternative that i can use to resolve the issue or maybe advise on what i did wrong on the functions script
I managed to resolve this issue by using custom facter as suggested by Matt. Just sharing the custom facter scripts that i used. It might not be perfect as i am still not really proficient in using ruby.
require 'win32/registry'
Facter.add(:winservices) do
confine :kernel => "windows"
setcode do
keyname= 'SYSTEM\CurrentControlSet\Services'
access = Win32::Registry::KEY_ALL_ACCESS
arr = []
winservices_list = []
Win32::Registry::HKEY_LOCAL_MACHINE.open(keyname, access) do |reg|
service_lists = (reg.each_key { |key, wtime| arr.push key })
arr.each do |service|
service_key = "SYSTEM\\CurrentControlSet\\Services\\#{service}"
begin
Win32::Registry::HKEY_LOCAL_MACHINE.open(service_key, access) do |reg|
value = reg['Start']
winservices_list.push service
end
rescue
end
end
winservices_list
end
end
end
And it simply works just by adding simply checking whether the service name is in the array or not
if $service_name in $facts['winservices'] {
service { "${service_name}":
provider => 'windows',
enable => $start_real,
}
}
I have to run bash heavy-job.sh <data-num> (that takes 0.5~2 days) frequently on my computer to process data located at ~/a/data/num . The script call a few sub-processes sequentially and write a log to ~/a/result/num.log . I have done this manually until now.
I wanted to visualize processed tasks and it's status(success or fail), etc as html table. I wrote simple sinatra app to render a table that shows
the list of ~/a/data/num to be processed
~/a/result/num.log exists or not (process not-launched/processing/done)
it's status (the log file contains the word "error" or not)
I found that it would be convenient that if I could launch a bash heavy-job.sh <data-num> from the sinatra app, log the tasks (and info like time,date,etc..) and it's args (heavy-jobs takes some optional args ) and show them as html table.
So I need something that manages jobs and logs to files (or db).
First I wrote a code like below for test (! for test, not integrated with my system yet !), but later I found resque is what i wanted. I am a beginner and not sure if my decision is reasonable or not.
my questions are
is it reasonable to use resque to manage external long-running commands (and log tasks)
or should I use another tool (not necessarily ruby-tool).
(extra;) the task-manager and the sinatra app should work separately (and communicate each other over REST or something) OR not ?
The jobs are not critical since I can retry tasks manually later if failed.
I am not good at English and my question may be misleading. I appreciate any help :) .
class TaskSpawn
def initialize()
#pids = []
end
def spawn(command, options = {})
#opt = {:pgroup => true}
#pids << Kernel.spawn(command, options)
end
def pids()
return #pids.clone
end
def waitany_nohang()
delete_idx = nil
ret = nil
#pids.each_with_index do |p, idx|
pid,status = Process.waitpid2(p, Process::WNOHANG)
unless pid.nil?
delete_idx = idx
ret = [pid,status]
break
end
end
if delete_idx
#pids.delete_at(delete_idx)
return ret
else
# no task fininshed
return nil
end
end
def waitall()
ret = waitall
raise "interal error" if ret.size != pids.size
return ret
end
end
Maybe I've gotten my sockets programming way mixed up, but shouldn't something like this work?
srv = TCPServer.open(3333)
client = srv.accept
data = ""
while (tmp = client.recv(10))
data += tmp
end
I've tried pretty much every other method of "getting" data from the client TCPSocket, but all of them hang and never break out of the loop (getc, gets, read, etc). I feel like I'm forgetting something. What am I missing?
In order for the server to be well written you will need to either:
Know in advance the amount of data that will be communicated: In this case you can use the method read(size) instead of recv(size). read blocks until the total amount of bytes is received.
Have a termination sequence: In this case you keep a loop on recv until you receive a sequence of bytes indicating the communication is over.
Have the client closing the socket after finishing the communication: In this case read will return with partial data or with 0 and recv will return with 0 size data data.empty?==true.
Defining a communication timeout: You can use the function select in order to get a timeout when no communication was done after a certain period of time. In which case you will close the socket and assume every data was communicated.
Hope this helps.
Hmm, I keep doing this on stack overflow [answering my own questions]. Maybe it will help somebody else. I found an easier way to go about doing what I was trying to do:
srv = TCPServer.open(3333)
client = srv.accept
data = ""
recv_length = 56
while (tmp = client.recv(recv_length))
data += tmp
break if tmp.length < recv_length
end
There is nothing that can be written to the socket so that client.recv(10) returns nil or false.
Try:
srv = TCPServer.open(3333)
client = srv.accept
data = ""
while (tmp = client.recv(10) and tmp != 'QUIT')
data += tmp
end