Библиотека lua_share: обмен данными между скриптами и приложениями

Автор записи: toxa
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 13, среднее: 3,92 из 5)
Загрузка...

ОПИСАНИЕ:
Библиотека предназначена для обмена данными между lua-скриптами, работающими в разных процессах, а так же в
одном процессе, но в разных lua-машинах. Прежде всего, она будет полезна пользователям терминала QUIK.

Комплект состоит из библиотеки lua_share.dll и файла lua_share_boot.lua. Для корректной работы оба файла должны
находиться в одном каталоге. Если файл lua_share_boot.lua отсутствует, то библиотека ведет себя несколько иначе,
но тоже работает, о чем ниже. Для межпроцессного взаимодействия в комплект так же входит IPC-сервер под названием
lua_share_server.exe и lua-скрипт lua_share_server.lua.

инициализация:

1
2
package.cpath = getScriptPath() .. "\\lua_share.dll"
sh = require "share"

запись и чтение:

1
2
sh["hello"] = "world" -- запись
val = sh["hello"] -- чтение

пространства имен:

1
2
3
local ns = sh.GetNameSpace("test_name_space") -- создать пространство имен test_name_space
ns["hello"] = "world" -- запись
val = ns["hello"] -- чтение

получение снапшота:

1
2
3
4
local ns = sh.GetNameSpace("test_name_space") -- создать пространство имен test_name_space
ns["hello"] = "hello" -- 1 значение
ns["world"] = "world" -- 2 значение
val = ns:DeepCopy() -- получение снапшота

"bootstrap":
Файл lua_share_boot.lua содержит код, который кастомизирует поведение хранилища. В текущей реализации
используется сравнение таблиц по содержимому. Например:

1
2
3
4
local ns = sh.GetNameSpace("test_name_space")
ns[{1, 2, {3, 4}}] = "JOHN"
ns[{1, 2, {3, 4}}] = "DOE"
tmp = ns[{1, 2, {3, 4}}]

Если файл lua_share_boot.lua существует, то в результате хранилище будет содержать только строку
"DOE" и в переменную tmp будет помещено это значение, иначе хранилице будет содержать обе строки:
"JOHN" и "DOE", а в переменную tmp будет помещено значение nil, так как ключи {1, 2, {3, 4}} - это
deepcopy исходных ключей и разные объекты, хотя и с одинаковым содержимым, а по-умолчанию в lua
сравниваются ссылки.

В lua_share_boot.lua можно запрограммировать свое поведение, а добавить свои метаметоды, например __gc.
См комментарии в коде lua_share_boot.lua.

IPC:

Существует возможность создавать "удаленные" пространства имен, общие для нескольких запущенных приложений
(терминалов QUIK). Для этого необходимо запустить сервер lua_share_server.exe, который хранит общие данные.
Сервер запускает lua-скрипт, который хранится в файле lua_share_server.lua и который можно, при желании,
кастомизировать. Общее хранилище существует, пока запущен сервер. Удаленное пространство имен создается
следующим образом:

1
local ns = sh.GetIPCNameSpace("test_name_space")

Способ работы с ним не отличается.

RPC:

Существует возможность вызова удаленной функции на lua_share_server и получить результаты ее выполнения.
Тестовая функция testfunc() определена в lua_share_server.lua. Вот пример ее вызова:

1
2
local ns = sh.GetIPCNameSpace("test_name_space")
a, b, c = ns.RPC("testfunc", "a", {1, 2, {3, "b"}})

pre-defined пространства:

"queues" - пространство имен, реализующее очереди (queue).
"eventlist" - пространство, реализующее списки событий (аналог waitformultipleobjects).
"permanent" - пространство, загружающее себя из файла при старте и записывающее себя в файл при
выходе (завершении всех скриптов).

примеры:

Примеры предназначены для запуска в терминале QUIK.

01_test_share_common.lua - общий пример работы с lua_share

02_test_share_producer.lua - пример скрипта "писатель" в цикле обновляет общие данные
03_test_share_consumer.lua - пример скрипта "читатель" читает данные и выводит их в окно сообщений

04_test_share_tablekeys.lua - демонстрация использования таблиц в качестве ключей хранилища

05_test_share_pushqueue.lua - очереди: писатель
06_test_share_popqueue.lua - очерели: читатель

07_test_share_pushevent.lua - eventlist: писатель
08_test_share_popevent.lua - eventlist: читатель

09_test_share_permanent.lua - сохранение данных между запусками скрипта а так же перезапуском QUIK

10_test_share_IPC.lua - пример работы с "удаленным" хранилищем, должен быть запущен lua_share_server.exe

11_test_share_RPC.lua - пример удаленного вызова функции, должен быть запущен lua_share_server.exe и
в lua_share_server.lua должна быть определена функция testfunc().

дистрибутив:

бинарники: https://www.dropbox.com/s/vg8oucqo117o0kx/lua_share_binaries.zip?dl=0

репозиторий github: https://github.com/untoxa/lua_share

еще можно пообсуждать тут: https://quik2dde.ru/viewtopic.php?id=306

Добавить комментарий

