MyCSS

2010/05/19

Amazon SNSのRubyライブラリを(適当に)つくりました はてなブックマークに追加

Amazon Web ServiceのSimple Notification Serviceですが、Rubyのライブラリが見つからなかったので、適当に作りました。元ネタはRightScale提供のRightAwsで、これをSNS対応させた形です。

ソースを張っておきますので、ご自由にお使いください。動作無保証です。未実装のメソッドもあります。テストも不完全です。無い無い尽くしでアレですが、ご自身の責任範囲でお使いください。

本来であればGitHubからForkさせるべきなんでしょうけど、使い方を把握していないので・・すみません・・

※注:すでに同じ様な事やってらっしゃる方がいました。http://github.com/bemurphy/right_aws/blob/add_sns/lib/sns/right_sns_interface.rb

require "right_aws"

module RightAws

  class SnsInterface < RightAwsBase
    include RightAwsBaseInterface

    DEFAULT_HOST      = 'sns.us-east-1.amazonaws.com'
    DEFAULT_PORT      = 443
    DEFAULT_PROTOCOL  = 'https'
    DEFAULT_PATH      = '/'
    API_VERSION       = '2010-03-31'

    @@bench = AwsBenchmarkingBlock.new
    def self.bench_xml; @@bench.xml;     end
    def self.bench_sns; @@bench.service; end

    # Creates new RightSns instance.
    # 
    # Example:
    #
    #  sns = RightAws::SnsInterface.new(aws_access_key_id, aws_secret_key)
    #
    def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
      params.delete(:nil_representation)
      init({
          :name                => 'SNS',
          :default_host        => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).host    : DEFAULT_HOST,
          :default_port        => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).port    : DEFAULT_PORT,
          :default_service     => DEFAULT_PATH,
          :default_protocol    => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).scheme  : DEFAULT_PROTOCOL,
          :default_api_version => API_VERSION
        },
        aws_access_key_id     || ENV['AWS_ACCESS_KEY_ID'],
        aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
        params)
    end


    #--------------------
    #      APIs
    #--------------------

    def add_permission()
      raise 'Sorry! Not Implemented!'
    end
    
    def confirm_subscription()
      raise 'Sorry! Not Implemented!'
    end
    
    def set_topic_attributes(topic_arn, attribute_name, attribute_value)
      request_params = {'TopicArn' => topic_arn, 'AttributeName' => attribute_name, 'AttributeValue' => attribute_value}
      link   = generate_request("SetTopicAttributes", request_params)
      result = request_info(link, QSnsSetTopicAttributesParser.new(:logger => @logger))
      return result
    rescue Exception
      on_exception
    end
    
    def get_topic_attributes(topic_arn)
      request_params = {'TopicArn' => topic_arn}
      link   = generate_request("GetTopicAttributes", request_params)
      result = request_info(link, QSnsGetTopicAttributesParser.new(:logger => @logger))
      return result
    rescue Exception
      on_exception
    end

    def create_topic(topic_name)
      request_params = {'Name' => topic_name}
      link   = generate_request("CreateTopic", request_params)
      result = request_info(link, QSnsCreateTopicParser.new(:logger => @logger))
      return result
    rescue Exception
      on_exception
    end

    def delete_topic(topic_arn)
      request_params = {'TopicArn' => topic_arn}
      link   = generate_request("DeleteTopic", request_params)
      result = request_info(link, QSnsDeleteTopicParser.new(:logger => @logger))
      return result
    rescue Exception
      on_exception
    end

    def list_topics(next_token = nil )
      request_params = {'NextToken' => next_token}
      link   = generate_request("ListTopics", request_params)
      result = request_info(link, QSnsListTopicsParser.new(:logger => @logger))
      # return result if no block given
      return result unless block_given?
      # loop if block if given
      begin
        # the block must return true if it wanna continue
        break unless yield(result) && result[:next_token]
        # make new request
        request_params['NextToken'] = result[:next_token]
        link   = generate_request("ListTopics", request_params)
        result = request_info(link, QSnsListTopicsParser.new(:logger => @logger))
      end while true
    rescue Exception
      on_exception
    end

    def subscribe(topic_arn, protocol, endpoint)
      request_params = {'TopicArn' => topic_arn, 'Protocol' => protocol, 'Endpoint' => endpoint}
      link   = generate_request("Subscribe", request_params)
      result = request_info(link, QSnsSubscribeParser.new(:logger => @logger))
      return result
    rescue Exception
      on_exception
    end

    def unsubscribe(subscription_arn)
      request_params = {'SubscriptionArn' => subscription_arn}
      link   = generate_request("Unsubscribe", request_params)
      result = request_info(link, QSnsUnubscribeParser.new(:logger => @logger))
      return result
    rescue Exception
      on_exception
    end

    # return {:subscritions => []}
    def list_subscriptions(next_token = nil )
      request_params = {'NextToken' => next_token }
      link   = generate_request("ListSubscriptions", request_params)
      result = request_info(link, QSnsListSubscriptionsParser.new(:logger => @logger))
      # return result if no block given
      return result unless block_given?
      # loop if block if given
      begin
        # the block must return true if it wanna continue
        break unless yield(result) && result[:next_token]
        # make new request
        request_params['NextToken'] = result[:next_token]
        link   = generate_request("ListSubscriptions", request_params)
        result = request_info(link, QSnsListSubscriptionsParser.new(:logger => @logger))
      end while true
    rescue Exception
      on_exception
    end

    # return {:subscritions => []}
    def list_subscriptions_by_topic(topic_arn, next_token = nil )
      request_params = {'TopicArn' => topic_arn, 'NextToken' => next_token}
      link   = generate_request("ListSubscriptionsByTopic", request_params)
      result = request_info(link, QSnsListSubscriptionsParser.new(:logger => @logger))
      # return result if no block given
      return result unless block_given?
      # loop if block if given
      begin
        # the block must return true if it wanna continue
        break unless yield(result) && result[:next_token]
        # make new request
        request_params['NextToken'] = result[:next_token]
        link   = generate_request("ListSubscriptionsByTopic", request_params)
        result = request_info(link, QSnsListSubscriptionsParser.new(:logger => @logger))
      end while true
    rescue Exception
      on_exception
    end

    def publish(topic_arn, subject, message)
      request_params = {'TopicArn' => topic_arn, 'Subject' => subject, 'Message' => message}
      link   = generate_request("Publish", request_params)
      result = request_info(link, QSnsPublishParser.new(:logger => @logger))
      return result
    rescue Exception
      on_exception
    end


    #--------------------
    #      Requests
    #--------------------

    def generate_request(action, params={}) #:nodoc:
      generate_request_impl(:get, action, params )
    end

    # Sends request to Amazon and parses the response
    # Raises AwsError if any banana happened
    def request_info(request, parser)  #:nodoc:
      request_info_impl(:sdb_connection, @@bench, request, parser)
    end

    
    #--------------------
    #      PARSERS:
    #--------------------

    class QSnsCreateTopicParser < RightAWSParser #:nodoc:
      def reset
        @result = {}
      end
      def tagend(name)
        case name
        when 'TopicArn'  then @result[:topic_arn]  =  @text
        when 'RequestId' then @result[:request_id] =  @text
        end
      end
    end

    class QSnsDeleteTopicParser < RightAWSParser #:nodoc:
      def reset
        @result = {}
      end
      def tagend(name)
        case name
        when 'RequestId' then @result[:request_id] =  @text
        end
      end
    end

    class QSnsListTopicsParser < RightAWSParser #:nodoc:
      def reset
        @result = { :topics => [] }
      end
      def tagend(name)
        case name
        when 'NextToken'  then @result[:next_token] =  @text
        when 'TopicArn'   then @result[:topics]     << @text
        end
      end
    end

    class QSnsSubscribeParser < RightAWSParser #:nodoc:
      def reset
        @result = {}
      end
      def tagend(name)
        case name
        when 'SubscriptionArn' then @result[:subscription_arn] =  @text
        when 'RequestId' then @result[:request_id] =  @text
        end
      end
    end

    # same with QSnsDeleteParser...
    class QSnsUnubscribeParser < RightAWSParser #:nodoc:
      def reset
        @result = {}
      end
      def tagend(name)
        case name
        when 'RequestId' then @result[:request_id] =  @text
        end
      end
    end

    class QSnsListSubscriptionsParser < RightAWSParser #:nodoc:
      def reset
        new_member()
        @result = {:subscriptions => [] }
      end
      def tagend(name)
        case name
        when 'NextToken'  then @result[:next_token] =  @text
        when 'TopicArn'   then @member[:topic_arn]  =  @text
        when 'Protocol'   then @member[:protocol]   =  @text
        when 'SubscriptionArn'   then @member[:subscription_arn] =  @text
        when 'Owner'   then @member[:owner]         = @text
        when 'Endpoint'   then @member[:endpoint]   =  @text; @result[:subscriptions] << @member; new_member();
        end
      end
      private
      def new_member
        @member = {:topic_arn => '', :protocol => '', :subscription_arn => '', :owner => '', :endpoint => ''}
      end
    end

    class QSnsPublishParser < RightAWSParser #:nodoc:
      def reset
        @result = {}
      end
      def tagend(name)
        case name
        when 'MessageId' then @result[:message_id] =  @text
        when 'RequestId' then @result[:request_id] =  @text
        end
      end
    end

    # same with QSnsDeleteTopicParser...
    class QSnsSetTopicAttributesParser < RightAWSParser #:nodoc:
      def reset
        @result = {}
      end
      def tagend(name)
        case name
        when 'RequestId' then @result[:request_id] =  @text
        end
      end
    end

    class QSnsGetTopicAttributesParser < RightAWSParser #:nodoc:
      def reset
        @result = {:attributes => []}
      end
      def tagend(name)
        case name
        when 'key' then @key = @text
        when 'value' then @result[:attributes] << {:key => @key, :value => @text}
        when 'RequestId' then @result[:request_id] =  @text
        end
      end
    end
  end

end

0 件のコメント :

コメントを投稿