repertoire-repertoire-devtools 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Adapted from mongrel_rails_persist by Christopher York on 09/16/2008
4
+
5
+ # Copyright (c) 2007 Apple Inc. All Rights Reserved.
6
+
7
+ # Create a launchd plist to run merb persistently across reboots
8
+
9
+ class MerbPersist
10
+ require 'osx/cocoa'
11
+ include OSX
12
+
13
+ def initialize(args)
14
+ @merb_root = Dir.pwd
15
+ @port = 4000
16
+ @user = nil
17
+ @group = nil
18
+ @merb_args = []
19
+
20
+ while opt = args.shift
21
+ case opt
22
+ when '-m', '--merb-root' then @merb_root = args.shift
23
+ when '-p', '--port'
24
+ @port = args.shift
25
+ [opt, @port].each { |i| @merb_args << i }
26
+ when '-u', '--user' then @user = args.shift
27
+ when '-g', '--group' then @group = args.shift
28
+ when '-d', '--daemonize', '-c', '--cluster-nodes'
29
+ # Silently remove the daemonize option as it doesn't work well with launchd
30
+ else
31
+ [opt, args.shift].each { |i| @merb_args << i }
32
+ end
33
+ end
34
+
35
+ @label = "edu.mit.hyperstudio.persist.port#{@port}.merb_server"
36
+ @plist_path = "/Library/LaunchDaemons/#{@label}.plist"
37
+ end
38
+
39
+ def start
40
+ if ! test(?d,File.dirname(@plist_path))
41
+ raise unless system('/bin/mkdir', '-m', '0755', @plist_path)
42
+ raise unless system('/usr/sbin/chown', 'root:wheel', @plist_path)
43
+ end
44
+
45
+ h = {}
46
+ h['Label'] = @label
47
+ h['OnDemand'] = false
48
+ h['KeepAlive'] = true
49
+ h['ProgramArguments'] = [@merb_root + '/bin/merb', @merb_args].flatten.compact
50
+ h['WorkingDirectory'] = @merb_root
51
+ h['UserName'] = @user if @user
52
+ h['GroupName'] = @group if @group
53
+ h['StandardErrorPath'] = "/var/log/merb_persist_#{@port}.log"
54
+ if h['UserName'] || h['GroupName']
55
+ # Ensure that the log file is writable by the specified user:group
56
+ system('/usr/bin/touch', h['StandardErrorPath']) unless test(?e, h['StandardErrorPath'])
57
+ raise unless system('/usr/sbin/chown', "#{h['UserName']}:#{h['GroupName']}", h['StandardErrorPath'])
58
+ end
59
+
60
+ data = NSPropertyListSerialization.dataFromPropertyList_format_errorDescription(h, NSPropertyListXMLFormat_v1_0, nil)
61
+ plist = NSString.alloc.initWithData_encoding(data, NSUTF8StringEncoding)
62
+ File.open(@plist_path, 'w') { |f| f.puts plist }
63
+
64
+ `/bin/launchctl unload #{@plist_path} >/dev/null 2>&1`
65
+ raise unless system('/bin/launchctl', 'load', @plist_path)
66
+ puts "Loaded #{@plist_path}.\nMerb instance should persist across reboot."
67
+ puts "To stop: #{File.basename($0)} stop -p #{@port}"
68
+ end
69
+
70
+ def stop
71
+ raise unless system('/bin/launchctl', 'unload', @plist_path)
72
+ File.delete(@plist_path)
73
+ puts "Unloaded and deleted #{@plist_path}."
74
+ end
75
+
76
+ def restart
77
+ raise unless system('/bin/launchctl', 'unload', @plist_path)
78
+ sleep(2)
79
+ raise unless system('/bin/launchctl', 'load', @plist_path)
80
+ end
81
+ end
82
+
83
+ if __FILE__ == $0
84
+ usage = <<EOU
85
+ Usage: #{File.basename($0)} -h | [start | restart | stop] [options]
86
+ This is a launchd wrapper for merb.
87
+ See merb command for details.
88
+ EOU
89
+
90
+ if ARGV.empty? || ARGV.include?('-h') || ARGV.include?('--help')
91
+ $stderr.puts usage
92
+ exit
93
+ end
94
+
95
+ begin
96
+ action = ARGV.shift.to_sym
97
+ m = MerbPersist.new(ARGV)
98
+ if m.respond_to?(action)
99
+ m.send(action)
100
+ else
101
+ raise ArgumentError, "#{action}: unknown action"
102
+ end
103
+ rescue ArgumentError => e
104
+ $stderr.puts e.message
105
+ $stderr.puts usage
106
+ rescue => e
107
+ $stderr.puts e.message
108
+ end
109
+ end
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Copyright (c) 2008 MIT. All Rights Reserved.
4
+
5
+ require "rubygems"
6
+ require "pg"
7
+
8
+ #
9
+ # Basic support for crontab-type tasks within PostgreSQL
10
+ #
11
+ # This script makes it easy to schedule periodic tasks in your PostgreSQL database
12
+ # Fits a variety of use-cases: updating full text indexes, cleaning up stale caches, expiring accounts, etc.
13
+ #
14
+ # Initial Hyperstudio use is to maintain full text indexes for database models with many joins
15
+ # (1) moves expensive indexing operations outside of the initial database transaction
16
+ # (2) avoids complicated set of hand-tuned triggers and functions on dependent tables
17
+ # (2) ensures data consistency and integrity by rebuilding index periodically
18
+ #
19
+ # Before running, create the crontab table as follows:
20
+ #
21
+ # CREATE TABLE crontab(id SERIAL PRIMARY KEY,
22
+ # notice TEXT NOT NULL,
23
+ # task TEXT NOT NULL,
24
+ # interval INTERVAL NOT NULL,
25
+ # last_updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT 'epoch',
26
+ # failing BOOLEAN NOT NULL DEFAULT false,
27
+ # message TEXT);
28
+ #
29
+ # This script makes a single sweep through the crontab list, executing pending tasks. To use,
30
+ # run as a cron script (standard UNIX), or launchd task (OS X).
31
+ #
32
+ # If you would like the script to set up the database table and a basic launchd task, you can use
33
+ # the following shortcut:
34
+ # `sudo postgresql_crontab_sweep install <database-name>`
35
+ # on the command line (OS X only). This will generate the relevant files, tables, and start the
36
+ # update polling process.
37
+ #
38
+ # Each task is executed in a separate transaction, so they fail or succeed separately. If the
39
+ # task commits, its timestamp is updated. If it aborts, last_updated_at will show the most
40
+ # recent successful run, and the failing and message fields will be set.
41
+ #
42
+ # Parameters: -d <database> -p <port> -h <host> -u <user> -p <password> [ all are optional ]
43
+ # or: install <database>
44
+ #
45
+ # Because this script should only be run locally to the database, it expects postgres to accept
46
+ # your user without a password prompt (see pg_hba.conf to configure). Usually this user will
47
+ # be 'postgres', the db admin role. When writing tasks, keep in mind that this user will
48
+ # execute them. You may need to qualify tables in separate schemas, and grant access to appropriately.
49
+ #
50
+ # Christopher York 12/8/2008
51
+ #
52
+
53
+
54
+ def run(dbparams)
55
+ # setup and connect
56
+ cron_conn = PGconn.open(dbparams)
57
+ forking = false
58
+
59
+ # get the pending database cron tasks
60
+ pending = cron_conn.exec("SELECT id, notice, task, interval, last_updated_at FROM crontab WHERE last_updated_at + interval < now();")
61
+
62
+ pending.each do |crontask|
63
+ # fork a sub-process for each task, with its own database connection
64
+ forking ||= true
65
+ fork do
66
+ task_conn = PGconn.open(dbparams)
67
+ begin
68
+ # all postgresql cron tasks take place in their own transaction (which is the reason for this script - not possible in plpgsql)
69
+ task_conn.transaction do
70
+ puts crontask[:notice]
71
+ task_conn.exec("UPDATE crontab SET last_updated_at = now(), failing = false, message = NULL WHERE id = #{ crontask['id'] }")
72
+ task_conn.exec(crontask['task'])
73
+ end
74
+ rescue PGError => e
75
+ STDERR.puts "ERROR! #{ Time.now } - #{ e.message }"
76
+ task_conn.exec("UPDATE crontab SET failing = true, message = '#{ e.message }' WHERE id = #{ crontask['id'] }")
77
+ end
78
+ task_conn.close
79
+ exit!
80
+ end
81
+ end
82
+
83
+ cron_conn.close
84
+ Process.wait if forking # avoid zombies by waiting for child processes to finish
85
+ end
86
+
87
+ def install(dbparams)
88
+ launchd_plist = <<-END_OF_PLIST
89
+ <?xml version="1.0" encoding="UTF-8"?>
90
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
91
+ <plist version="1.0">
92
+ <dict>
93
+ <key>Label</key>
94
+ <string>edu.mit.hyperstudio.postgresql.crontab.plist</string>
95
+ <key>OnDemand</key>
96
+ <false/>
97
+ <key>ProgramArguments</key>
98
+ <array>
99
+ <string>/usr/bin/postgresql_crontab_sweep</string>
100
+ <string>-d</string>
101
+ <string>#{dbparams['dbname']}</string>
102
+ </array>
103
+ <key>StartCalendarInterval</key>
104
+ <dict>
105
+ <key>StartInterval</key>
106
+ <integer>5</integer>
107
+ </dict>
108
+ </dict>
109
+ </plist>
110
+ END_OF_PLIST
111
+
112
+ create_table = <<-END_OF_CREATE_TABLE
113
+ CREATE TABLE crontab(id SERIAL PRIMARY KEY,
114
+ notice TEXT NOT NULL,
115
+ task TEXT NOT NULL,
116
+ interval INTERVAL NOT NULL,
117
+ last_updated_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT 'epoch',
118
+ failing BOOLEAN NOT NULL DEFAULT false,
119
+ message TEXT);
120
+ END_OF_CREATE_TABLE
121
+
122
+ File.open('/Library/LaunchDaemons/edu.mit.hyperstudio.postgresql.crontab.plist', 'w') { |f| f.write(launchd_plist) }
123
+
124
+ conn = PGconn.open(dbparams)
125
+ conn.exec(create_table)
126
+ conn.close
127
+ end
128
+
129
+
130
+ # parse params, with defaults
131
+
132
+ opts = {
133
+ :dbname => 'hyperstudio_development',
134
+ :user => 'postgres',
135
+ :port => 5432,
136
+ :host => 'localhost'
137
+ }
138
+
139
+ while opt = ARGV.shift
140
+ case opt
141
+ when '-d' then opts['dbname'] = ARGV.shift
142
+ when '-p' then opts['port'] = ARGV.shfit
143
+ when '-u' then opts['user'] = ARGV.shift
144
+ when '-p' then opts['password'] = ARGV.shift
145
+ when 'install' then install(opts) && exit
146
+ end
147
+ end
148
+
149
+ run(opts)
150
+ exit
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: repertoire-repertoire-devtools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Christopher York
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-15 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ruby-pg
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.0
23
+ version:
24
+ description: Development and server tools for use with Hyperstudio Repertoire
25
+ email: yorkc@mit.edu
26
+ executables:
27
+ - merb_persist
28
+ - postgresql_crontab_sweep
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.txt
33
+ files:
34
+ - README.txt
35
+ has_rdoc: false
36
+ homepage: http://hyperstudio.mit.edu/repertoire
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --main
40
+ - README.txt
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.2.0
59
+ signing_key:
60
+ specification_version: 2
61
+ summary: Server and development tools for use with Hyperstudio Repertoire
62
+ test_files: []
63
+