Библиотека lua_share: обмен данными между скриптами и приложениями: 13 комментариев

  1. Выбор автором стейта Lua, в качестве буфера взаимодействия скриптов/процессов, обеспечил высокое качество реализации пакета.
    ---
    Но есть некоторые моменты, которые можно отметить.
    1. При описании пакета, наверное, стоило бы указать ограничения на типы данных, допустимые при взаимодействии, а в пакете сделать контроль таких ограничений и выдачу сообщений об их нарушении.
    2. Похоже, есть ошибка синхронизации при инициализации пакета (обнаружил в lua_share, lua_share_rpc не смотрел). Эта ошибка возникает (в QUIK 9.2.1.4) сразу при одновременном запуске двух скриптов, в которых есть подключение lua_share. Если в одном из скриптов сделать задержку(sleep(100)) подключения пакета, то ошибка не проявляется.
    3. Взаимодействие между скриптами/процессами можно достаточно просто реализовать, используя давно известный пакет SQLite, примерно, следующим образом:
    1) для обеспечения быстрого взаимодействия между скриптами QUIK открывается база в оперативной памяти с указанием ее общего для скриптов имени;
    2) для обеспечения взаимодействия между процессами используется база на накопителе;
    3) для служебный целей создается общая служебная база на накопителе, в которой могут вестись разные справочники и т.д;
    4) устанавливаются следующие ограничения на типы данных, допустимые при взаимодействии: строки (строки данные и строки функции) и таблицы (без их метатаблиц); данными таблиц (ключи и поля) могут быть только: таблицы, числа, строки и логические значения;
    5) для взаимодействия используются таблицы SQLite вида (описаны их поля):

    Каждый скрипт, использующий межскриптовое/межпроцессорное взаимодействие создает в соответствующей базе свою таблицу передачи данных, таблицу приема данных и регистрируется в справочнике служебной базы;
    6) строковые данные (функции) передаются скриптами так, как они есть, а табличные данные перед перередачей сереализуются, а при приеме десереализуются.

    В описанной схеме не нужен специальный сервер-процесс для взаимодействия процессов. Запись/чтение таблиц взаимодействия предложенного простого формата в SQLite, даже на накопителе (не говоря уже об оперативной памяти), операции достаточно быстрые (млсек).
    Что нельзя реализовать в рамках изложеннной схемы взаимодействия скриптов?
    Наверное, использование SQLite не лучший вариант, но есть и другие варианты использавания баз в оперативной памяти, например: tarantool, memcached и т.д.
    ---------
    P.S. Специально для «эксперта по IT- терминологии».
    Текущая парадигма программирования состоит не в том, чтобы написать свою программу, а в том, чтобы не повторять то, что уже реализовано в виде, мало отличающемся от того, что хочется реализовать. И для этого есть сеть.

    1. Почему то был потерян формат таблиц взаимодействия. Попытаюсь его восстановить.
      Для взаимодействия используются таблицы SQLite вида (описаны их поля):

      1. Не получилось (наверное из-за угловых скобок). Без использования таких скобок:
        для взаимодействия используются таблицы SQLite вида (описаны их поля):
        Числовой ключ | Дата и время | Кому (на всякий случай) | Тип передаваемых данных | Строка передаваемых данных (строки данные, строки функции, табли-цы)

        1. я встречал в рунете людей, которые используют связку quik - mysql, а довольных такой связкой вообще не встречал.
          чем проще, тем лучше, особенно для начинающих кодеров.

          1. Я написал: "высокое качество реализации пакета". Но так как я не использую этот пакет, то, возможно, моя оценка не достаточно валидна. Только практика использования средств разработки программ является критерием их качества. Вы используете этот пакет и я на месте читателей данной статьи больше бы доверял вам. Но вопросы я могу задавать.

            1. Я с вами не спорю.
              Странно, что у вас возникла ошибка, у меня не было за всю практику использования библиотеки lua_share.
              Посмотрю в ближайшее время обновление QUIK и отпишусь.

              1. Здравствуйте!
                Вы, скорее всего, подключаете пакет lua_share в начале скриптов. Начальные части скриптов (до main) при их запуске выполняются в служебном потоке их обслуживания последовательно даже при их одновременном запуске. Поэтому у вас обсуждаемая ошибка не должна проявляться. В своих экспериментах я специально подключил пакет lua_share в начале функции main, выполняемой для разных запущенных скриптов в различных потоках. Пакеты могут подключаться там, где это требуется.

                1. Здравствуйте!
                  Так и есть, загружается библиотека в начале скриптов локально.
                  Подключение пакетов там, где требуется, может вызвать существенную задержку основного алгоритма, что несовместимо с торговлей.

                  1. Здравствуйте!
                    Что характерно 🙂 : для «совместимости с торговлей» пакеты желательно подключать в начале main (а не в начале скрипта). Если при запуске очередного скрипта, есть уже торгующие скрипты, то возможна задержка торговли в них из-за того, что основной поток QUIK (запускающий колбеки уже работающих скриптов) «отвлечется» дополнительно (к тому, что в нем выполняется запуск самого скрипта) на открытие пакетов запускаемого скрипта.

                    1. То что модули подключать нужно в начале майн, согласен, помимо прочего - это ускоряет запуск терминала.

                    2. Это не одно и тоже. Пакеты подключаемые в начале main открываются в пользовательском потоке отличном от служебного потока QUIK.