SlideShare a Scribd company logo
1 of 59
Tatsumaki
non-blocking web framework built on Plack/AnyEvent

                Tatsuhiko Miyagawa
    Nov. 30th, 2009 / Shibuya.pm Tech Talks #12
PSGI
Perl Web Server
Gateway Interface
Python’s WSGI
 Ruby’s Rack
my $app = sub {
   my $env = shift;
   return [ $status, $headers, $body ];
};
Plain Old Perl
Servers
         CGI, FastCGI, mod_perl1&2
  Standalone, Prefork, AnyEvent, Coro, POE,
Danga::Socket, nginx, mod_psgi, evhttpd, Perlbal
Frameworks
Catalyst, Mason, Maypole, CGI::Application, Jifty
 Dancer, HTTP::Engine, Sqauatting, Continuity
  WebGUI, Movable Type, Ark, Angelos, Noe
Middleware
Static, ConditionalGET, AccessLog, Chunked, Deflater,
    NYTProf, FCGIDispatcher, JSONP, StackTrace,
      Auth::Basic, XSendfile, Rewrite, JSConcat ...
Servers
         CGI, FastCGI, mod_perl1&2
  Standalone, Prefork, AnyEvent, Coro, POE,
Danga::Socket, nginx, mod_psgi, evhttpd, Perlbal
Non-blocking?
psgi.streaming
# delayed response
my $app = sub {
  my $env = shift;
  return sub {
   my $respond = shift;
   $respond->([ $status, $headers, $body ]);
};
# streaming content
my $app = sub {
  my $env = shift;
  return sub {
   my $respond = shift;
   my $w = $respond->([ $status, $headers ]);
   some_event_loop(sub {
     $w->write($content);
     $w->close;
   });
};
WARNING
         psgi.streaming is an interface
Servers may not work if event loop is not shared
  (Recommended to use AnyEvent in your app)
Frameworks?
Most frameworks do not
support non-blocking interface.
     (Mojo 0.99 has IOLoop and Client)
Let’s make one!
Tatsumaki

    http://www.flickr.com/photos/88699006@N00/679056142/
Port of Tornado
Plack and AnyEvent
   All the way from the bottom to the top
Handle thousands of connections with EV/epoll
Works with
AnyEvent, POE, Coro, Danga::Socket and perlbal
            Because it’s AnyEvent!
You can use
Any of AnyEvent::* libraries to do
asynchronous tasks (unlike Mojo)
The first and only framework
  that uses psgi.streaming
package MainHandler;
use base qw(Tatsumaki::Handler);

sub get {
  my $self = shift;
  $self->write(“Hello World”);
}

package main;
use Tatsumaki::Application;
my $app = Tatsumaki::Application->new([
   ‘/’ => ‘MainHandler’,
]);
Tatsumaki::HTTPClient
        AnyEvent::HTTP wrapper
  non-blocking HTTP client for Tatsumaki
package HTTPClientHandler;
use base qw(Tatsumaki::Handler);
__PACKAGE__->asynchronous(1);

use Tatsumaki::HTTPClient;

sub get {
  my $self = shift;
  my $client = Tatsumaki::HTTPClient->new;
  $client->get($api_url, sub {
      my $res = shift;
      my $body = $res->content;
      $self->write(...);
      $self->finish;
  });
}
Long-poll (comet)
package AsyncHandler;
use base qw(Tatsumaki::Handler);
__PACKAGE__->asynchronous(1);

sub get {
  my $self = shift;
  my $t; $t = AE::timer 3, 0, sub {
      undef $t;
      $self->write(“Hello World”);
      $self->finish;
  });
}

package main;
use Tatsumaki::Application;
my $app = Tatsumaki::Application->new([
   ‘/’ => ‘AsyncHandler’,
]);
Tatsumaki::MessageQueue
    Pure perl MQ (in AnyEvent)
package LongPollHandler;
use base qw(Tatsumaki::Handler);
__PACKAGE__->asynchronous(1);

use Tatsumaki::MessageQueue;

sub get {
  my $self = shift;
  my $mq = Tatsumaki::MessageQueue-
>instance(‘ch-name’);
  $mq->poll_once($client_id, sub {
      my @events = @_;
      $self->write(@events);
      $self->finish;
  });
}
package EventPostHandler;
use base qw(Tatsumaki::Handler);

sub post {
  my $self = shift;
  my $mq = Tatsumaki::MessageQueue-
>instance(‘ch-name’);
  $mq->publish({
      name => “NewComment”, ...
  });
  $self->write({ success => 1 });
}
Multipart XHR
JavaScript hack to emulate server push
package MXHRPollHandler;
use base qw(Tatsumaki::Handler);
__PACKAGE__->asynchronous(1);

use Tatsumaki::MessageQueue;

sub get {
  my $self = shift;
  $self->multipart_xhr_push(1);
  my $mq = Tatsumaki::MessageQueue-
>instance(‘ch-name’);
  $mq->poll($client_id, sub {
      my @events = @_;
      $self->stream_write(@events);
  });
}
JS Client libraries
       jquery.ev
      DUI.Stream
       raphaeljs
DEMO
http://192.168.100.50:5000/chat/demo
Other apps
            github.com/gugod/Social
        github.com/miyagawa/Subfeedr
         github.com/audreyt/socialcalc
github.com/clkao/Finance-GeniusTrader-Chart
          github.com/lestrrat/Hamaki
         github.com/yusukebe/Nagare
WHY
Web server resource
I/O bound
!CPU bound
I/O bound web apps
  HTTP API proxy (e.g. OpenSocial)
     Mash up (XML, REST API)
     Real-time Web (Comet)
CPU bound jobs
       Database Servers
 Job Workers (TheSchwartz etc.)
Tatsumaki for
I/O bound web
✓ Non-blocking HTTP client
 ✓ Pure perl Message Queue
 ✓ I/O libraries (AnyEvent::*)
✓ DB libraries (AnyEvent::DBI)
✓ Job dispatcher (AE::Gearman)
Status
 0.1.x on CPAN, considered beta
AnyEvent server has bugs on Linux
Plans
Tatsumaki::Service
Inspired by Google AppEngine Email/XMPP service
               Webhook pattern
XMPP/IRC
Write Jabber/IRC bot as a web application
# see Tatsumaki-Service-XMPP/eg/translate.psgi
package XMPPTranslateHandler;
use base qw(Tatsumaki::Handler::XMPP);

sub post {
  my $self = shift;
  my $msg = $self->xmpp_message;

    my $uri = “http://ajax.googleapis.com/...”;
    my $client = Tatsumaki::HTTPClient->new;
    $client->get($uri, $self->async_cb(sub {
      my $res = shift;
      my $r = JSON::decode_json($res->content);
      $msg->reply($r->{translatedText});
      $self->finish;
    }));
}
Standard Comet Interface
        a.k.a Stardust
Bayeux
HTTP push relay
“Real” PubSub interface
  for Tatsumaki::MQ
Pluggable MQ
using “real” MQ like ActiveMQ or RabbitMQ
DataStore interface
   using AnyEvent::DBI, Redis etc.
See Subfeedr
for Redis integration
  http://github.com/miyagawa/Subfeedr
cpan> install Tatsumaki
http://github.com/miyagawa/Tatsumaki
         irc://irc.perl.org/#plack
That’s it!
Questions?

More Related Content

What's hot

Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
som_nangia
 
Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
Tatsuhiko Miyagawa
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
Masahiro Nagano
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
Jeremy Kendall
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
diego_k
 

What's hot (20)

Modern Perl
Modern PerlModern Perl
Modern Perl
 
PSGI/Plack OSDC.TW
PSGI/Plack OSDC.TWPSGI/Plack OSDC.TW
PSGI/Plack OSDC.TW
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 
Plack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento web
 
Inside Bokete: Web Application with Mojolicious and others
Inside Bokete:  Web Application with Mojolicious and othersInside Bokete:  Web Application with Mojolicious and others
Inside Bokete: Web Application with Mojolicious and others
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
Developing apps using Perl
Developing apps using PerlDeveloping apps using Perl
Developing apps using Perl
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClient
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
Writing Pluggable Software
Writing Pluggable SoftwareWriting Pluggable Software
Writing Pluggable Software
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
About Data::ObjectDriver
About Data::ObjectDriverAbout Data::ObjectDriver
About Data::ObjectDriver
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 

Viewers also liked (7)

CPAN Realtime feed
CPAN Realtime feedCPAN Realtime feed
CPAN Realtime feed
 
No Hugging, No Learning
No Hugging, No LearningNo Hugging, No Learning
No Hugging, No Learning
 
ZeroMQ in PHP
ZeroMQ in PHPZeroMQ in PHP
ZeroMQ in PHP
 
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012
 
Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
 
Network Programming With Anyevent
Network Programming With AnyeventNetwork Programming With Anyevent
Network Programming With Anyevent
 
Carton CPAN dependency manager
Carton CPAN dependency managerCarton CPAN dependency manager
Carton CPAN dependency manager
 

Similar to Tatsumaki

Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
wilburlo
 
Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...
Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...
Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...
Gosuke Miyashita
 
Facebook的缓存系统
Facebook的缓存系统Facebook的缓存系统
Facebook的缓存系统
yiditushe
 
4069180 Caching Performance Lessons From Facebook
4069180 Caching Performance Lessons From Facebook4069180 Caching Performance Lessons From Facebook
4069180 Caching Performance Lessons From Facebook
guoqing75
 
Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門
lestrrat
 
Performance measurement and tuning
Performance measurement and tuningPerformance measurement and tuning
Performance measurement and tuning
AOE
 
Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
Kar Juan
 

Similar to Tatsumaki (20)

Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 
Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...
Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...
Yapc::Asia 2008 Tokyo - Easy system administration programming with a framewo...
 
How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server How to build a High Performance PSGI/Plack Server
How to build a High Performance PSGI/Plack Server
 
PHP, RabbitMQ, and You
PHP, RabbitMQ, and YouPHP, RabbitMQ, and You
PHP, RabbitMQ, and You
 
Facebook的缓存系统
Facebook的缓存系统Facebook的缓存系统
Facebook的缓存系统
 
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
 
Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
4069180 Caching Performance Lessons From Facebook
4069180 Caching Performance Lessons From Facebook4069180 Caching Performance Lessons From Facebook
4069180 Caching Performance Lessons From Facebook
 
Harmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and PuppetHarmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and Puppet
 
Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門
 
Performance measurement and tuning
Performance measurement and tuningPerformance measurement and tuning
Performance measurement and tuning
 
Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
What RabbitMQ can do for you (phpnw14 Uncon)
What RabbitMQ can do for you (phpnw14 Uncon)What RabbitMQ can do for you (phpnw14 Uncon)
What RabbitMQ can do for you (phpnw14 Uncon)
 

More from Tatsuhiko Miyagawa (14)

cpanminus at YAPC::NA 2010
cpanminus at YAPC::NA 2010cpanminus at YAPC::NA 2010
cpanminus at YAPC::NA 2010
 
Asynchronous programming with AnyEvent
Asynchronous programming with AnyEventAsynchronous programming with AnyEvent
Asynchronous programming with AnyEvent
 
Remedie OSDC.TW
Remedie OSDC.TWRemedie OSDC.TW
Remedie OSDC.TW
 
Why Open Matters It Pro Challenge 2008
Why Open Matters It Pro Challenge 2008Why Open Matters It Pro Challenge 2008
Why Open Matters It Pro Challenge 2008
 
20 modules i haven't yet talked about
20 modules i haven't yet talked about20 modules i haven't yet talked about
20 modules i haven't yet talked about
 
Web::Scraper for SF.pm LT
Web::Scraper for SF.pm LTWeb::Scraper for SF.pm LT
Web::Scraper for SF.pm LT
 
Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8
 
Web::Scraper
Web::ScraperWeb::Scraper
Web::Scraper
 
XML::Liberal
XML::LiberalXML::Liberal
XML::Liberal
 
Test::Base
Test::BaseTest::Base
Test::Base
 
Hacking Vox and Plagger
Hacking Vox and PlaggerHacking Vox and Plagger
Hacking Vox and Plagger
 
Plagger the duct tape of internet
Plagger the duct tape of internetPlagger the duct tape of internet
Plagger the duct tape of internet
 
Tilting Google Maps and MissileLauncher
Tilting Google Maps and MissileLauncherTilting Google Maps and MissileLauncher
Tilting Google Maps and MissileLauncher
 
How we build Vox
How we build VoxHow we build Vox
How we build Vox
 

Recently uploaded

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Recently uploaded (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Decarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceDecarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational Performance
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern Enterprise
 
Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation Computing
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
 

Tatsumaki