meeseeker 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/Gemfile +4 -0
- data/LICENSE +41 -0
- data/README.md +178 -0
- data/Rakefile +75 -0
- data/bin/meeseeker +48 -0
- data/lib/meeseeker/block_follower_job.rb +64 -0
- data/lib/meeseeker/version.rb +3 -0
- data/lib/meeseeker.rb +19 -0
- data/meeseeker.gemspec +26 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c77b50a00bf28514314ae08d98371ebdca3215549843665d82d111080ed466c3
|
4
|
+
data.tar.gz: 0ae8f242244db5535800836cede789ab459e3b6091e610cb1b0fb1bf7fab9019
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c1a9b6e6280f27661b7a2447b34caf8fe2757b8bd87a52c7dc7112aab6f0ce2fac8307cdb631e728bdf503ac9f13d57748fc8d5f481acb104a8c54abaf5ec6d3
|
7
|
+
data.tar.gz: 37c5f658c328e6436f977305b9ecb7b2ea7d3343bf6a873aeb6baf6edcd3860d3fac1fa729b5178f6af18affe8557d38e9a7bd06a889d4bb6fb0aea88cf71a89
|
data/.gitignore
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
CC0 1.0 Universal (CC0 1.0)
|
2
|
+
Public Domain Dedication
|
3
|
+
https://creativecommons.org/publicdomain/zero/1.0/
|
4
|
+
|
5
|
+
This is a human-readable summary of the Legal Code:
|
6
|
+
https://creativecommons.org/publicdomain/zero/1.0/legalcode
|
7
|
+
|
8
|
+
Disclaimer
|
9
|
+
|
10
|
+
The Commons Deed is not a legal instrument. It is simply a handy reference for
|
11
|
+
understanding the CC0 Legal Code, a human-readable expression of some of its key
|
12
|
+
terms. Think of it as the user-friendly interface to the CC0 Legal Code beneath.
|
13
|
+
This Deed itself has no legal value, and its contents do not appear in CC0.
|
14
|
+
Creative Commons is not a law firm and does not provide legal services.
|
15
|
+
Distributing, displaying, or linking to this Commons Deed does not create an
|
16
|
+
attorney-client relationship.
|
17
|
+
|
18
|
+
Creative Commons has not verified the copyright status of any work to which CC0
|
19
|
+
has been applied. CC makes no warranties about any work or its copyright status
|
20
|
+
in any jurisdiction, and disclaims all liability for all uses of any work.
|
21
|
+
|
22
|
+
No Copyright
|
23
|
+
|
24
|
+
The person who associated a work with this deed has dedicated the work to the
|
25
|
+
public domain by waiving all of his or her rights to the work worldwide under
|
26
|
+
copyright law, including all related and neighboring rights, to the extent
|
27
|
+
allowed by law.
|
28
|
+
|
29
|
+
You can copy, modify, distribute and perform the work, even for commercial
|
30
|
+
purposes, all without asking permission. See Other Information below.
|
31
|
+
|
32
|
+
Other Information
|
33
|
+
|
34
|
+
* In no way are the patent or trademark rights of any person affected by CC0,
|
35
|
+
nor are the rights that other persons may have in the work or in how the work
|
36
|
+
is used, such as publicity or privacy rights.
|
37
|
+
* Unless expressly stated otherwise, the person who associated a work with this
|
38
|
+
deed makes no warranties about the work, and disclaims liability for all uses
|
39
|
+
of the work, to the fullest extent permitted by applicable law.
|
40
|
+
* When using or citing the work, you should not imply endorsement by the author
|
41
|
+
or the affirmer.
|
data/README.md
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
# meeseeker
|
2
|
+
|
3
|
+
Redis based block follower is an efficient way for multiple apps to stream the Steem Blockchain.
|
4
|
+
|
5
|
+
If you have multiple applications that need to perform actions as operations occur, `meeseeker` will allow your apps to each perform actions for specific operations without each app having to streaming the entire blockchain.
|
6
|
+
|
7
|
+
*In a nutshell:* The overarching intent here is to provide a "live view" of the blockchain, *not* store the entire blockchain. Apps can attach to your redis source and ask, "What *just* happened?"
|
8
|
+
|
9
|
+
## Purpose
|
10
|
+
|
11
|
+
Although Meeseeker tracks all operations, it is only intended to provide other applications signals that those operations have happened. It is not intended to provide cryptographically verifiable events.
|
12
|
+
|
13
|
+
Possible uses:
|
14
|
+
|
15
|
+
* Notifications of events, suitable for push to mobile devices or web browsers.
|
16
|
+
* Invoke periodic updates on a threshold.
|
17
|
+
* Light-weight bots that only care about a limit set of operations, reducing the number of API calls.
|
18
|
+
|
19
|
+
## Why Redis?
|
20
|
+
|
21
|
+
Redis is a persistent key-value database, with built-in net interface. See: https://redis.io/
|
22
|
+
|
23
|
+
It allows for quick storage and lookup of operations by key as well as the ability to automatically expire keys that are no longer needed.
|
24
|
+
|
25
|
+
### Installation
|
26
|
+
|
27
|
+
First, install redis:
|
28
|
+
|
29
|
+
On linux:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
sudo apt install redis-server
|
33
|
+
```
|
34
|
+
|
35
|
+
On macOS:
|
36
|
+
|
37
|
+
```bash
|
38
|
+
brew install redis
|
39
|
+
```
|
40
|
+
|
41
|
+
Next, install ruby. One way to do this is install [rvm](https://rvm.io/install). Once ruby is installed, install `meeseeker` with the `gem` command:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
gem install meeseeker
|
45
|
+
```
|
46
|
+
|
47
|
+
This installs meeseeker as a command available to the OS, e.g.:
|
48
|
+
|
49
|
+
```bash
|
50
|
+
meeseeker help
|
51
|
+
```
|
52
|
+
|
53
|
+
To do the actual sync to your local redis source (defaults assume `redis://127.0.0.1:6379/0`):
|
54
|
+
|
55
|
+
```bash
|
56
|
+
meeseeker sync
|
57
|
+
```
|
58
|
+
|
59
|
+
To specify an alternative redis source:
|
60
|
+
|
61
|
+
```bash
|
62
|
+
MEESEEKER_REDIS_URL=redis://:p4ssw0rd@10.0.1.1:6380/15 meeseeker sync
|
63
|
+
```
|
64
|
+
|
65
|
+
You can also specify an alternative Steem node:
|
66
|
+
|
67
|
+
```bash
|
68
|
+
MEESEEKER_NODE_URL=https://api.steemit.com meeseeker sync
|
69
|
+
```
|
70
|
+
|
71
|
+
To sync from the head block instead of the last irreversible block:
|
72
|
+
|
73
|
+
```bash
|
74
|
+
MEESEEKER_STREAM_MODE=head meeseeker sync
|
75
|
+
```
|
76
|
+
|
77
|
+
To ignore virtual operations (useful if the node doesn't enable `get_ops_in_blocks` or if you want to sync from the head block):
|
78
|
+
|
79
|
+
```bash
|
80
|
+
MEESEEKER_INCLUDE_VIRTUAL=false meeseeker sync
|
81
|
+
```
|
82
|
+
|
83
|
+
Normally, keys stay on redis for 24 hours. If you want to change this behavior, use `MEESEEKER_EXPIRE_KEYS` and specify the new value in seconds, for example:
|
84
|
+
|
85
|
+
```bash
|
86
|
+
MEESEEKER_EXPIRE_KEYS=10 meeseeker sync
|
87
|
+
```
|
88
|
+
|
89
|
+
### Usage
|
90
|
+
|
91
|
+
When `meeseeker sync` starts for the first time, it initializes from the last irreversible block number. If the sync is interrupted, it will resume from the last block sync'd unless that block is older than `MEESEEKER_EXPIRE_KEYS` in which case it will skip to the last irreversible block number.
|
92
|
+
|
93
|
+
#### Using `SCAN`
|
94
|
+
|
95
|
+
From the redis manual:
|
96
|
+
|
97
|
+
> Since these commands allow for incremental iteration, returning only a small number of elements per call, they can be used in production without the downside of commands like KEYS or SMEMBERS that may block the server for a long time (even several seconds) when called against big collections of keys or elements.
|
98
|
+
>
|
99
|
+
> However while blocking commands like SMEMBERS are able to provide all the elements that are part of a Set in a given moment, The SCAN family of commands only offer limited guarantees about the returned elements since the collection that we incrementally iterate can change during the iteration process.
|
100
|
+
|
101
|
+
See: https://redis.io/commands/scan
|
102
|
+
|
103
|
+
Once you're sync has started, you can begin doing queries against redis, for example, in the `redis-cli`:
|
104
|
+
|
105
|
+
```bash
|
106
|
+
redis-cli --scan --pattern 'steem:*:vote'
|
107
|
+
```
|
108
|
+
|
109
|
+
This returns the keys, for example:
|
110
|
+
|
111
|
+
```
|
112
|
+
steem:29811083:7fd2ea1c73e6cc08ab6e24cf68e67ff19a05896a:0:vote
|
113
|
+
steem:29811085:091c3df76322ec7f0dc51a6ed526ff9a9f69869e:0:vote
|
114
|
+
steem:29811085:24bfc199501779b6c2be2370fab1785f58062c5a:0:vote
|
115
|
+
steem:29811086:36761db678fe89df48d2c5d11a23cdafe57b2476:0:vote
|
116
|
+
steem:29811085:f904ac2e5e338263b03b640a4d1ff2d5fd01169e:0:vote
|
117
|
+
steem:29811085:44036fde09f20d91afda8fc2072b383935c0b615:0:vote
|
118
|
+
steem:29811086:570abf0fbeeeb0bb5c1e26281f0acb1daf175c39:0:vote
|
119
|
+
steem:29811083:e3ee518c4958a10f0d0c5ed39e3dc736048e8ec7:0:vote
|
120
|
+
steem:29811083:e06be9ade6758df59e179160b749d1ace3508044:0:vote
|
121
|
+
```
|
122
|
+
|
123
|
+
To get the actual vote operation for a particular key, use:
|
124
|
+
|
125
|
+
```bash
|
126
|
+
redis-cli get steem:29811085:f904ac2e5e338263b03b640a4d1ff2d5fd01169e:0:vote
|
127
|
+
```
|
128
|
+
|
129
|
+
If, on the other hand, you want `custom_json` only:
|
130
|
+
|
131
|
+
```bash
|
132
|
+
redis-cli --scan --pattern 'steem:*:custom_json'
|
133
|
+
```
|
134
|
+
|
135
|
+
This only returns the related keys, for example:
|
136
|
+
|
137
|
+
```
|
138
|
+
steem:29811084:43f1e1a367b97ea4e05fbd3a80a42146d97121a2:0:custom_json
|
139
|
+
steem:29811085:5795ff73234d64a11c1fb78edcae6f5570409d8e:0:custom_json
|
140
|
+
steem:29811083:2d6635a093243ef7a779f31a01adafe6db8c53c9:0:custom_json
|
141
|
+
steem:29811086:31ecb9c85e9eabd7ca2460fdb4f3ce4a7ca6ec32:0:custom_json
|
142
|
+
steem:29811083:7fbbde120aef339511f5af1a499f62464fbf4118:0:custom_json
|
143
|
+
steem:29811083:04a6ddc83a63d024b90ca13996101b83519ba8f5:0:custom_json
|
144
|
+
```
|
145
|
+
|
146
|
+
To get the actual custom json operation for a particular key, use:
|
147
|
+
|
148
|
+
```bash
|
149
|
+
redis-cli get steem:29811083:7fbbde120aef339511f5af1a499f62464fbf4118:0:custom_json
|
150
|
+
```
|
151
|
+
|
152
|
+
To get all transactions for a particular block number:
|
153
|
+
|
154
|
+
```bash
|
155
|
+
redis-cli --scan --pattern 'steem:29811085:*'
|
156
|
+
```
|
157
|
+
|
158
|
+
Or to get all ops for a particular transaction:
|
159
|
+
|
160
|
+
```bash
|
161
|
+
redis-cli --scan --pattern 'steem:*:31ecb9c85e9eabd7ca2460fdb4f3ce4a7ca6ec32:*'
|
162
|
+
```
|
163
|
+
|
164
|
+
---
|
165
|
+
|
166
|
+
<center>
|
167
|
+
<img src="https://i.imgur.com/Y3Sa2GW.jpg" />
|
168
|
+
</center>
|
169
|
+
|
170
|
+
See some of my previous Ruby How To posts in: [#radiator](https://steemit.com/created/radiator) [#ruby](https://steemit.com/created/ruby)
|
171
|
+
|
172
|
+
## Get in touch!
|
173
|
+
|
174
|
+
If you're using Radiator, I'd love to hear from you. Drop me a line and tell me what you think! I'm @inertia on STEEM.
|
175
|
+
|
176
|
+
## License
|
177
|
+
|
178
|
+
I don't believe in intellectual "property". If you do, consider Radiator as licensed under a Creative Commons [![CC0](http://i.creativecommons.org/p/zero/1.0/80x15.png)](http://creativecommons.org/publicdomain/zero/1.0/) License.
|
data/Rakefile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
require 'meeseeker'
|
4
|
+
|
5
|
+
Rake::TestTask.new(:test) do |t|
|
6
|
+
t.libs << 'test'
|
7
|
+
t.libs << 'lib'
|
8
|
+
t.test_files = FileList['test/**/*_test.rb']
|
9
|
+
t.ruby_opts << if ENV['HELL_ENABLED']
|
10
|
+
'-W2'
|
11
|
+
else
|
12
|
+
'-W1'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
task :default => :test
|
17
|
+
|
18
|
+
task :console do
|
19
|
+
exec "irb -r meeseeker -I ./lib"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Build a new version of the meeseeker gem.'
|
23
|
+
task :build do
|
24
|
+
exec 'gem build meeseeker.gemspec'
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Publish the current version of the meeseeker gem.'
|
28
|
+
task :push do
|
29
|
+
exec "gem push meeseeker-#{Meeseeker::VERSION}.gem"
|
30
|
+
end
|
31
|
+
|
32
|
+
task :check_schema do
|
33
|
+
begin
|
34
|
+
abort 'Unable to ping redis source.' unless Meeseeker.redis.ping == 'PONG'
|
35
|
+
rescue Redis::CommandError => e
|
36
|
+
puts e
|
37
|
+
rescue Redis::CannotConnectError => e
|
38
|
+
puts e
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task(:sync, [:at_block_num] => [:check_schema]) do |t, args|
|
43
|
+
job = Meeseeker::BlockFollowerJob.new
|
44
|
+
job.perform(at_block_num: args[:at_block_num])
|
45
|
+
end
|
46
|
+
|
47
|
+
task(:find, [:what, :key] => [:check_schema]) do |t, args|
|
48
|
+
redis = Meeseeker.redis
|
49
|
+
match = case args[:what].downcase.to_sym
|
50
|
+
when :block then "steem:#{args[:key]}:*"
|
51
|
+
when :trx then "steem:*:#{args[:key]}:*"
|
52
|
+
else; abort "Unknown lookup using #{args}"
|
53
|
+
end
|
54
|
+
|
55
|
+
puts "Looking for match on: #{match}"
|
56
|
+
keys = redis.keys(match)
|
57
|
+
|
58
|
+
keys.each do |key|
|
59
|
+
puts key
|
60
|
+
puts redis.get(key)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
task reset: [:check_schema] do
|
65
|
+
print 'Dropping keys ...'
|
66
|
+
keys = Meeseeker.redis.keys('steem:*')
|
67
|
+
|
68
|
+
if keys.any?
|
69
|
+
print " found #{keys.size} keys ..."
|
70
|
+
dropped = Meeseeker.redis.del(*keys)
|
71
|
+
puts " dropped #{dropped} keys."
|
72
|
+
else
|
73
|
+
puts ' nothing to drop.'
|
74
|
+
end
|
75
|
+
end
|
data/bin/meeseeker
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'pp'
|
5
|
+
require 'meeseeker'
|
6
|
+
|
7
|
+
gem_dir = File.expand_path("..", File.dirname(__FILE__))
|
8
|
+
$LOAD_PATH.unshift gem_dir
|
9
|
+
|
10
|
+
pwd = Dir.pwd
|
11
|
+
Dir.chdir(gem_dir)
|
12
|
+
Rake.application.init
|
13
|
+
Rake.application.load_rakefile
|
14
|
+
Dir.chdir(pwd)
|
15
|
+
|
16
|
+
puts "meeseeker-#{Meeseeker::VERSION}"
|
17
|
+
filename = __FILE__.split('/').last
|
18
|
+
|
19
|
+
case ARGV[0]
|
20
|
+
when 'console' then Rake::Task['console'].invoke
|
21
|
+
when 'sync'
|
22
|
+
backoff = 0.01
|
23
|
+
max_backoff = 30
|
24
|
+
|
25
|
+
loop do; begin
|
26
|
+
Rake::Task['sync'].invoke(ARGV[1])
|
27
|
+
rescue Steem::BaseError => e
|
28
|
+
puts "Error: #{e.inspect}"
|
29
|
+
backoff = [backoff, max_backoff].min
|
30
|
+
sleep backoff *= 2
|
31
|
+
puts "Retrying ..."
|
32
|
+
Rake::Task['sync'].reenable
|
33
|
+
end; end
|
34
|
+
when 'find' then Rake::Task['find'].invoke(*ARGV[1..-1])
|
35
|
+
when 'reset' then Rake::Task['reset'].invoke
|
36
|
+
else
|
37
|
+
puts "\nBegin/resume sync:"
|
38
|
+
puts "\t#{filename} sync\n\n"
|
39
|
+
puts "Start in the ruby console:"
|
40
|
+
puts "\t#{filename} console\n\n"
|
41
|
+
puts 'Find block or transaction:'
|
42
|
+
puts "\t#{filename} find block 3044538"
|
43
|
+
puts "\t#{filename} find trx 983c5e5c6aef52f1647d952a18771f76b885e6de\n\n"
|
44
|
+
puts 'Clear all keys:'
|
45
|
+
puts "\t#{filename} reset\n\n"
|
46
|
+
puts "Note, using find and reset is not intended for routine operations. It is intended for analysis only."
|
47
|
+
puts "See: https://github.com/inertia186/meeseeker#usage"
|
48
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Meeseeker
|
2
|
+
class BlockFollowerJob
|
3
|
+
def perform(options = {})
|
4
|
+
stream = Steem::Stream.new(url: Meeseeker.node_url, mode: Meeseeker.stream_mode)
|
5
|
+
database_api = Steem::DatabaseApi.new(url: Meeseeker.node_url)
|
6
|
+
redis = Meeseeker.redis
|
7
|
+
|
8
|
+
if !!options[:at_block_num]
|
9
|
+
last_block_num = options[:at_block_num].to_i
|
10
|
+
else
|
11
|
+
last_block_num = redis.get(LAST_BLOCK_NUM_KEY).to_i + 1
|
12
|
+
|
13
|
+
database_api.get_dynamic_global_properties do |dgpo|
|
14
|
+
block_num = case Meeseeker.stream_mode
|
15
|
+
when :head then dgpo.last_irreversible_block_num
|
16
|
+
when :irreversible then dgpo.last_irreversible_block_num
|
17
|
+
else; abort "Unknown stream mode: #{Meeseeker.stream_mode}"
|
18
|
+
end
|
19
|
+
|
20
|
+
if block_num - last_block_num > Meeseeker.expire_keys / 3
|
21
|
+
last_block_num = block_num
|
22
|
+
|
23
|
+
puts 'Starting new sync.'
|
24
|
+
else
|
25
|
+
behind_sec = block_num - last_block_num
|
26
|
+
behind_sec *= 3.0
|
27
|
+
|
28
|
+
puts "Resuming from #{behind_sec / 60} minutes ago ..."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
options = {
|
34
|
+
at_block_num: last_block_num,
|
35
|
+
include_virtual: Meeseeker.include_virtual
|
36
|
+
}
|
37
|
+
|
38
|
+
if !!last_block_num
|
39
|
+
puts options.to_json
|
40
|
+
end
|
41
|
+
|
42
|
+
last_key_prefix = nil
|
43
|
+
trx_index = 0
|
44
|
+
|
45
|
+
stream.operations(options) do |op, trx_id, block_num|
|
46
|
+
current_key_prefix = "steem:#{block_num}:#{trx_id}"
|
47
|
+
|
48
|
+
if current_key_prefix == last_key_prefix
|
49
|
+
trx_index += 1
|
50
|
+
else
|
51
|
+
last_key_prefix = "steem:#{block_num}:#{trx_id}"
|
52
|
+
trx_index = 0
|
53
|
+
end
|
54
|
+
|
55
|
+
op_type = op.type.split('_')[0..-2].join('_')
|
56
|
+
key = "#{current_key_prefix}:#{trx_index}:#{op_type}"
|
57
|
+
puts key
|
58
|
+
redis.set(key, op.to_json)
|
59
|
+
redis.expire(key, Meeseeker.expire_keys)
|
60
|
+
redis.set(LAST_BLOCK_NUM_KEY, block_num)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/meeseeker.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'steem'
|
3
|
+
|
4
|
+
require 'meeseeker/version'
|
5
|
+
require 'meeseeker/block_follower_job'
|
6
|
+
|
7
|
+
module Meeseeker
|
8
|
+
LAST_BLOCK_NUM_KEY = 'steem:meeseeker:last_block_num'
|
9
|
+
BLOCKS_PER_DAY = 28800
|
10
|
+
@redis = Redis.new(url: ENV.fetch('MEESEEKER_REDIS_URL', 'redis://127.0.0.1:6379/0'))
|
11
|
+
@node_url = ENV.fetch('MEESEEKER_NODE_URL', 'https://api.steemit.com')
|
12
|
+
@stream_mode = ENV.fetch('MEESEEKER_STREAM_MODE', 'head').downcase.to_sym
|
13
|
+
@include_virtual = ENV.fetch('MEESEEKER_INCLUDE_VIRTUAL', 'true').downcase == 'true'
|
14
|
+
@expire_keys = ENV.fetch('MEESEEKER_EXPIRE_KEYS', BLOCKS_PER_DAY * 3).to_i
|
15
|
+
|
16
|
+
extend self
|
17
|
+
|
18
|
+
attr_accessor :redis, :node_url, :expire_keys, :stream_mode, :include_virtual
|
19
|
+
end
|
data/meeseeker.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'meeseeker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'meeseeker'
|
8
|
+
s.version = Meeseeker::VERSION
|
9
|
+
s.licenses = 'CC0-1.0'
|
10
|
+
s.summary = 'Redis based block follower is an efficient way for multiple apps to stream the Steem Blockchain.'
|
11
|
+
s.description = 'If you have multiple applications that need to perform actions as operations occur, `meeseeker` will allow your apps to each perform actions for specific operations without each app having to streaming the entire blockchain.'
|
12
|
+
s.authors = ['Anthony Martin']
|
13
|
+
s.email = ['meeseeker@martin-studio.com,']
|
14
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test)/}) }
|
15
|
+
s.homepage = 'https://rubygems.org/gems/meeseeker'
|
16
|
+
s.metadata = { 'source_code_uri' => 'https://github.com/inertia186/meeseeker' }
|
17
|
+
s.bindir = 'bin'
|
18
|
+
s.executables = 'meeseeker'
|
19
|
+
|
20
|
+
# Ruby Make (interprets the Rakefile DSL).
|
21
|
+
s.add_development_dependency 'rake', '~> 12.3', '>= 12.3.1'
|
22
|
+
|
23
|
+
s.add_dependency 'redis', '~> 4.1', '>= 4.1.0'
|
24
|
+
s.add_dependency 'steem-mechanize', '~> 0.0', '>= 0.0.5'
|
25
|
+
s.add_dependency 'rb-readline', '~> 0.5', '>= 0.5.5'
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: meeseeker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anthony Martin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '12.3'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 12.3.1
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '12.3'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 12.3.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: redis
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.1'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 4.1.0
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '4.1'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 4.1.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: steem-mechanize
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.0'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.0.5
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.0'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 0.0.5
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: rb-readline
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0.5'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.5.5
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.5'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 0.5.5
|
93
|
+
description: If you have multiple applications that need to perform actions as operations
|
94
|
+
occur, `meeseeker` will allow your apps to each perform actions for specific operations
|
95
|
+
without each app having to streaming the entire blockchain.
|
96
|
+
email:
|
97
|
+
- meeseeker@martin-studio.com,
|
98
|
+
executables:
|
99
|
+
- meeseeker
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- ".gitignore"
|
104
|
+
- Gemfile
|
105
|
+
- LICENSE
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- bin/meeseeker
|
109
|
+
- lib/meeseeker.rb
|
110
|
+
- lib/meeseeker/block_follower_job.rb
|
111
|
+
- lib/meeseeker/version.rb
|
112
|
+
- meeseeker.gemspec
|
113
|
+
homepage: https://rubygems.org/gems/meeseeker
|
114
|
+
licenses:
|
115
|
+
- CC0-1.0
|
116
|
+
metadata:
|
117
|
+
source_code_uri: https://github.com/inertia186/meeseeker
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.7.7
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: Redis based block follower is an efficient way for multiple apps to stream
|
138
|
+
the Steem Blockchain.
|
139
|
+
test_files: []
|