Coder Social home page Coder Social logo

Comments (15)

dmitryuv avatar dmitryuv commented on August 25, 2024

I actually used code of run_ioloop() function directly to achieve desired result, but would be good to see better design of manual "stepping" through the iterations, thanks!

from luamqtt.

xHasKx avatar xHasKx commented on August 25, 2024

@dmitryuv , if if I understand you correctly, you intend to use ioloop builtin into the luamqtt.
In this case, you may try this way.
There is a https://github.com/xHasKx/luamqtt/blob/master/mqtt/ioloop.lua module (require("mqtt.ioloop"))
This module .get() method will return you an instance of ioloop_mt which has a methods :add(client) and :run_until_clients().

So you may create an object with methods :set_ioloop(self) and :_ioloop_iteration() (through metatable or its own).
Then use :add(it) method of the ioloop.
Then ioloop will call it:_ioloop_iteration() over and over in its :run_until_clients() method the same way it process all MQTT clients in the luamqtt.

Please try this way and if it will help - I'll think how to export functions to simplify the described workflow.

from luamqtt.

dmitryuv avatar dmitryuv commented on August 25, 2024

Thanks for getting back on this,

If I understand you correctly you propose to create "fake" mqtt client with my own loop implementation. Might sound like a solution, but it washes out meaning of the existing class (mqtt client), unless there's an additional abstraction on top of it.
The other option i've implemented right now is plugging in my own step into the loop, but i had to extract portion of the code from the loop function:

-- part of the setup
local lb = require('localbus').new(0.005)
lb:sethandler('groupwrite', knx_cb)

-- main loop
function run_loop(client, bus)
  print("running ioloop for it")

  local loop = mqtt.get_ioloop()

  loop:add(client)
  loop.running = true   -- not sure why i need this? part of the original loop
  while next(loop.clients) do
    loop:iteration()
    bus:step()  -- KNX bus iteration
  end
  loop.running = false
  print("done, ioloop is stopped")
end

Probably my concern is that i had to extract part of the library's code instead of plugging in my custom step function. My original first thought that the easiest solution to address this is supplying user's callback that will be called from within the loop, but it's less flexible than your proposal.

from luamqtt.

xHasKx avatar xHasKx commented on August 25, 2024

The Lua has no interfaces/classes in its core like in Java or C#, so masquerading some object as mqtt client is not a "forbidden black magic" thing. It's more like a duck-typing concept in Python.

But inserting a function to the mqtt client lists in ioloop might be a good idea. A function is a first-class value in Lua, so we can easily distinguishing it from usual mqtt clients during ioloop iteration.

Consider this example:

local bus = ...

local loop = mqtt.get_ioloop()
loop:add(function() bus:step()  --[[ KNX bus iteration ]] end)
-- ...

loop:run_until_clients()

What do you think?

from luamqtt.

dmitryuv avatar dmitryuv commented on August 25, 2024

Thanks, that sounds like a good plan. One more thought – since you have mqtt.run_ioloop(..) as an "official" entry point, could it be simplified to something like
mqtt.run_ioloop( client1, function() --[[ custom loop ]] end)

overwise there will be duplication of library parts, also i'm not sure how important are the additional steps in the pre-step, i mean line cl:start_connecting() in the run_ioloop() code

from luamqtt.

xHasKx avatar xHasKx commented on August 25, 2024

@dmitryuv , check the new version v3.2.0 and example in a test https://github.com/xHasKx/luamqtt/blob/master/tests/spec/ioloop.lua

from luamqtt.

dmitryuv avatar dmitryuv commented on August 25, 2024

@xHasKx looks great to me, thanks!

from luamqtt.

dvv avatar dvv commented on August 25, 2024

@xHasKx please clarify how to use with copas standard loop?

I attempted twice:

  copas.addthread(function()
    while true do
      client:_ioloop_iteration() -- choke
    end
  end)

./mqtt/client.lua:898: bad argument #1 to 'coroutine_resume' (thread expected, got nil)

  client:start_connecting()
  copas.addthread(function()
    while true do
      client:_io_iteration(client.connection.recv_func) -- choke
    end
  end)

./mqtt/luasocket.lua:34: bad argument #1 to 'receive' (string expected, got table)

TIA

from luamqtt.

dvv avatar dvv commented on August 25, 2024
  local ioloop = require("mqtt.ioloop").get(true, { timeout = 0.001 })
  copas.addthread(function()
    client.ioloop = ioloop
    while true do
      client:_ioloop_iteration()
      copas.sleep(ioloop.args.timeout)
    end
  end)

This works but shows CPU busy loop.

from luamqtt.

xHasKx avatar xHasKx commented on August 25, 2024

@dvv, I've added an example: https://github.com/xHasKx/luamqtt/blob/master/examples/copas-example.lua

The main thing is to use a new copas thread for each ioloop and mqtt client you plan to use (and proper arguments for ioloop creation: { sleep = 0.001, sleep_function = copas.sleep }, sleep=X is configurable )

from luamqtt.

dvv avatar dvv commented on August 25, 2024

@xHasKx Great, thanks!

However it still eats 6-10% of CPU in timeout busy loop.

from luamqtt.

xHasKx avatar xHasKx commented on August 25, 2024

@dvv, try to play with ioloop creation params - set sleep=0.01 and maybe add timeout=0.1

from luamqtt.

xHasKx avatar xHasKx commented on August 25, 2024

Actually, luamqtt's internal ioloop can be designed better (for example, with socket.select).
I'm sure there is a way to improve luamqtt behavior when it runs inside copas loop

from luamqtt.

dvv avatar dvv commented on August 25, 2024

@xHasKx I sent a pull request with the idea.
Please validate and consider applying.
Running under copas allows for many benefits, imho.

from luamqtt.

xHasKx avatar xHasKx commented on August 25, 2024

@xHasKx I sent a pull request with the idea.
Please validate and consider applying.
Running under copas allows for many benefits, imho.

Thanks, I'll check

from luamqtt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.