{"id":15107713,"url":"https://github.com/mumez/tarantalk","last_synced_at":"2025-10-23T02:31:31.238Z","repository":{"id":147003636,"uuid":"76957539","full_name":"mumez/Tarantalk","owner":"mumez","description":"Tarantool connector for Pharo Smalltalk","archived":false,"fork":false,"pushed_at":"2022-03-24T09:06:07.000Z","size":277,"stargazers_count":15,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-09-25T21:41:05.203Z","etag":null,"topics":["pharo","pharo-smalltalk","tarantool"],"latest_commit_sha":null,"homepage":null,"language":"Smalltalk","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mumez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-12-20T13:10:39.000Z","updated_at":"2022-03-24T09:06:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"fcf4a28b-4025-4b53-9b61-eb60c7e81a0a","html_url":"https://github.com/mumez/Tarantalk","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mumez%2FTarantalk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mumez%2FTarantalk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mumez%2FTarantalk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mumez%2FTarantalk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mumez","download_url":"https://codeload.github.com/mumez/Tarantalk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219871956,"owners_count":16554471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pharo","pharo-smalltalk","tarantool"],"created_at":"2024-09-25T21:41:11.884Z","updated_at":"2025-10-23T02:31:29.576Z","avatar_url":"https://github.com/mumez.png","language":"Smalltalk","funding_links":[],"categories":[],"sub_categories":[],"readme":"Tarantalk\r\n========\r\n\r\n[Tarantool](https://tarantool.org/ \"Tarantool\") client for [Pharo Smalltalk](http://www.pharo-project.org/ \"Pharo\").\r\n\r\nTarantalk = Smalltalk + Lua + Tuple DB.\r\n\r\nEnjoy its chemical effects on such a dynamic environment. \r\n\r\n## Installation ##\r\n\r\nYou can install via Catalog Browser, or just do it:\r\n\r\n```Smalltalk\r\nMetacello new\r\n  baseline: 'Tarantalk';\r\n  repository: 'github://mumez/Tarantalk/repository';\r\n  load.\r\n```\r\n\r\n## Settings ##\r\n\r\nTarantool supports authentication and fine-grained access control. So, you should add a user for Tarantalk from the tarantool admin console.\r\n\r\n```Lua\r\nbox.cfg{listen = 3301}\r\nbox.schema.user.create('taran', {password='talk', if_not_exists=true})\r\nbox.schema.user.grant('taran', 'read,write,execute,create,drop', 'universe', nil, {if_not_exists=true})\r\n```\r\n\r\n## Connecting\r\n\r\nYou can pass a URI for connecting a running tarantool instance.\r\n\r\n```Smalltalk\r\ntarantalk := TrTarantalk connect: 'taran:talk@localhost:3301'.\r\n```\r\n\r\n## Usages ##\r\n\r\n### Storing tuples\r\n\r\n```Smalltalk\r\n\"Create a space\"\r\ntarantalk := TrTarantalk connect: 'taran:talk@localhost:3301'.\r\nspace := tarantalk ensureSpaceNamed: 'bookmarks'.\r\n```\r\n\r\n```Smalltalk\r\n\"Create a primary TREE index (string typed)\"\r\nprimaryIndex := space ensurePrimaryIndexSetting: [ :options | options tree; partsTypes: #(#string)].\r\n```\r\n\r\n```Smalltalk\r\n\"Insert tuples\"\r\nspace insert: #('Tarantool' 'https://tarantool.org' 'Tarantool main site').\r\nspace insert: #('Pharo books' 'http://files.pharo.org/books/' 'Pharo on-line books').\r\nspace insert: #('Pharo' 'http://pharo.org' 'Pharo main site').\r\nspace insert: #('Smalltalkユーザ会' 'http://www.smalltalk-users.jp' 'Japan Smalltalk users group').\r\n```\r\n\r\n### Retrieving tuples\r\n\r\n```Smalltalk\r\n\"Select all tuples in a space\"\r\nprimaryIndex selectAll.\r\n```\r\n```Smalltalk\r\n\"Find a tuple with 'Pharo' element\"\r\nprimaryIndex selectHaving: #('Pharo').\r\n  \" =\u003e #(#('Pharo' 'http://pharo.org' 'Pharo main site'))\"\r\n```\r\n```Smalltalk\r\n\"Find tuples with a condition.\"\r\nprimaryIndex select: #\u003e= having: #('Smalltalkユーザ会').\r\n  \" =\u003e #(#('Smalltalkユーザ会' 'http://www.smalltalk-users.jp' 'Japan Smalltalk users group') #('Tarantool' 'https://tarantool.org' 'Tarantool main site'))\"\r\n```\r\n\r\n### Updating tuples\r\n```Smalltalk\r\n\"Update the first field in a tuple\"\r\nprimaryIndex updateHaving: #('Pharo books') performing: [:row | row @ 1 assign: 'http://books.pharo.org'].\r\nprimaryIndex selectHaving: #('Pharo books').\r\n  \" =\u003e #(#('Pharo books' 'http://books.pharo.org' 'Pharo on-line books'))\"\r\n```\r\n\r\n### Evaluating Lua expression\r\n\r\n```Smalltalk\r\n(tarantalk evalWithReturn: 'string.match(\"Hello, world!\", \"w(%w+)\")') value.\r\n  \" =\u003e #('orld')\"\r\n```\r\n\r\n```Smalltalk\r\n(tarantalk evalWithReturn: '(require(\"digest\").sha512_hex(...))' arguments: {'Hello, Smalltalk'}) value.\r\n  \" =\u003e #('ec599e128831b282f6f7a833834c90a3eb2e61453e5757ca3c2bc8a26e94d7c2f76bd6a7ce33df2427f3821e44a12d26781d39eac6782b59a649950ea59f9e13')\"\r\n```\r\n\r\n### Calling Lua stored function\r\n\r\n```Lua\r\nfunction bookmarkUrls()\r\n\tlocal urls = {}\r\n\tfor k,v in box.space.bookmarks:pairs() do\r\n\t\ttable.insert(urls, v[2])\r\n\tend\r\n\treturn urls\r\nend\r\nbox.schema.func.create('bookmarkUrls', {if_not_exists=true})\r\n```\r\n\r\n```Smalltalk\r\ntarantalk call: 'bookmarkUrls'.\r\n  \" =\u003e #(#('http://pharo.org' 'http://files.pharo.org/books/' 'http://www.smalltalk-users.jp' 'https://tarantool.org'))\"\r\n```\r\n\r\n### Releasing\r\n\r\n```Smalltalk\r\ntarantalk release.\r\n\r\n\"OR\"\r\n\r\nTrTarantalk releaseAll.\r\n```\r\n## SQL\r\n\r\nPlease see [SQL.md](./doc/SQL.md).\r\n\r\n## TaskIt integration\r\n\r\nPlease see [TaskIt-integration.md](./doc/TaskIt-integration.md).\r\n\r\n## Performance\r\n\r\nI tried a simple micro benchmark and compared the results with my Redis client - [RediStick](\u003chttp://smalltalkhub.com/#!/~MasashiUmezawa/RediStick\u003e \"RediStick\").\r\n\r\nTarantalk outperformed RediStick well (more than 5x faster).\r\nI think the reason is partly related to the async-write API of Tarantool. But it is still remarkable.\r\n\r\n### The results\r\nOn mid 2013 MacBook Air (1.7GHz Core i7, 8GB RAM).\r\n\r\n|  | Tarantalk | RediStick |\r\n|-----------|-----------|-----------|\r\n| Simple Get/Put round-trips (1st try to an empty space) | 0:00:00:03.104 | 0:00:00:14.449 |\r\n| Simple Get/Put round-trips (2nd try) | 0:00:00:03.184 | 0:00:00:15.291 |\r\n| Deleting keys | 0:00:00:00.931 | 0:00:00:07.166 |\r\n\r\n### Tarantalk code\r\n```Smalltalk\r\ntarantalk := TrTarantalk connect: 'taran:talk@localhost:3301'.\r\nspace := tarantalk ensureSpaceNamed: 'perf'.\r\nspace ensurePrimaryIndex.\r\n```\r\n\r\n```Smalltalk\r\n\"Simple Get/Put round-trips\"\r\n[  \r\n  1 to: 10000 do: [:idx | | ret newVal |\r\n    newVal := idx asString.\r\n    space at: idx put: newVal.\r\n    ret := space at: idx.\r\n    (ret = newVal) ifFalse: [ self halt ]. \"for checking that value is correctly stored\"\r\n  ]\r\n] timeToRun.\r\n```\r\n```Smalltalk\r\n\"Deleting keys\"\r\n[  \r\n  1 to: 10000 do: [:idx | \r\n    space removeKey: idx\r\n  ]\r\n] timeToRun.\r\n```\r\n\r\n### RediStick code\r\n\r\n```Smalltalk\r\nstick := RsRediStick targetUrl: 'sync://localhost'.\r\nstick connect.\r\nredisEndPoint := stick endpoint.\r\n```\r\n\r\n```Smalltalk\r\n\"Simple Get/Put round-trips\"\r\n[  \r\n  1 to: 10000 do: [:idx | | ret newVal |\r\n    newVal := idx asString.\r\n    redisEndPoint set: idx value: newVal.\r\n    ret := redisEndPoint get: idx.\r\n    (ret = newVal) ifFalse: [ self halt ]. \"for checking that value is correctly stored\"\r\n  ]\r\n] timeToRun.\r\n```\r\n```Smalltalk\r\n\"Deleting keys\"\r\n[  \r\n  1 to: 10000 do: [:idx |\r\n    redisEndPoint del: {idx}.\r\n  ].\r\n] timeToRun.\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmumez%2Ftarantalk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmumez%2Ftarantalk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmumez%2Ftarantalk/lists"}